2011-08-13 11 views
1

だから、私はPythonに関するいくつかの基本的なことを誤解しているようです。インスタンス変数を関数に渡す必要があるのは、オブジェクト自体への参照を渡すだけなので、オブジェクトが不変の場合、self.var = "something"; foo(self.var)は、変数に新しい値が代入された場合、self.varを変更しないでください。予想通り。インスタンス変数を使ったスレッディング問題

しかし、今は、このことを考慮してください。

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の、パイソン3.1 x64)の

Bar: arg0 
Bar: arg2 
Bar: arg2 
Bar: arg5 
Bar: arg3 

編集取得:これを入力した後にオーケーを、私はおそらく、ラムダ式が後にスレッドを作成するときに実行されないが、栄光のアイデアを持っていましたこれは動作を説明するので、単純な回避策はローカル変数を作成して使用することです。

ラムダを意味し、自分自身をselfにクロージャを作成しなくself.argへ:私は、私はまだその1に答えていませんでした気づいたので、ここで、

+0

おめでとうございます!あなたは謎を解決した。別のもの: 'class Test:'や 'class Test(object):'とは対照的に、 'class Test():'は何をしていると思いますか? – pillmuncher

+0

@pillmuncher:私はPython3を使用していますので、古いスタイルと新しいスタイルのクラスを心配する必要はありません。私は 'class Test:'が正当な構文であることを知らなかったが、それはちょっといいよ(Python2の場合でも古いクラスの構文になってしまうだろうが) – Voo

+0

あなた自身の問題を解決すれば@Voo答えとして投稿すると、2日後にそれを受け入れることができます。 – agf

答えて

2

)私達は行く; - まあ今ではSOによって速い助けました後でbarを実行すると、ラムダ作成時の値ではなく最新の値にアクセスします。

関連する問題