You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python:for循环+setattr重载运算符异常问题及解决方法

问题原因与修正方案

错误代码示例

你大概率写了类似这样的代码:

class X:
    def __init__(self, val):
        self.val = val

# 定义运算符对应的函数
ops = [
    ('__add__', lambda self, other: self.val + other.val),
    ('__mul__', lambda self, other: self.val * other.val)
]

# 循环绑定方法
for name, func in ops:
    setattr(X, name, func)

运行后X(5)+X(2)和X(5)*X(2)都返回10,不符合预期。

问题根源

这是Python闭包的延迟绑定特性导致的:lambda表达式里引用的循环变量func,不会在循环迭代时立即获取当前值,而是等到函数被调用时,才去查找当前作用域中func的最终值。循环结束后,func最后指向的是乘法对应的lambda,所以__add__和__mul__实际上都绑定了同一个乘法函数,自然加法运算也会执行乘法逻辑。

修正方法

方法1:利用默认参数即时绑定

修改循环逻辑,给lambda添加默认参数,在迭代时就把当前的func值绑定进去:

class X:
    def __init__(self, val):
        self.val = val

ops = [
    ('__add__', lambda self, other: self.val + other.val),
    ('__mul__', lambda self, other: self.val * other.val)
]

for name, func in ops:
    # 通过默认参数f绑定当前迭代的func
    setattr(X, name, lambda self, other, f=func: f(self, other))

方法2:使用functools.partial固定参数

借助functools.partial将当前的函数作为固定参数传入,生成独立的可调用对象:

from functools import partial

class X:
    def __init__(self, val):
        self.val = val

def wrap_method(func, self, other):
    return func(self, other)

ops = [
    ('__add__', lambda self, other: self.val + other.val),
    ('__mul__', lambda self, other: self.val * other.val)
]

for name, func in ops:
    setattr(X, name, partial(wrap_method, func))

方法3:提前生成绑定好的方法列表

通过列表推导式提前创建每个方法,利用默认参数完成绑定:

class X:
    def __init__(self, val):
        self.val = val

ops = [
    ('__add__', lambda self, other: self.val + other.val),
    ('__mul__', lambda self, other: self.val * other.val)
]

# 提前生成每个绑定好的方法
methods = [(name, lambda self, other, f=func: f(self, other)) for name, func in ops]
for name, method in methods:
    setattr(X, name, method)

验证效果

修正后运行:

print(X(5) + X(2))  # 输出7
print(X(5) * X(2))  # 输出10

符合预期。

内容的提问来源于stack exchange,提问作者Tachy0n_

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 03:22:48