gpt4 book ai didi

python - 你能解释一下为什么改变类的函数属性会产生以下效果吗?

转载 作者:行者123 更新时间:2023-12-01 02:24:35 26 4
gpt4 key购买 nike

考虑下面的代码:

class A:
def __init__(self, data):
self.data = data

def f(self):
print('from A', self.data)

a = A(20)

def fnew(self):
print('new from A', self.data)

A.f = fnew
print(a.f.__func__ is A.f)

输出是 True,但我预计它是 false。原因如下:据我了解,每次从类 C 创建对象 O 时,它都会以“method”类型的对象形式继承 C 的所有函数属性。每个这样的方法对象都具有属性O和相应的函数。在本例中,a.f 具有对象 a 的属性和名为“f”的函数。但是当执行 A.f = fnew 时,我只是改变了类对象 A 的属性,而不是方法对象 a.f 的属性,那么为什么 a.f.func 最后会被改变呢?

最佳答案

当您执行a.f时,Python将从实例a中查找成员f。当它找不到具有该名称的成员时,它将查找类型层次结构以找到它。因此在本例中,它将查看实例的类型,即 A。这就是为什么访问 a.f 将使用存储在 A.f 中的函数。

如果您要在实例中覆盖 f,则不会发生这种情况:

>>> A.f = fnew
>>> a.f
<bound method fnew of <__main__.A object at 0x00000083E819B1D0>>
>>> a.f = 'foo'
>>> a.f
'foo

请注意,创建实例时,类型中的成员将不会复制到实例中。如果发生这种情况,创建对象实例的成本将会非常昂贵。相反,当实例本身没有成员时,类型系统只会从类型中查找成员。

<小时/>

正如 timgeb 在评论中指出的,在 Python 2 中,您的最终检查 a.f.__func__ is A.f 将返回 False。这是因为,A.f 将返回一个与原始函数不同的未绑定(bind)函数。但这只是一个小细节,不会改变我上面所写的内容:该方法仍将从类型中查找。

关于python - 你能解释一下为什么改变类的函数属性会产生以下效果吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47531948/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com