我通常声明在Python中的实例中使用的类变量的方式如下:
class MyClass(object):
def __init__(self):
self.a_member = 0
my_object = MyClass()
my_object.a_member # evaluates to 0
Run Code Online (Sandbox Code Playgroud)
但以下也有效.这是不好的做法吗?如果是这样,为什么?
class MyClass(object):
a_member = 0
my_object = MyClass()
my_object.a_member # also evaluates to 0
Run Code Online (Sandbox Code Playgroud)
第二种方法在Zope上使用,但我还没有在其他任何地方看到它.这是为什么?
编辑:作为对sr2222答案的回应.我知道这两者本质上是不同的.但是,如果该类仅用于实例化对象,则两者将以相同的方式工作.那么使用类变量作为实例变量是不是很糟糕?感觉就像是,但我无法解释原因.
问题是这是属于类本身还是特定对象的属性.如果整个类具有某个属性(可能有少量例外),那么无论如何都要在类上分配一个属性.如果某个奇怪的对象或子类在此属性中不同,则可以根据需要覆盖它.而且,这比为每个对象分配一个基本上恒定的属性更具内存效率; 只有该类__dict__具有该属性的单个条目,并且__dict__每个对象的每个对象可以保持为空(至少对于该特定属性).
简而言之,您的两个示例都是非常惯用的代码,但它们在机器级别和人类语义级别上都意味着不同的东西.
让我解释一下:
>>> class MyClass(object):
... a_member = 'a'
...
>>> o = MyClass()
>>> p = MyClass()
>>> o.a_member
'a'
>>> p.a_member
'a'
>>> o.a_member = 'b'
>>> p.a_member
'a'
Run Code Online (Sandbox Code Playgroud)
在第二行,您正在设置"类属性".这是一个名为"MyClass"的对象的属性.它存储为MyClass.__dict__['a_member'] = 'a'.在后面的行中,您将对象属性o.a_member设置为.这完全等同于o.__dict__['a_member'] = 'b'.你可以看到这与单独的字典无关p.__dict__.访问a_memberp时,在对象字典中找不到它,并推迟到它的类字典:MyClass.a_member.这就是为什么修改属性o不会影响属性p,因为它不会影响属性MyClass.