2012-06-22 29 views
6

bu kapsam davranışı hakkında karıştı:garip Python fonksiyonu kapsamı davranışı

class Bar: 
    def __init__(self): 
     for fn in ["open","openW","remove","mkdir","exists","isdir","listdir"]: 
      print "register", fn 
      def func_wrapper(filename): 
       print "called func wrapper", fn, filename 
      setattr(self, fn, func_wrapper) 

bar = Bar() 
bar.open("a") 
bar.remove("b") 
bar.listdir("c") 

Bu çıktıyı verir:

register open 
register openW 
register remove 
register mkdir 
register exists 
register isdir 
register listdir 
called func wrapper listdir a 
called func wrapper listdir b 
called func wrapper listdir c 

Ama func_wrapper her zaman doğru işlevi olacağını umuyordum. func_wrapper'un kapsamının tüm işlev için olduğunu biliyorum, ancak her döngü yinelemesinde onu yeniden tanımladım ve son örnek öznede kurtarıldı. Ayrıca setattr'un altına func_wrapper = None'u eklemeyi denedim ama bu yardımcı olmadı (aynı zamanda beni merak ediyordu ...).

Kör miyim? Bunu nasıl halledeceğimi/düzelteceğimi bile göremiyorum. Orijinal örnekte

def mkwrapper(fn): 
    def func_wrapper(filename): 
     print "called func wrapper", fn, filename 
    func_wrapper.__name__ = fn 
    return func_wrapper 

class Bar: 
    def __init__(self): 
     for fn in ["open","openW","remove","mkdir","exists","isdir","listdir"]: 
      print "register", fn 
      func_wrapper = mkwrapper(fn) 
      setattr(self, fn, func_wrapper) 

ile daha sağlam

class Bar: 
    def __init__(self): 
     for fn in ["open","openW","remove","mkdir","exists","isdir","listdir"]: 
      print "register", fn 
      def func_wrapper(filename, fn=fn): 
       print "called func wrapper", fn, filename 
      setattr(self, fn, func_wrapper) 

veya birlikte

+0

@heltonbiker: Detaylandırır mısınız? Bunun yerine burada nasıl bir tarif kullanmalıyım? Ve neden? – Albert

+0

Daha ayrıntılı bir şekilde okudum ve önceki yorumu sildim. – heltonbiker

cevap

6

Ya, tüm oluşturulan fonksiyonlar her döngü vadede değiştirir aynı dış değişkeni fn, erişin. Düzeltilmiş örneklerde, bu önlenir.

+0

Ah evet, sanki böyle bir şey düşündüm ... :) – Albert

+0

Her zaman, * geç * ciltle ilgili özel bir şey olduğunu düşünmüştüm ama artık normal işlevlerin aynı sorunu olduğunu anlıyorum. onlar çok sık değil aynı şekilde kullanılır lambda fonksiyonları. Soru ve cevap için +1. –

+0

İnsanların bu varsayılan parametreyi hacklemeyi tavsiye etmelerini istemeseydim. –