pygtk:在封闭范围中赋值之前引用的自由变量

Cla*_*diu 6 python gtk closures programming-languages semantics

非常奇怪的范围错误,我甚至看不到.在updater函数内部,我有一个嵌套的辅助函数来帮助w/something:

    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)
Run Code Online (Sandbox Code Playgroud)

这有效,但如果update()函数运行太多,我最终得到:

    for eb in es:
NameError: free variable 'es' referenced before assignment in enclosing scope
Run Code Online (Sandbox Code Playgroud)

是什么造成的?在这些函数被调用之前,es肯定会被分配.不是吗?是否有一些奇怪的事情发生在哪里由于某种原因,在创建新的行时调用先前创建的行的ene(),并且封闭的覆盖es被覆盖?

Ale*_*lli 4

确实很神秘——看起来闭包从内部函数下面消失了。想知道这是否与 pygtk如何保存此类回调函数有关(我不熟悉其内部结构)。尝试探究这一点 - 如果您还将 ene 和 lne 附加到全局列表的末尾会发生什么attach_row,只是为了确保它们“正常”地保存在某个地方,以便它们的闭包得以幸存,会发生什么情况 - 问题是否仍然存在案件?

如果确实如此,那么我必须承认这个问题太神秘了,并同意之前的答案,建议作为一种解决方法,使用可调用对象以更清晰的方式保存其状态(我建议一个类实例的两个绑定方法) ,因为它们共享它们的状态,但是单个类的两个实例并__call__接收要设置的状态以及其中的事件框列表__init__当然也是合理的——恕我直言,拥有两个单独的类有点夸张;-)。