5

我正在使用一个 Python API,它希望我向它传递一个函数。但是,由于各种原因,我想向它传递一个方法,因为我希望函数根据它所属的实例表现出不同的行为。如果我向它传递一个方法,API 将不会使用正确的“self”参数调用它,所以我想知道如何将一个方法变成一个知道它属于什么“self”的函数。

我可以想到几种方法来做到这一点,包括使用 lambda 和闭包。我在下面包含了一些示例,但我想知道是否有标准机制可以实现相同的效果。

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 的工作方式。

从您所写的内容来看,您似乎想要的是绑定参数 - 换句话说,就是currying。你可以在各处找到示例,但根据我的口味, Recipe 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 回答