使用类属性为您打算成为特定于实例的数据提供默认值的主要缺点是,默认值将在类的所有实例之间共享,直到值被更改。例如:
class Foo(object):
a = []
foo1 = Foo()
foo2 = Foo()
foo1.a.append(123)
foo1.a # [123]
foo2.a # [123]
但是,以下将按预期工作:
class Bar(object):
a = 123
bar1 = Bar()
bar2 = Bar()
bar1.a = 456
bar2.a # 123
为避免在使用此技术时出现此问题,您应该只使用它来设置不可变值的默认值。(例如数字、字符串、元组……)
Python 以这种方式运行的原因是,当您使用以下命令访问属性时:
foo.bar
然后bar
是先在对象中查找foo
。如果在对象中找不到名称 in (即 in foo.__dict__
),则在该对象的类型中查找名称。例如,这种机制是方法查找工作方式的一部分。(如果您查看__dict__
对象的 ,您会注意到它的方法不存在。)
其他小问题是,当它们打算特定于实例时,这会通过类型对象公开默认值;并且如果您有任何默认值,它将混合特定于类的属性(如常量)的定义。前者的推论是,这将允许您稍后通过分配给类属性为尚未更改值的所有对象重新定义默认值。(这可能有用,也可能令人困惑;对可变“全局”变量的预防措施同样适用。)