python的类变量属于类(class),在所有此类生产的objects(或instances)中共享此变量。简单来说,类的对象可以有很多,但是类变量共享一个。

>>> class person():
... count = 0
... def __init__(self, age):
... self.age = age
... person.count += 1
...
>>>
>>> p1 = person(12)
>>> person.count
1
>>> p2 = person(34)
>>> person.count
2
>>>
>>> person.count = 9
>>> person.count
9
>>> p3 = person(56)
>>> person.count
10
>>> p1.count
10
>>> p2.count
10
>>> p3.count
10

person class中的count就是一个类变量,class variable。下面生成的三个对象p1,p2,p3,都会影响到person.count的值。直接修改person.count的值,通过对象访问类变量(不建议这样使用),可以看出每个对象引用的count,就是一个count。

访问class variable

阅读上面的示例代码,出现了两种访问class variable的方式,一种是通过class name,person.count,一种是通过对象,p1.count,p2.count......

推荐大家使用类名来访问类变量,即使用class.variable的方式来访问,不推荐使用object.class_variable的方式来访问。为什么呢?请看下面的示例代码:

>>> p1.count = 123
>>> p1.count
123
>>> p2.count
10
>>> p3.count
10
>>> person.count
10

各位看出来发生了什么吗?为什么再使用p1.count的时候,返回的值是123,而不再是10了呢?

因为,对于p1来说,count已经变成了它的instance variable,使用p1.count,不再是访问person.count,而是访问p1自己的一个实例变量。

>>> id(p1.count)
94278636975936
>>> id(p2.count)
94278636972320
>>> id(p3.count)
94278636972320
>>> id(person.count)
94278636972320
>>> getattr(p2, 'count')
10
>>> getattr(p3, 'count')
10
>>> getattr(p1, 'count')
123
>>> getattr(person, 'count')
10

看吧,就是p1.count的地址更大家不一样。因此,不要使用对象来访问类变量,因为有可能你不知道你访问的都是是类变量还是对象变量。

(不要)删除class variable

跟实例变量一样,类变量也可以删除,使用del语句。但是跟实例变量不一样的地方是,类变量是在类定义的时候添加的,如果删除,没有地方再添加了,而且会导致创建新的实例失败。

>>> del person.count
>>> person.count
Traceback (most recent call last):
File "", line 1, in 
AttributeError: type object 'person' has no attribute 'count'
>>> p1.count # instance variable
123
>>> p2.count
Traceback (most recent call last):
File "", line 1, in 
AttributeError: 'person' object has no attribute 'count'
>>> p4 = person(78) # create new object failed
Traceback (most recent call last):
File "", line 1, in 
File "", line 5, in __init__
AttributeError: type object 'person' has no attribute 'count'

p1对象的count,在上文已经修改为指向自己的实例变量,所以还可以访问。而p2对count的访问已经失败了,再创建p4,也是失败,因为__init__函数中有对class varibale count的操作。

class所包含的代码,在python中形成一个class namespace(还有function namespace,module namespace,global namespace),当python解释器遇到class之后,引入其中的代码的时候,本质上就是一顿执行。这样就可以理解为什么del语句可以删除一个class variable了。

>>> class codeinclass():
... for i in range(10): print(i)
...
0
1
2
3
4
5
6
7
8
9
>>> cic = codeinclass()
>>> cic
<__main__.codeinclass object at 0x7fc73001e358>

定义一个class,这个class中只有一个for循环,python解释器直接执行了这段代码,仅留下class name,还可以用来创建object。

-- EOF --