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, чтобы обойти это, но кто-нибудь знает, есть ли чистый, здоровый, путинский способ связать несвязанный метод с экземпляром и продолжить его, не называя его?

Ответ 1

Все функции также являются дескрипторами, поэтому вы можете связать их, вызвав их метод __get__:

bound_handler = handler.__get__(self, MyWidget)

Здесь Р. Хеттингер отлично описывает руководство для дескрипторов.

Ответ 2

Это можно сделать с помощью 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>>

Ответ 3

Создание замыкания с self в нем не будет технически связывать функцию, но это альтернативный способ решения одной и той же (или очень похожей) основной проблемы. Здесь тривиальный пример:

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

Ответ 4

Это привяжет self к handler:

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

Это работает, передавая self в качестве первого аргумента функции. object.function() - это просто синтаксический сахар для function(object).