Python 类属性和对象属性

摘自:http://python.jobbole.com/85100/

示例:

class AAA():  
    aaa = 10  
 
# 情形1   
obj1 = AAA()  
obj2 = AAA()   
print obj1.aaa, obj2.aaa, AAA.aaa
 
# 情形2  
obj1.aaa += 2  
print obj1.aaa, obj2.aaa, AAA.aaa
 
# 情形3  
AAA.aaa += 3  
print obj1.aaa, obj2.aaa, AAA.aaa

结果:

    情形1: 10 10 10

    情形2: 12 10 10

    情形3: 12 13 13

Python中类属性的含义

Python属于动态强类型的语言,在很多地方和C++/Java这种静态语言不同,因此,不能把静态语言的规则套到动态语言上来。其中,类属性就是一个很好的例子。

类属性相当于Java中的 static 变量:public static String aaa = ""

Python中属性的获取
对于属性,我们通常采用类.属性实例.属性的形式调用。

例如上例中的AAA.aaa属于类.属性形式,obj1.aaa属于实例.属性的形式

Python中属性的设置
对于属性的设置我们通常采用 类.属性 = 值实例.属性 = 值的形式
例如 obj1.aaa = 3

上例中obj1.aaa += 2等价于obj1.aaa = obj1.aaa + 2,这句话包含了属性获取属性设置两个操作

OK,重点来了,Python中属性的获取和设置的机制与静态语言是不同的,正是背后机制的不同,导致了Python中类属性不一定是为其实例所共享的

Python中属性查找机制

Python中属性的获取存在一个向上查找机制,还是拿上面的例子做说明:

Python中一切皆对象,AAA属于类对象obj1属于实例对象,从对象的角度来看,AAAobj1是两个无关的对象,但是,Python通过下面的查找树建立了类对象AAA与实例对象obj1obj2之间的关系。

        AAA
         |
       -----
      |     |  
    obj1   obj2

当调用AAA.aaa时,直接从AAA获取其属性aaa
但是情形1中调用obj1.aaa时,Python按照从obj1AAA的顺序由下到上查找属性aaa
值得注意的这时候obj1是没有属性aaa,于是,Python到类AAA中去查找,成功找到,并显示出来。所以,从现象上来看,AAA的属性aaa确实是共享给其所有实例的,虽然这里只是从查找树的形式模拟了其关系。

Python中的属性设置

原帖子的作者也指出问题的关键在于情形2中obj1.aaa += 2
为什么呢?
上面我们指出obj.aaa += 2包含了属性获取属性设置两个操作。即obj1.aaa += 2等价于obj1.aaa = obj1.aaa + 2
其中等式右侧的obj.aaa属于属性获取,其规则是按照上面提到的查找规则进行,即,这时候,获取到的是AAA的属性aaa,所以等式左侧的值为12
第二个操作是属性设置,即obj.aaa = 12当发生属性设置的时候,obj1这个实例对象没有属性aaa,因此会为自身动态添加一个属性aaa
由于从对象的角度,类对象和实例对象属于两个独立的对象,所以,这个aaa属性只属于obj1,也就是说,这时候类对象AAA和实例对象aaa各自有一个属性aaa
那么,在情形3中,再次调用obj1.aaa时,按照属性调用查找规则,这个时候获取到的是实例对象obj1的属性aaa,而不是类对象AAA的属性aaa

对问题探讨的总结

到这里就可以完满解释上面的问题:
1. Python中属性的获取是按照从下到上的顺序来查找属性;
2. Python中的类和实例是两个完全独立的对象;
3. Python中的属性设置是针对对象本身进行的;

对情形1的解释

因为Python中的属性获取是按照从下到上的顺序来查找的,所以在情形1:

实例对象obj1obj2不存在属性aaa
证明如下:

所以,此时,obj1.aaa, obj2.aaa, AAA.aaa实质上都是指AAA.aaa。因此,输出同样的结果。


对情形2的解释

因为Python中的类和实例是两个完全独立的对象Python中的属性设置是针对对象本身进行的,所以在情形2:

实质上是对实例对象obj1设置了属性aaa,并赋值为12。证明如下:

因此,再次调用obj1.aaa时,将获取到的是实例对象obj1的属性aaa,而不是类对象AAA的属性aaa。而对于实例对象obj2,由于其并没有属性aaa,所以调用obj2.aaa时,获取到的是AAA的属性aaa

对情形3的解释

顺利理解了前两个情形,那么第3个情形就很容易了,改变AAA的属性aaa只能影响到类对象AAA和实例对象obj2,不能影响obj1,因为,obj1存在aaa,在获取时,不会获取到AAA的属性。


猜你喜欢

转载自blog.csdn.net/shihongji/article/details/80221645