所以我似乎误解了一些关于Python的基本内容。将实例变量传递给函数应该只传递对象本身的引用,所以如果对象是不可变的,那么像self.var = "something"; foo(self.var)
这样的东西不应该改变self.var如果foo为变量赋予了一个新值 - 所以一切都很好,正如预期的那样。
但现在考虑一下:
import threading
class Test():
def __init__(self):
self.lock = threading.Lock()
self.arg = "arg0"
def foo(self, i):
with self.lock:
threading.Thread(target=lambda: bar(self.arg)).start()
self.arg = "arg" + str(i)
def bar(arg):
import time
time.sleep(1)
print("Bar: " + arg)
if __name__ == '__main__':
t = Test()
for i in range(1, 6):
t.foo(i)
我创建了一个带有对当前字符串的引用的线程对象,然后更新它 - 线程不应该看到它。由于锁定,下一个线程也应该只在更新后开始 - 所以虽然我不能对arg0-5的打印顺序做出任何假设,但我认为每个arg应该只打印一次。但我得到以下输出(Win7 x64,python 3.1 x64)
Bar: arg0
Bar: arg2
Bar: arg2
Bar: arg5
Bar: arg3
编辑:好的,在输入之后,我有一个光荣的想法,可能在创建线程时可能没有执行lambda表达式,但稍后会解释行为,因此简单的解决方法是创建一个本地变量并使用它。好吧 - 现在这是SO的快速帮助;)
答案 0 :(得分:2)
因为我注意到我还没有回答那个,所以我们走了:
lambda为self
而不是self.arg
本身创建一个闭包,这意味着当我们稍后执行bar时,我们访问最新值而不是lambda创建时的值。