Python生成布尔函数列表遇闭包引用问题求助
问题分析与解决方法
问题根源
你猜的没错——所有lambda函数都捕获了func_list的引用,而非循环迭代中每次的func_list副本。即使套了一层f()闭包也没用,因为Python闭包采用延迟绑定:只有当lambda被调用时,才会去查找func_list的值,此时循环已经结束,func_list停留在最后一次迭代的状态,所以所有函数返回的都是同一组结果。
解决思路
要让每个lambda绑定当前迭代的func_list快照,核心是在函数定义时就把当前的func_list值固定下来,而不是延迟到调用时查找。常用两种方法:
方法1:用默认参数绑定当前值
默认参数会在函数定义时求值,因此可以把当前的func_list副本作为默认参数传给lambda:
bucket.append(lambda x, lst=func_list.copy(): bool(lst[var_list.index(x)]))
这里用func_list.copy()是因为列表是可变对象,直接传func_list会绑定同一个引用,复制后才能保留当前迭代的状态。
方法2:用嵌套闭包显式传递参数
给内层闭包传入当前的func_list,让它绑定这个局部变量:
def create_eval_func(lst): return lambda x: bool(lst[var_list.index(x)]) bucket.append(create_eval_func(func_list.copy()))
修改后的完整代码
def all_var_evals(var_set): bucket = [] var_list = list(var_set) # 给集合中的变量赋予顺序 total = 2 ** len(var_set) for row in range(total): to_bin = row func_list = [] # 转换为二进制位列表 while to_bin != 0: func_list.insert(0, to_bin % 2) to_bin = to_bin // 2 # 补前导0,保证长度和变量数一致 while len(func_list) < len(var_list): func_list.insert(0, 0) # 绑定当前迭代的func_list副本,生成布尔函数 bucket.append(lambda x, lst=func_list.copy(): bool(lst[var_list.index(x)])) return bucket
测试验证
调用后每个函数会返回对应变量的布尔值:
funcs = all_var_evals({"P", "Q"}) print(funcs[0]("P"), funcs[0]("Q")) # 输出: False False print(funcs[1]("P"), funcs[1]("Q")) # 输出: False True print(funcs[2]("P"), funcs[2]("Q")) # 输出: True False print(funcs[3]("P"), funcs[3]("Q")) # 输出: True True
内容的提问来源于stack exchange,提问作者Addem
相关产品推荐
相关产品推荐

