我在 Python 中得不到的东西。像外星人一样的有界方法



我不理解这种行为,我在类"f"上更改了"r",它被反射回来 在"q"上,你可以看到"q.r"表示它现在引用了一个"lambda"函数,但同时地址总是"0x037591F0",那么为什么"q.r(("失败了?

class f:
def r(self):
print('bla bla bla')
>>> q=f()
>>> f.r
<function f.r at 0x0378F4B0>
>>> q.r
<bound method f.r of <__main__.f object at 0x037591F0>>
>>> f.r=lambda : 'google'
>>> f.r
<function <lambda> at 0x015F9348>
>>> q.r
<bound method <lambda> of <__main__.f object at 0x037591F0>>
>>> q.r()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: <lambda>() takes 0 positional arguments but 1 was given

r是一个类属性,其值是一个函数。当您从类的实例访问它时,您实际上并没有返回function对象:您返回函数的__get__方法的结果,这是一个新的method对象。此外,每次此类访问都会创建一个新的method对象,但由于该对象的生存期很短(基本上,它存在的时间足以被调用,然后它是垃圾回收的(,因此每个新对象都可以使用与前一个对象相同的内存。

首先,您需要了解什么是实例方法以及它是如何工作的, 请记住,在 Python 中,实例方法存在于类中而不是对象中,因此 Python 在每个实例方法中以隐式方式传递 self 参数(以了解哪个对象正在调用该方法(。

在您的示例中,lambda 函数不接收任何参数,并且您不使用 self 参数,因此告诉我们该方法必须是静态方法(未绑定方法(而不是实例方法(绑定方法(,换句话说,"r"方法需要绑定到类而不是对象。

class f:
@staticmethod
def r():
print('bla bla bla')

如果仍然令人困惑,请阅读类方法,静态方法和实例方法。

在您的情况下,r甚至不是作为静态方法开始的,但即使它确实如此,当您将 lambda 分配给类上的 lambda 以r时,您正在替换它,它将不再是静态方法。因此,当 Python 调用它时,它会将self作为第一个参数传递。

import inspect

class C:
@staticmethod
def r():
return 'x'

print(isinstance(inspect.getmro(C)[0].__dict__['r'], staticmethod))
C.r = lambda: 'y'
print(isinstance(inspect.getmro(C)[0].__dict__['r'], staticmethod))

结果:

True
False

相关内容

最新更新