函数内.append与+=的差异及Pool.apply_async回调赋值报错解析
为什么在multiprocessing回调函数中使用
results += [t]会报错,而append却正常? 这是个很有意思的问题,本质和多进程或者回调机制本身无关,核心是Python中可变对象的操作方式与变量作用域的区别。
先看你提供的代码:
from multiprocessing import Pool import random results = [] def f(t): return t def cb_append_result(t): # 报错:"local variable 'results' referenced before assignment" # results += [t] # 正常运行 results.append(t) if __name__ == '__main__': pool = Pool() t = random.random() pool.apply_async(f,args=(t,),callback=cb_append_result) pool.close() pool.join() print("Result is {}".format(results))
问题原因分析
results.append(t):这是在原列表对象上进行的原地修改操作。Python会先在当前函数作用域查找results,找不到就自动去外层全局作用域寻找,找到后直接调用它的append方法——整个过程没有改变results变量本身的指向,因此不需要额外声明作用域。results += [t]:这个操作等价于results = results + [t],本质是创建了一个新的列表对象,并把results变量重新赋值指向这个新对象。Python解释器看到赋值操作时,会默认把results当作当前函数的局部变量,但此时局部作用域里还未定义results,就会抛出“局部变量未赋值即引用”的错误。
解决方案
要让results += [t]正常运行,只需要在回调函数里声明results是全局变量,告诉解释器去全局作用域查找这个变量:
def cb_append_result(t): global results results += [t]
这样解释器就不会把results当作局部变量处理,而是直接使用全局作用域中的列表,执行赋值操作时也会正确更新全局变量的指向。
内容的提问来源于stack exchange,提问作者Donna
相关产品推荐
相关产品推荐

