为什么猴子补丁方法不传实例引用?
这里有一个示例来演示:
>>> class M:
def __init__(self): self.x = 4
>>> sample = M()
>>> def test(self):
print(self.x)
>>> sample.test = test
>>> sample.test()
Traceback (most recent call last):
File "<pyshell#17>", line 1, in <module>
sample.test()
TypeError: test() missing 1 required positional argument: 'self'
为什么呢?
2 个回答
2
函数其实和其他对象一样,都是对象。无论这些对象的名字在哪里(比如在本地命名空间里,或者作为某个对象的属性),它们的赋值过程都应该保持一致。
当你用 def
来定义一个函数时,你就是把这个函数和 def
后面的名字绑定在一起。而当你做类似 some_object.f = my_function
的赋值时,你也是在把这个函数和一个名字绑定在一起。这个赋值过程没有什么神奇之处,它不会改变函数的本质。
不过,在类定义的过程中确实有一些特别的地方。作为实例方法定义的函数(也就是在类定义内部定义的函数),并不是简单地作为属性赋值给实例,而是通过一种叫做 描述符 的机制来绑定到实例上。
18
你给 sample.test
赋值的 test
方法并没有和 sample
这个对象绑定在一起。你需要手动把它绑定,像这样做:
import types
sample.test = types.MethodType(test, sample)
sample.test()
# 4