5

関数を渡すことを期待する Python API を使用しています。ただし、さまざまな理由から、メソッドを渡したいと思います。これは、関数が属するインスタンスに応じて関数の動作が異なるようにするためです。メソッドを渡すと、API は正しい「自己」引数でそれを呼び出しません。そのため、メソッドを、それが属する「自己」を認識する関数に変換する方法を考えています。

これを行うには、ラムダやクロージャーを使用するなど、いくつかの方法が考えられます。以下にいくつかの例を示しますが、同じ効果を達成するための標準的なメカニズムがあるかどうか疑問に思っています。

class A(object):
    def hello(self, salutation):
        print('%s, my name is %s' % (salutation, str(self)))

    def bind_hello1(self):
        return lambda x: self.hello(x)

    def bind_hello2(self):
        def hello2(*args):
            self.hello(*args)
        return hello2


>>> a1, a2 = A(), A()
>>> a1.hello('Greetings'); a2.hello('Greetings')
Greetings, my name is <__main__.A object at 0x71570>
Greetings, my name is <__main__.A object at 0x71590>

>>> f1, f2 = a1.bind_hello1(), a2.bind_hello1()
>>> f1('Salutations'); f2('Salutations')
Salutations, my name is <__main__.A object at 0x71570>
Salutations, my name is <__main__.A object at 0x71590>

>>> f1, f2 = a1.bind_hello2(), a2.bind_hello2()
>>> f1('Aloha'); f2('Aloha')
Aloha, my name is <__main__.A object at 0x71570>
Aloha, my name is <__main__.A object at 0x71590>
4

2 に答える 2

9

インスタンスにバインドされたメソッドを渡すことはできますか? その場合、特別なことをする必要はありません。

In [2]: class C(object):
   ...:     def method(self, a, b, c):
   ...:         print a, b, c
   ...:
   ...:

In [3]: def api_function(a_func):
   ...:     a_func("One Fish", "Two Fish", "Blue Fish")
   ...:
   ...:

In [4]: c = C()

In [5]: api_function(c.method)
One Fish Two Fish Blue Fish
于 2009-01-29T03:58:53.303 に答える
0

あなたはあなたの質問を明確にしたいかもしれません。ライアンが指摘するように、

def callback(fn):
    fn('Welcome')
callback(a1.hello)
callback(a2.hello)

hello正しいself境界、a1またはで呼び出されることになりますa2。これが発生していない場合は、Pythonの動作方法であるため、何かが深刻に間違っています。

あなたが書いたものから判断して、あなたが望んでいるように見えるのは、引数をバインドすることです-言い換えれば、カリー化です。至る所で例を見つけることができますが、レシピ52549は、私の好みでは、最高のPythonicの外観を持っています。

class curry:
    def __init__(self, fun, *args, **kwargs):
        self.fun = fun
        self.pending = args[:]
        self.kwargs = kwargs.copy()

    def __call__(self, *args, **kwargs):
        if kwargs and self.kwargs:
            kw = self.kwargs.copy()
            kw.update(kwargs)
        else:
            kw = kwargs or self.kwargs

        return self.fun(*(self.pending + args), **kw)

f1 = curry(a1.hello, 'Salutations')
f1()  #  == a1.hello('Salutations')
于 2009-01-29T04:19:17.287 に答える