[python] Python : 바인딩되지 않은 메서드 바인딩?

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 방식이 있는지 아는 사람이 있습니까?



답변

모든 함수도 설명자 이므로 해당 __get__메서드 를 호출하여 바인딩 할 수 있습니다 .

bound_handler = handler.__get__(self, MyWidget)

다음은 R. Hettinger의 훌륭한 설명자 가이드 입니다.


Keith의 의견 에서 가져온 독립형 예 :

def bind(instance, func, as_name=None):
    """
    Bind the function *func* to *instance*, with either provided name *as_name*
    or the existing name of *func*. The provided *func* should accept the
    instance as the first argument, i.e. "self".
    """
    if as_name is None:
        as_name = func.__name__
    bound_method = func.__get__(instance, instance.__class__)
    setattr(instance, as_name, bound_method)
    return bound_method

class Thing:
    def __init__(self, val):
        self.val = val

something = Thing(21)

def double(self):
    return 2 * self.val

bind(something, double)
something.double()  # returns 42


답변

이것은 types.MethodType으로 깔끔하게 수행 할 수 있습니다 . 예:

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


답변

self가있는 클로저를 생성하면 기능이 기술적으로 바인딩되지는 않지만 동일한 (또는 매우 유사한) 근본적인 문제를 해결하는 다른 방법입니다. 다음은 간단한 예입니다.

self.method = (lambda self: lambda args: self.do(args))(self)


답변

이것은 다음에 바인딩 self됩니다 handler.

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

이것은 self함수에 대한 첫 번째 인수로 전달 하여 작동합니다. object.function()의 구문 상 설탕입니다 function(object).


답변

파티에 늦었지만 비슷한 질문으로 여기에 왔습니다. 클래스 메서드와 인스턴스가 있고 인스턴스를 메서드에 적용하고 싶습니다.

OP의 질문을 과도하게 단순화 할 위험에 처한 나는 여기에 도착한 다른 사람들에게 유용 할 수있는 덜 신비한 일을하게되었습니다 (주의 : 저는 Python 3-YMMV에서 작업 중입니다).

이 간단한 클래스를 고려하십시오.

class Foo(object):

    def __init__(self, value):
        self._value = value

    def value(self):
        return self._value

    def set_value(self, value):
        self._value = value

다음과 같이 할 수 있습니다.

>>> meth = Foo.set_value   # the method
>>> a = Foo(12)            # a is an instance with value 12
>>> meth(a, 33)            # apply instance and method
>>> a.value()              # voila - the method was called
33


답변