一. python的类属性与实例属性的注意点
1 class TestAtt(): 2 aaa = 10 3 4 def main(): 5 # case 1 6 obj1 = TestAtt() 7 obj2 = TestAtt() 8 print obj1.aaa, obj2.aaa, TestAtt.aaa 9 10 # case 2 11 obj1.aaa += 1 12 print obj1.aaa, obj2.aaa, TestAtt.aaa 13 14 # case 3 15 TestAtt.aaa += 2 16 print obj1.aaa, obj2.aaa, TestAtt.aaa 17 18 if __name__ == ‘__main__‘: 19 main()
一段示例代码,一个类TestAtt只有一个类对象,然后通过改变其不同对象的属性和类的属性,结果如下:
改变的似乎挺特殊,分析原因如下:
python中的属性获取机制,是从底层的对象到上层中一点点找的;在第一次获取obj1.aaa, obj2.aaa的时候,因为这个类并没有初始化实例的属性,所以其实obj1和obj2并没有aaa这个属性,所以实质上obj1.aaa, obj2.aaa都是TestAtt.aaa。
而对于 case2,obj1.aaa += 1这个操作实际上是给obj1这个实例创建了aaa的属性(以TestAtt.aaa的值再加1),所以从case2来看它的值就单独改变了,而且在case3中也没再受到影响。
现在我把代码修改如下再运行下结果,打印出每个实例的__dict__:
1 def main(): 2 # case 1 3 obj1 = TestAtt() 4 obj2 = TestAtt() 5 print obj1.aaa, obj2.aaa, TestAtt.aaa 6 print obj1.__dict__ 7 print obj2.__dict__ 8 9 # case 2 10 obj1.aaa += 1 11 print obj1.aaa, obj2.aaa, TestAtt.aaa 12 print obj1.__dict__ 13 print obj2.__dict__ 14 15 # case 3 16 TestAtt.aaa += 2 17 print obj1.aaa, obj2.aaa, TestAtt.aaa 18 print obj1.__dict__ 19 print obj2.__dict__
这样看就很明显,可以证明上述的情况。
二. python多重继承注意点:
在python2.7里面有经典类和新式类之分,前者定义时没有明式的继承,后者会继承object类。
在多重继承后寻找属性的时候,二者的行为有一个明显的区别:
经典类是深度优先地搜索——会在条继承链上线搜索到底,再到下一个优先级的继承链上搜索,以此类推。
形式类是广度优先地搜索——在同一代际的继承者们之间按照优先级水平搜索,这一代际搜索不到,再向更上层的父辈里寻找,一次类推。
示例代码如下:
1 class A(object): 2 def foo(self): 3 print "class A" 4 5 class A1(): 6 def foo(self): 7 print "class A1" 8 9 class C(A): 10 pass 11 12 class C1(A1): 13 pass 14 15 class D(A): 16 def foo(self): 17 print "class D" 18 19 class D1(A1): 20 def foo(self): 21 print "class D1" 22 23 class E(C, D): 24 pass 25 26 class E1(C1, D1): 27 pass 28 29 e = E() 30 e.foo() 31 32 e1 = E1() 33 e1.foo()
这里字母后带数字的是经典类,不带的是新式类,然后我们运行一下结果:
证明了上面的说法。
但是我们看看在python3中的表现,一样的代码结果如下:
所以在python3中,其实并没有所谓经典类和形式类的区别了,而且多重继承的顺序统一为深度优先了。
时间: 2024-12-22 08:19:10