我通常在 Python 中声明要在实例中使用的类变量的方式如下:
class MyClass(object):
def __init__(self):
self.a_member = 0
my_object = MyClass()
my_object.a_member # evaluates to 0
但以下也有效。这是不好的做法吗?如果是,为什么?
class MyClass(object):
a_member = 0
my_object = MyClass()
my_object.a_member # also evaluates to 0
第二种方法在整个 Zope 中都被使用,但我没有在其他任何地方看到它。这是为什么?
编辑:作为对 sr2222 回答的回应。我明白这两者本质上是不同的。但是,如果该类仅用于实例化对象,则两者将以相同的方式工作。那么将类变量用作实例变量不好吗?感觉就像是,但我无法解释为什么。
请您参考如下方法:
问题是这是类本身的属性还是特定对象的属性。如果整个类别的事物都具有某个属性(可能有一些小的异常(exception)),那么一定要为该类别分配一个属性。如果一些奇怪的对象或子类在此属性上有所不同,则可以根据需要覆盖它。此外,这比为每个对象分配一个基本不变的属性更节省内存;只有类的 __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'
在第二行,您要设置“类属性”。这实际上是名为“MyClass”的对象的一个属性。它存储为 MyClass.__dict__['a_member'] = 'a'。在后面几行中,您将 object 属性 o.a_member 设置为。这完全等同于 o.__dict__['a_member'] = 'b'。可以看到这和p.__dict__这个单独的字典没有关系。当访问 p 的 a_member 时,在对象字典中找不到它,并延迟到它的类字典:MyClass.a_member。这就是为什么修改o的属性不会影响p的属性,因为它不会影响MyClass的属性。
