2012-06-22 2 views
6

나는이 범위 동작에 대한 혼란 스러워요 :이상한 파이썬 기능 범위의 동작

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") 

이 출력 제공 :

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 

을하지만 func_wrapper 항상 올바른 기능이 될 것이라고 예상했을 것이다. func_wrapper의 범위가 전체 함수에 있음을 알고 있지만 모든 루프 반복에서이를 재정의하고 마지막 인스턴스가 attrib에서 제외되었습니다. 나도 setattr 아래에 func_wrapper = None를 더하려고 노력했다. 그러나 그것은 도움이되지 않는다 (또한 나를 궁금하게 생각할 것이다. ..).

내가 장 님? 나는이 문제를 해결하는 방법을 실제로 보지 못했다. 원래 예에서

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) 

더 견고

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) 

또는 함께

+0

@heltonbiker : 자세히 설명해 주시겠습니까? 여기서 어떻게 사전을 사용해야합니까? 그리고 왜? – Albert

+0

나는 더 철저히 읽고 이전 주석을 삭제했습니다. – heltonbiker

답변

6

중 하나는, 생성 된 모든 기능은 각 루프의 실행으로 변화 같은 외부 변수 fn를 액세스. 수정 된 예제에서는 이것이 방지됩니다.

+0

아 그래, 나는 이렇게 생각했다. :) – Albert

+0

후기 바인딩과 관련하여 '람다'에 대해 * 특별한 * 것이 있다고 항상 생각했지만, 이제는 정규 함수가 실제로 똑같은 문제가 있다는 것을 이해한다. 그것들은 람다 함수와 같은 방식으로 그렇게 자주 사용되지는 않습니다. 질의 응답 +1. –

+0

사람들이 기본 매개 변수 해킹을 권장하지 않기를 바랍니다. –