Python 2.7类方法赋值异常:为何Lambda实现符合预期?
问题解析:为什么Lambda实现的
_revert能正常工作? 先还原你的代码和输出:
from collections import namedtuple Point = namedtuple('Point',['x','y']) Point2 = namedtuple('Point2',['x','y']) Point._revert = tuple Point2._revert = lambda s: tuple(s) for pointClass in [Point,Point2]: instance = pointClass(x=10,y=20) print "{} reverts to {}".format(instance,instance._revert())
输出结果:
Point(x=10, y=20) reverts to () Point2(x=10, y=20) reverts to (10, 20)
核心差异在于Python的方法绑定机制对普通函数(包括lambda)和内置类型构造函数的处理逻辑不同:
对于
Point2._revert = lambda s: tuple(s):
当你通过实例instance调用_revert()时,Python会自动把实例本身作为第一个参数传递给这个lambda函数——这是Python实例方法的默认绑定行为。lambda里的s就是instance,而namedtuple的实例本身是tuple的子类,所以tuple(s)会把这个实例转换为标准元组,得到(10, 20),和直接调用tuple(instance)的效果完全一致。对于
Point._revert = tuple:tuple是Python的内置类型构造函数,它的签名是tuple(iterable=())——默认参数是空可迭代对象,不传参时会返回空元组。当你把它赋值给类属性后,通过实例调用instance._revert()时,Python并不会自动将实例作为参数传递给tuple函数(内置构造函数不参与普通的方法绑定逻辑)。这时候相当于直接调用tuple(),自然返回空元组()。
如果想要让Point._revert也能正常工作,你可以用普通函数或者lambda包装tuple(就像Point2那样),或者手动传递实例参数:
# 方式1:用普通函数包装 def revert(self): return tuple(self) Point._revert = revert # 方式2:调用时手动传参 instance = Point(x=10,y=20) print(instance._revert(instance)) # 输出(10, 20)
内容的提问来源于stack exchange,提问作者Thomas Andrews
相关产品推荐
相关产品推荐

