So it seems I'm misunderstanding some basic stuff about Python. Passing an instance variable into a function should only pass a reference to the object itself, so in case the object is immutable doing something like self.var = "something"; foo(self.var) shouldn't change self.var if foo assigned a new value to the variable - so long everything's fine and as expected.
But now consider this:
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)
I create a thread object with a reference to the current string and afterwards update it - which the thread shouldn't see. Thanks to the lock the next thread also should only start after the update - so while I can't make any assumptions about the sequence in which arg0-5 will be printed I'd assume every arg should be printed exactly once. But I get the following output (Win7 x64, python 3.1 x64)
Bar: arg0
Bar: arg2
Bar: arg2
Bar: arg5
Bar: arg3
Edit: Okay after typing this up, I had the glorious idea that probably the lambda expression isn't executed when creating the thread but later on, which would explain the behavior, so the simple workaround would be to just create a local variable and use that. Well - now that was fast help by SO ;)
class Test():does, as opposed toclass Test:orclass Test(object):?class Test:was legal syntax - a bit nicer that way, great (for python2 that would still default to old class syntax though wouldn't it?)