2009-06-18 5 views
92

파이썬에서는 언 바운드 메서드를 호출하지 않고 바인딩하는 방법이 있습니까?Python : 바인딩되지 않은 메서드 바인딩?

나는 wxPython에 프로그램을 작성하고,하고 나는 그렇게 같이 함께 내 모든 버튼의 데이터 튜플 클래스 수준의 목록으로, 그룹 좋을 것 결정 특정 클래스 :

class MyWidget(wx.Window): 
    buttons = [("OK", OnOK), 
       ("Cancel", OnCancel)] 

    # ... 

    def Setup(self): 
     for text, handler in MyWidget.buttons: 

      # This following line is the problem line. 
      b = wx.Button(parent, label=text).Bind(wx.EVT_BUTTON, handler) 

handler의 모든 값이 언 바운드 메서드이므로 문제가 발생합니다. 내 프로그램이 장엄한 화재로 폭발하고 울 것입니다.

나는 비교적 단순하고 해결할 수있는 문제에 대한 해결책을 온라인에서 찾고있었습니다. 불행히도 나는 아무것도 찾을 수 없었다. 지금 당장은이 문제를 해결하기 위해 functools.partial을 사용하고 있지만 언 바운드 메서드를 인스턴스에 바인딩하고 호출하지 않고 계속 전달하는 깨끗한 느낌, 건강한 Python 메서드가 있다면 누구나 알 수 있습니까? 이 함수의 첫 번째 인수로 self을 전달하여 작동

bound_handler = lambda *args, **kwargs: handler(self, *args, **kwargs) 

:

+1

는 "언 바운드 방법" – Christopher

+4

@Christopher 정의 - 당신이 명시 적으로 자신을 통과해야하므로,이 빨려 된 개체의 범위에 바인딩되지 않은 방법. –

답변

143

모든 기능은 또한 설명 있습니다.

+2

꽤 멋지 네요. 어떻게 형식을 생략하고 "바운드 메서드? .f"를 대신 얻을 수있는 방법을 좋아합니다. – Kiv

+0

'MethodType'의 인수가 약간 변경되었지만 py3k에서 동일하게 작동하므로'MethodType'에 비해이 솔루션을 좋아합니다. – bgw

+8

함수를 클래스 인스턴스에 바인딩하는 함수 : 'bind = lambda instance, func, asname : setattr (인스턴스, asname, func .__ get __ (인스턴스, 인스턴스 .__ 클래스 __)) ' 예 : 'class A : " "a = A(); bind (a, bind, 'bind') –

3

selfhandler에 바인딩합니다. object.function()function(object)에 대한 구문 식 설탕입니다.

+1

예,이 방법을 호출합니다. 문제는 내가 바운드 메서드를 호출 가능한 개체로 전달할 수 있어야한다는 것입니다. 바인딩되지 않은 메서드와 바인딩 할 인스턴스가 있지만 즉시 호출하지 않고 함께 넣을 방법을 찾을 수 없습니다 –

+6

아니요, 그렇지 않으면 메서드가 호출됩니다. do bound_handler(). 람다 정의는 람다를 호출하지 않습니다. –

+0

람다를 정의하는 대신 실제로'functools.partial'을 사용할 수 있습니다. 그러나 정확한 문제는 해결되지 않습니다. 당신은 여전히'instancemethod' 대신'function'을 다루고 있습니다. –

68

types.MethodType으로 깨끗하게 처리 할 수 ​​있습니다. 예 :

bound_handler = handler.__get__(self, MyWidget) 

여기 R. Hettinger의 우수한 guide에 대한 설명을 : 당신은 자신의 __get__ 방법을 호출하여 바인딩 할 수 있도록

import types 

def f(self): print self 

class C(object): pass 

meth = types.MethodType(f, C(), C) # Bind f to an instance of C 
print meth # prints <bound method C.f of <__main__.C object at 0x01255E90>> 
+8

+1 정말 대단 합니다만, 제공하신 URL의 파이썬 문서에는 아무런 언급이 없습니다. –

+2

+1, 나는 내 코드 (예 :'__get__')에서 마법 함수 호출을 원하지 않습니다. 나는 이것을 테스트 한 python의 버전을 모르지만 python 3.4에서는'MethodType' 함수가 두 개의 인수를 취합니다. 함수와 인스턴스. 따라서 이것을 types.MethodType (f, C())로 변경해야합니다. –

+0

여기 있습니다! 인스턴스 메소드를 패치하는 좋은 방법입니다 :'wgt.flush = types.MethodType (lambda self : None, wgt)' – Winand

7

자기가 포함 된 클로저를 만드는 것은 기술적으로 함수를 바인딩하지 않지만 동일한 (또는 매우 유사한) 근본적인 문제를 해결할 수있는 또 다른 방법입니다. 여기에 사소한 예는 다음과 같습니다

self.method = (lambda self: lambda args: self.do(args))(self) 
관련 문제