1. ホーム
  2. python

[解決済み] Pythonです。未束縛のメソッドを束縛する?

2022-07-11 16:14:23

質問

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 を使用して回避していますが、未束縛のメソッドをインスタンスに結合し、それを呼び出さずに渡し続けるための、クリーンで健全な、Pythonicな方法があるかどうか、誰か知っていますか?

どのように解決するのですか?

また、全ての関数は ディスクリプタ を呼び出すことで、それらをバインドすることができます。 __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