为什么字典内容在类实例之间共享,但字符串不共享?
测试代码:
class Config(object):
file_names = dict()
file_name_1 = None
file_name_2 = None
def __init__(self):
if not self.file_names:
print "DEBUG: Config(): set initial values"
self.file_names["0"] = None
self.file_names["1"] = None
def set_file_names(self, file_names):
self.file_name_1 = file_names[0]
self.file_names["0"] = file_names[0]
self.file_name_2 = file_names[1]
self.file_names["1"] = file_names[1]
class CommandLineParser(object):
def __init__(self):
self.cfg = Config()
self.start()
def start(self):
self.cfg.set_file_names(("file_1.log", "file_2.log"))
print self.__class__.__name__, "FileName1 (str) :", self.cfg.file_name_1
print self.__class__.__name__, "FileName1 (dict):", self.cfg.file_names["0"]
class LogProcessor(object):
def __init__(self):
self.cfg = Config()
self.cmdln = CommandLineParser()
print self.__class__.__name__, "FileName1 (str) :", self.cfg.file_name_1
print self.__class__.__name__, "FileName1 (dict):", self.cfg.file_names["0"]
if __name__ == '__main__':
processor = LogProcessor()
输出:
DEBUG: Config(): set initial values
CommandLineParser FileName1 (str) : file_1.log
CommandLineParser FileName1 (dict): file_1.log
LogProcessor FileName1 (str) : None
LogProcessor FileName1 (dict): file_1.log
在字典属性中实例之间共享选项是否正确?
答案 0 :(得分:3)
files_names
是类Config
的类属性,因此它由此类的所有实例共享。 file_name_1
和file_name_2
最初也是类属性(设置为None
),但您在set_file_names
方法中的实例中重新绑定它们,因此它们成为实例属性,对每个实例都是私有的,那个时候。
您的想法是使用一个类属性,它是一个可变容器(dict
),包含所有实例共有的配置,并且可以动态更新。
如果您仍想使用单个字符串属性file_name_1
和file_name_2
,但希望在所有实例之间共享它们,则可以执行以下操作之一:
set_file_names
代替Config.file_name_1 = whatever
self.file_name_1 = whatever
中创建实例属性
set_file_names
方法成为类方法(使用@classmethod
装饰器),以便它可以在类上运行,而不是在实例上运行。Config
代替Config()
。答案 1 :(得分:2)
虽然我不确定在你的情况下Config是否需要单例,但是将dict配置为一个Config实例的方法可能是:
class Config(object):
file_names = None
file_name_1 = None
file_name_2 = None
def __init__(self):
if self.file_names is None:
self.file_names = dict()
...
但是,我坚信它是一个更好的设计,只在您的应用程序中实例化一次Config并传递实例:
class CommandLineParser(object):
def __init__(self, config):
self.cfg = config
self.start()
从更一般的角度来说,最好明确地传递上下文信息。