以下看起来很奇怪..基本上,somedata属性似乎在所有继承的类之间共享the_base_class
.
class the_base_class: somedata = {} somedata['was_false_in_base'] = False class subclassthing(the_base_class): def __init__(self): print self.somedata first = subclassthing() {'was_false_in_base': False} first.somedata['was_false_in_base'] = True second = subclassthing() {'was_false_in_base': True} >>> del first >>> del second >>> third = subclassthing() {'was_false_in_base': True}
self.somedata
在__init__
函数中定义显然是解决这个问题的正确方法(所以每个类都有它自己的somedata
dict) - 但什么时候这种行为是可取的?
你是对的,somedata
在类的所有实例和它的子类之间共享,因为它是在类定义时创建的.线条
somedata = {} somedata['was_false_in_base'] = False
在定义类时执行,即当解释器遇到class
语句时 - 而不是在创建实例时(在Java中考虑静态初始化程序块).如果类实例中不存在属性,则会检查类对象的属性.
在类定义时,您可以运行arbritrary代码,如下所示:
import sys class Test(object): if sys.platform == "linux2": def hello(self): print "Hello Linux" else: def hello(self): print "Hello ~Linux"
在Linux系统上,Test().hello()
将打印Hello Linux
,在所有其他系统上将打印另一个字符串.
相反,对象in __init__
在实例化时创建并且仅属于实例(当它们被分配时self
):
class Test(object): def __init__(self): self.inst_var = [1, 2, 3]
在类对象而不是实例上定义的对象在许多情况下都很有用.例如,您可能希望缓存类的实例,以便可以共享具有相同成员值的实例(假设它们应该是不可变的):
class SomeClass(object): __instances__ = {} def __new__(cls, v1, v2, v3): try: return cls.__insts__[(v1, v2, v3)] except KeyError: return cls.__insts__.setdefault( (v1, v2, v3), object.__new__(cls, v1, v2, v3))
大多数情况下,我将类体中的数据与元类或通用工厂方法结合使用.
请注意,您所看到的部分行为是由于somedata
是a dict
,而不是简单的数据类型,如a bool
.
例如,请看这个行为不同的不同示例(尽管非常相似):
class the_base_class: somedata = False class subclassthing(the_base_class): def __init__(self): print self.somedata >>> first = subclassthing() False >>> first.somedata = True >>> print first.somedata True >>> second = subclassthing() False >>> print first.somedata True >>> del first >>> del second >>> third = subclassthing() False
本实施例中从在问题给出的行为不同的原因是因为在这里first.somedata
被给定一个新的值(对象True
),而在第一个例子中通过引用的字典对象first.somedata
(并且还通过其他子类实例)被修改.
有关进一步说明,请参阅Torsten Marek对此答案的评论.