2017-02-23 16 views
1

아래 코드로 숫자 개체를 에뮬레이션하는 메서드를 동적으로 설정하려고합니다. 그러나 모든 메서드는 루프의 마지막 메서드로 설정됩니다. 왜 이런 일이 일어나고 파이썬을 DWIM으로 설득 할 수 있습니까?루프에서 동적으로 메서드를 정의하여 숫자 개체를 에뮬레이트하지만 모든 메서드가 마지막 반복 값을받습니다. 이유는 무엇입니까?

#!/usr/bin/env python3.5 
class Foo(float): 
    pass 

for tp in ("add", "sub", "mul", "truediv", "floordiv", "mod", "divmod", "pow"): 
    methname = "__{:s}__".format(tp) 
    print("defining", methname) 
    def func(self, other): 
     x = getattr(super(Foo, self), methname)(other) 
     print("I calculated x={:.3f}!".format(x)) 
     return x 
    func.__name__ = methname 
    setattr(Foo, methname, func) 

if __name__ == "__main__": # test 
    print("Addition", Foo(3) + Foo(3)) 
    print("Multiplication", Foo(3) * Foo(3)) 

$ ./dyn.py 
defining __add__ 
defining __sub__ 
defining __mul__ 
defining __truediv__ 
defining __floordiv__ 
defining __mod__ 
defining __divmod__ 
defining __pow__ 
I calculated x=27.000! 
Addition 27.0 
I calculated x=27.000! 
Multiplication 27.0 

답변

1

결과 27.0은 3 ** 3에 의해 계산되며 마지막 고리에서 변경된 methname을 호출 할 때 실제로 저장된 함수를 호출합니다.

func에서 사용되는 변수는 전역 변수를 참조합니다. func을 다른 메소드에 넣고 루프 변수를 매개 변수로 전달하여 func을 포함하는 함수의 로컬 변수가 상수이고 루프에 의해 변경되지 않도록하십시오.

#create function with the given name 
# \return the function 
def makeFunc(tp): 
    methname = "__{:s}__".format(tp) 
    print("defining", methname) 
    def func(self, other): 
     x = getattr(super(Foo, self), methname)(other) 
     print("I calculated x={:.3f}!".format(x)) 
     return x 
    func.__name__ = methname 
    return func 


for tp in ("add", "sub", "mul", "truediv", "floordiv", "mod", "divmod", "pow"): 
    func=makeFunc(tp) 
    setattr(Foo, func.__name__, func) 
+0

확실히. 비록 내가 어떤 기능도 중첩시키지 않더라도, 링크 된 대답으로 그것을 알아 낸 것입니다. 'methname = methname'을'func'의 시그니처에 추가하면 트릭을 만들었습니다. – gerrit