2009-08-07 18 views
6

Göremediğim çok tuhaf bir kapsam belirleme hatası. Bir güncelleyici fonksiyonunun içinde, ben .../bir şey w yardımıyla iç içe bir yardımcı işlevi vardır:pygtk: kapsamı tamamlamadan önce atanan serbest değişken

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) 

Bu arada bir çalışır, ancak güncelleme() işlevi çok fazla çalışıyorsa, sonunda alıyorum:

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

Buna neden oluyor? Bu işlevler çağrılmadan önce kesinlikle atanır. Bu doğru değil mi? Önceden yaratılmış bir satır için ene(), yeni bir tane oluşturulurken çağrılır ve es'un üzerine yazılır mı?

cevap

4

Oldukça esrarengiz bir gizlilik - kapağın iç işlevlerin altından kaybolacağına benziyor. pygtk'nin bu tür geri arama işlevlerini nasıl tuttuğunu merak ediyorsanız (içsellerine aşina değilim). Bunun için araştırmaya çalışın - 0e'un sonunda global bir listeye ene ve lne eklerseniz ne olur, sadece "normal" bir yerde tutulduklarından emin olun, böylece kapanırlar. O vaka?

Eğer öyleyse, o zaman sorunu sadece TOO gizemli olduğunu kabul etmeliyim ve bir önceki çözümle çelişen bir çözüm olarak, devletlerini daha açık bir şekilde tutabilen callables kullanımını önermek zorundayım (İki tane bağlantılı yöntem öneririm bir sınıf örneğinin, kendi durumlarını paylaştıklarından, ancak __call__ ile tek bir sınıfın iki örneğini alıp durumunu almak için durumu alma ve __init__'daki olay kutularının listesi de kesinlikle makul - iki ayrı sınıfa sahip olmak IMHO biraz abartı;-).

+0

hehe, doğru. Bunu yapmanın daha akılcı bir yolunun olduğunu fark ettim - bu satırların çoğunu çıkarmak ve takmak yerine, bunlardan sadece bir set oluşturup bunların içindeki widget'ları değiştiriyorum. Bir not: Yine de: "es" değerini kullanıcı verileri olarak ene ve lne işlevlerine geçirmeyi denedim. Ne olur ki artık NameError'a sahip değilim, ancak widgetlar hiç de vurgulanmayacaktı. Sisten hala bir yerlerde kayboluyordu. Eğer bu tekrar gelirse, sınıf fikrini deneyeceğim. – Claudiu

+0

daha da iyi bir yol - bir VBox kullanın, satır başına bir olay kutusu yerleştirin ve daha sonra – Claudiu

+0

sütunlarını hizalamak için bir boyut grubu kullanın, bu diğer durumlarda da oldu. Python 2.5 tuhaflık olduğunu düşünüyorum. hala bir cevap bulamadı – Claudiu

0

küresel veya daha yüksek bir kapsamda ...

  • Hayır 'es' değişkeni bir yorumun (sadece kayıtlı) olarak ayrılmak için yeterli puanı yok mu?
  • attach_row ayrıca iç içe geçmiş bir işlev de değil mi?
  • NameError istisnası, ene veya lne işlevlerindeki döngü çizgisi için işaret eder?

Mümkün olan, ancak çok kolay, geçici bir çözüm, __call __() yöntemi ile işlevler olarak örneklendirilebilen ve çağrılabilen ene ve lne sınıflarını yapmak olabilir.