感觉这种理解有问题,举个例子来说。
class Dog(object): name = 'dog' def init(self): self.age = 18
d1 = Dog() d2 = Dog()
这里有两个实例 d1,d2 吧。
d1.name # 输出 dog
d2.name # 输出 dog
d1.name = 'abc'
d1.name # 输出 abc
d2.name # 输出 dog
Dog.name # 输出 dog
原因是 d1.name 输出 dog 不是因为这个实例共享了类属性,而是因为这个实例没有 dog 属性,所以 python 查找了类属性。 但是一旦你修改了 d1.name 相当于给 d1 实例绑定了 name 属性之后,d1.name 就与类属性无关了。 既然这样就谈不上实例之间共享类属性了,因为只要一赋值,就相当于绑定了属性,则上述 d1.name 的含义和 d2.name 的含义就不同了,它们的值也不同,很明显它们的数据没有共享。
有点类似加static的味道,可以理解为加static。我的理解是作用域在一个类,相同类的都能访问,但是如果自己有实例变量了而且还同名的,那自然优先访问自己的实例变量,不过教程也建议了,自己的实例变量不要和类属性同名,以免删除实例变量之后访问类变量而造成问题
@TeCHiScy 写得很不错,但是要修改类属性,应该用
Dog.name = 'new name'
而不应该是
dog1.name = 'new name'
因为实例属性同名而覆盖类属性,的确是一个很容易忽视、出错的地方。
我觉得@TeCHiScy 说的和我理解的有一点不一样,我的理解,类属性就相当于static属性,只是python没有static关键字而已,你所为的
d1.name = 'abc'
之后,
d1.name # 输出'abc'
是因为你把name属性动态绑定给d1的实例了,那么按照查找顺序来说相当于把Dog的name属性给屏蔽了,其作用类似于:
Class Dog(object):
name='dog'
def __init__(self):
name='abc'
的作用。 而类的属性并没有改变,这和static的设计原则是符合的,以此类推,可以使用类属性写出类似static成员变量的objectCounter的代码:
class Base(object):
# private class attr. ## use Base._Base__counter to visit
__counter=0
def __init__(self):
Base.__counter+=1
self.__name="base"
# Return object counter
def getCounter(self):
return Base.__counter
class Derived(Base):
def __init__(self):
Base.__init__(self)
self.__name="Derived"
这时:
# Main function
if __name__ == '__main__':
a = Derived()
b = Derived()
print(b.getCounter())
返回的是2 这就和static成员变量的设计原则一致,因此我觉得楼主说的有一定正确性。而@TeCHiScy的理解有点问题
- 1
叫小小兽
类属性不就是static属性么,所有的实例都共享这个类属性