python 中更新实例变量的正确 OOP 方法是什么

what is the correct OOP method updating instance variables in python

我有两个 类 需要 app_config(在我的例子中 app_config 应该在我项目中的所有 类 中全局可用)。

Class1 需要 app_config,它提供了一些我需要在 app_config 中再次更新的输入,就像在 class2 中一样。

稍后我需要在 类 1 和 2 中更新 app_config。

什么是更新实例变量的正确方法。我做得对还是我需要换个角度考虑?

import requests 
app_config = {
    "MaxThreadCount": 10,
    "BaseURL": "https://google.com",
    "DB": "some db ip"
}

class Class1():
    def __init__(self, app_config):
        self.app_config = app_config
    
    def get_few_more_configs_in_class1(self):
        var1 = requests.get(self.app_config["BaseURL"])
        print("get few data")
        return {"class-1": "some inputs"}

    def set_appconfig(self, app_config):
        self.app_config = app_config

class Class2():
    def __init__(self, app_config):
        self.app_config = app_config
    
    def gather_few_more_configs_in_class2(self, inputs_from_class1):
        print("connect to db")
        return {"db-inputs": "some more inpus"}
    
    def set_appconfig(self, app_config):
        self.app_config = app_config

c1 = Class1(app_config=app_config)
c2 = Class2(app_config=app_config)
class1_inputs = c1.get_few_more_configs_in_class1()
class2_inputs = c2.gather_few_more_configs_in_class2(class1_inputs)
app_config.update(class1_inputs)
app_config.update(class2_inputs)

c1.set_appconfig(app_config=app_config)
c2.set_appconfig(app_config=app_config)

        

这里有一些更有意义的变化:

import requests

app_config = {
    "MaxThreadCount": 10,
    "BaseURL": "https://google.com",
    "DB": "some db ip"
}


class Class1():
    def __init__(self, cfg):  # you want to avoid shadowing something global
        # since you have a setter, discourage direct access
        self._cfg = cfg  

    def get_few_more_configs_in_class1(self):
        var1 = requests.get(self.app_config["BaseURL"])
        print("get few data")
        # no need to update after return, just update directly
        self._cfg.update({"class-1": "some inputs"})
    
    # this is a better way to expose and allow setting, with a property
    @property
    def app_config(self):
        return self._cfg
    
    @app_config.setter
    def app_config(self, cfg):
        self._cfg = cfg


class Class2():
    def __init__(self, cfg):
        self._cfg = cfg

    def gather_few_more_configs_in_class2(self):
        print("connect to db")
        # here, you can use whatever was previously set in your `app_config`
        print("using", self._cfg['class-1'])
        self._cfg.update({"db-inputs": "some more inpus"})

    # this is a better way to expose and allow setting, with a property
    @property
    def app_config(self):
        return self._cfg

    @app_config.setter
    def app_config(self, cfg):
        self._cfg = cfg


c1 = Class1(app_config)
c2 = Class2(app_config)

c1.get_few_more_configs_in_class1()
# no need to pass stuff in, already has the config
c2.gather_few_more_configs_in_class2()  

但是,既然您显然想将 app_config 用作共享应用程序 state,或许可以这样称呼它?通常最好避免使用全局变量,因此您可以在 main() 中进行设置。最后,如果您有多个具有相同逻辑的 类,为什么不使用继承?

import requests


class StateSharing:
    def __init__(self, state: dict):
        self._state = state

    @property
    def state(self) -> dict:
        return self._state

    @state.setter
    def state(self, state: dict):
        self._state = state


class Class1(StateSharing):
    def get_few_more_configs_in_class1(self):
        requests.get(self.state["BaseURL"])
        print("get few data")
        self._state.update({"class-1": "some inputs"})


class Class2(StateSharing):
    def __init__(self, state: dict, something_else: str):
        super().__init__(state)
        self.something_else = something_else

    def gather_few_more_configs_in_class2(self):
        print("connect to db")
        print("using", self._state['class-1'])
        self._state.update({"db-inputs": "some more inpus"})


def main():
    state = {
        "MaxThreadCount": 10,
        "BaseURL": "https://google.com",
        "DB": "some db ip"
    }
    c1 = Class1(state)
    c2 = Class2(state, 'something!')

    c1.get_few_more_configs_in_class1()
    c2.gather_few_more_configs_in_class2()


if __name__ == '__main__':
    main()