实例是具象化的类,它可以作为类访问所有静态绑定到类上的属性,包括类变量与方法,也可以作为实例访问动态绑定到实例上的属性。
实例1:
1 class A: 2 work = list("hello") 3 kind = list("world") 4 another = 1 5 6 def test1(self): 7 print(self.work, self.kind, self.another) 8 self.work[0], self.kind [0] = "t", "t" 9 self.another += 1 10 print(A.work, A.kind, A.another) 11 12 if __name__ == "__main__": 13 a = A() 14 a.test1()
输出结果:
1 [‘h‘, ‘e‘, ‘l‘, ‘l‘, ‘o‘] [‘w‘, ‘o‘, ‘r‘, ‘l‘, ‘d‘] 1 2 [‘t‘, ‘e‘, ‘l‘, ‘l‘, ‘o‘] [‘t‘, ‘o‘, ‘r‘, ‘l‘, ‘d‘] 1
test1中演示了实例对类变量的访问与修改,从输出结果可以看到,类变量work和kind的列表被修改了,而another的值没有发生变化,说明如果类变量是可变的,那么可以通过实例来对类变量进行修改,如果类变量不可变,那么实例无法修改类变量。
实例2:
1 class A: 2 work = list("hello") 3 kind = list("world") 4 another = 1 5 6 def test2(self): 7 A.work, A.kind = "hello", " world" 8 A.another += 2 9 print(self.__dict__) 10 print(self.work, self.kind, self.another) 11 A.test2 = 13 12 print(self.test2) 13 14 if __name__ == "__main__": 15 a = A() 16 a.test2()
输出结果:
1 {‘another‘: 2} 2 hello world 2 3 13
test2说明了实例访问类变量与方法的机制,在test1中,已经给实例动态绑定了一个another的属性,值为2(因为有赋值语句)。在self.__dict__中可以看到确实出现了实例属性another。
在使用实例访问属性(变量与方法)时,如果在实例的属性集里没有找到对应的属性,那么就会到类的属性集里找对应的属性。self.work和self.kind和类变量保持一致,说明并没有事先在实例与类变量之间建立引用,而是动态查找的。
1 class A: 2 work = list("hello") 3 kind = list("world") 4 another = 1 5 6 def test3(self): 7 print(self.__dict__) 8 self.w, self.k = 0, 1 9 print(self.__dict__) 10 self.work, self.kind = 4, 4 11 print(self.__dict__) 12 self.test1 = 12 13 print(self.__dict__) 14 try: 15 self.test1() 16 except: 17 print("test1 is not a bound method") 18 19 if __name__ == "__main__": 20 a = A() 21 a.test3()
输出结果:
1 {‘another‘: 2} 2 {‘another‘: 2, ‘w‘: 0, ‘k‘: 1} 3 {‘another‘: 2, ‘w‘: 0, ‘k‘: 1, ‘work‘: 4, ‘kind‘: 4} 4 {‘another‘: 2, ‘w‘: 0, ‘k‘: 1, ‘work‘: 4, ‘kind‘: 4, ‘test1‘: 12} 5 test1 is not a bound method
self.__dict__中保存了动态绑定到实例的变量与方法,只要出现了赋值语句,都是动态绑定属性。如果动态绑定的属性与类的变量或方法同名,在查找过程中就会覆盖类的变量和方法。
总结
1. 动态绑定到实例的属性位于self.__dict__中
2. 出现self.attribute = XXX之类的赋值语句都是在往实例上动态绑定属性
3. 实例查找属性的流程:self.work -> self.__dict__["work"] or cls.work,这是一个动态的过程,实例中的同名属性会覆盖类变量或方法,类变量或方法的修改会实时影响实例查找属性的结果
4. 如果类变量是可修改的,如列表,字典等,可以通过实例来修改类变量,方法是不可修改的,故无法通过实例修改方法
原文地址:https://www.cnblogs.com/luoheng23/p/10988942.html