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

时间:2009-08-07 02:25:53

标签: python programming-languages gtk closures 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)

这种方法偶尔使用一次,但如果update()函数运行得太多,我最终得到:

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

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

2 个答案:

答案 0 :(得分:4)

确实非常神秘 - 看起来封闭物从内在功能下消失了。不知道这是否与如何 pygtk拥有这样的回调函数有关(我不熟悉它的内部结构)。试图探究这一点 - 如果你还将{l}和lne附加到attach_row末尾的全局列表中会发生什么,只是为了确保它们“正常”保持在某个位置以便它们的闭包能够存活 - 那个问题还存在吗?

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

答案 1 :(得分:0)

没有足够的分数将此作为评论(刚注册)......

  • 全局或更高范围内没有'es'变量?
  • attach_row也不是嵌套函数吗?
  • NameError异常指向ene或lne函数中的for循环行?

一种可能但又icky的解决方法可能是通过__call __()方法创建实例化和可调用函数的ene和lne类。