6

私が見ることさえできない非常に奇妙なスコープエラー。アップデータ関数の内部には、ネストされたヘルパー関数があります...何かを支援します:

    def attach_row(ws,r1,r2):
        es = []
        for i,w in enumerate(ws):
            eb = gtk.EventBox()
            a = gtk.Alignment(xalign=0.0,yalign=0.5)
            a.add(w)
            eb.add(a)
            eb.set_style(self.rowStyle.copy())
            es.append(eb)                
            self.table.attach(eb, i, i+1, r1, r2,
                              xoptions=gtk.EXPAND|gtk.FILL,
                              yoptions=gtk.SHRINK)

        def ene(_,ev):
            for eb in es:
                eb.set_state(gtk.STATE_PRELIGHT)
        def lne(_,ev):
            for eb in es:
                eb.set_state(gtk.STATE_NORMAL)
        for eb in es:                
            eb.connect('enter-notify-event', ene)
            eb.connect('leave-notify-event', lne)

これは時々機能しますが、 update() 関数が実行されすぎると、最終的には次のようになります。

    for eb in es:
NameError: free variable 'es' referenced before assignment in enclosing scope

これは何が原因ですか?es は、これらの関数が呼び出される前に最も確実に割り当てられます。そうじゃない?何らかの理由で、新しい行が作成されている間に以前に作成された行の ene() が呼び出され、閉じられたオーバーesが上書きされるという奇妙なことが起こっていますか?

4

2 に答える 2

4

確かにかなり神秘的です - 内部関数の下からクロージャが消えているように見えます。それがpygtkがそのようなコールバック関数を保持する方法に関連しているのだろうか(私はその内部に精通していない)。それを調べようとすると- ene と lne をグローバルリストの最後に追加するとどうなるattach_rowか、それらが「正常に」どこかに保持されていることを確認して、それらの閉鎖が存続することを確認します-問題はその点で持続しますか?場合?

もしそうなら、私は問題があまりにも神秘的であることを認め、回避策として、より明確な方法で状態を保持する呼び出し可能オブジェクトの使用を提案する前の回答に同意する必要があります (1 つのクラスインスタンスの 2 つのバインドされたメソッドを提案します) 、それらは状態を共有するためですが、__call__設定する状態とその中のイベントボックスのリストを受け取り、受け取る単一クラスの2つのインスタンス__init__も確かに合理的です-2つの別々のクラスIMHOを持つことは少し誇張されます;-)。

于 2009-08-07T05:17:27.497 に答える
0

これをコメントとして残すのに十分なポイントがありません (登録したばかりです) ...

  • グローバルまたはより高いスコープに「es」変数はありませんか?
  • attach_row もネストされた関数ではありませんか?
  • NameError 例外は、ene 関数または lne 関数の for ループ行を指していますか?

可能性はあるものの厄介な回避策の 1 つは、__call__() メソッドを介してインスタンス化され、関数として呼び出し可能な ene および lne クラスを作成することです。

于 2009-08-07T03:47:44.633 に答える