为何内置函数无法成为绑定方法?自定义函数如何模拟该行为?
Python 方法绑定差异问题
先定义类与lambda函数:
class Something: pass f=lambda : True
执行以下代码:
Something.open=f g=Something() g.open()
会触发报错:
TypeError: <lambda>() takes 0 positional arguments but 1 was given
此时查看g.open的结果为:<bound method <lambda> of <__main__.Something object at 0xffff80253400>>,说明实例self被自动传递给了open。
但执行以下代码:
Something.open=open g=Something() g.open()
报错信息变为:
TypeError: open() missing required argument 'file' (pos 1)
此时g.open的结果是<built-in function open>,没有自动传递self参数。
差异原因
核心在于Python对Python实现的普通函数和C实现的内置函数的绑定逻辑不同:
- 普通函数(包括自定义lambda)被赋值为类属性后,通过实例调用时,Python会自动触发方法绑定机制,把实例作为第一个参数(
self)绑定到函数上,将其转换为绑定方法,这是Python为实例方法访问自身属性设计的默认行为。 - 内置函数(如
open)属于非Python实现的可调用对象,Python的方法绑定机制不会对这类对象生效。它们被赋值为类属性后,通过实例调用时不会自动绑定self,直接以原函数形式执行,因此会要求传入自身所需的参数(比如open必须的file参数)。
让f不接收self的实现方法
方法1:使用staticmethod装饰器
将f包装为静态方法,静态方法不会自动接收self参数:
class Something: pass f=lambda : True Something.open = staticmethod(f) g=Something() g.open() # 正常执行,返回True
方法2:用自定义可调用对象包装
Python的方法绑定仅针对函数生效,自定义可调用对象不会触发绑定逻辑:
class Something: pass # 定义一个可调用类,__call__方法不接收额外参数 class NoSelfCallable: def __call__(self): return True f = NoSelfCallable() Something.open = f g=Something() g.open() # 正常执行,返回True
推荐优先使用staticmethod,它是Python官方提供的、专门用于实现无需self的类方法的语法。
内容的提问来源于stack exchange,提问作者DrownedSuccess
相关产品推荐
相关产品推荐

