为什么通过动态绑定类的实例方法,不能修改实例属性?
Topic source我实验了一下分别利用 t.score
和 t.set_score()
赋值,用 t.score
和 t.get_score()
获取结果,结果显示:
t.score
和 t.set_score()
赋值互不影响, t.score
的改变不会影响 t.get_score()
结果, t.set_score()
赋值不改变 t.score
结果
因为属性和方法是不一样的。属性是变量,方法是函数,但是由于变量也可以是函数,因此具有迷惑性。区别方法是调用方法时不需要给self传参,而调用函数属性时则需要。
利用MethodType添加的是方法,Student是定义的类,同时也是type类的实例(python中类也是对象),因此你实际上给Student这一type类的实例添加了方法set_score。但是,只有给Student添加属性,才能给Student的实例添加方法,因此要用Student.set_score=set_score来给Student的实例添加方法。
Student.set_score = MethodType(set_score, Student)
Student.get_score = MethodType(get_score, Student)
没见过这种写法啊,如果这种写法作用真如他们说的那样:为类绑定了一个方法。那么同时也会为类新增一个score属性。
而实例也有score属性,实力的属性优先级要高于类,当用类调用score属性时,即Student.score,就会打印100.当用实例调用score属性时就会打印80.
看不懂前面的解释,但是可以试并且猜一下是MethodType的问题:
因为`MethodType(f, x)`的第二个参数x,实际就是以后执行 f 时代入的self。
比如:
from types import MethodType
class Student:
pass
A=Student()
B=Student()
def f(self, x):
self.x = x
B.f = MethodType(f, A)
B.f(555)
print(A.x) # 555
print(B.x) # AttributeError: 'Student' object has no attribute 'x'
此时调用 B.f(555),等价于运行 f(A, 555),即 A.x = 555,但B本身依旧没有x
类也同理
def set_score(self, score):
self.score = score
Student.set_score = MethodType(set_score, Student)
A.score = 80
A.set_score(50)
print(A.score) # 80
print(Student.score) # 50
确实是弄了个类方法,但调用A.set_score(50),等价于运行 set_score(Student, 50),即 Student.score = 50,对A没有影响,影响的是Student本身的类属性
问题在这里:
Student.set_score = MethodType(set_score, Student)
Student.get_score = MethodType(get_score, Student)
改这样就没问题了:
Student.set_score = set_score
Student.get_score = get_score
- 1
- 2
你曾温润如玉