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の方法があるかどうか誰もが知っていますか?
すべての関数もdescriptorsであるため、__get__
メソッドを呼び出してバインドできます。
bound_handler = handler.__get__(self, MyWidget)
R. Hettingerの優れた ガイド 記述子です。
Keith'scomment から抜粋した自己完結型の例として:
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