2009-01-29 30 views
3

我正在使用一個Python API,期望我通過它的一個函數。但是,由於各種原因,我想傳遞一個方法,因爲我希望函數的行爲有所不同,具體取決於它所屬的實例。如果我傳遞一個方法,API不會用正確的'self'參數調用它,所以我想知道如何將一個方法變成一個知道它屬於哪個「自我」的函數。使綁定方法像函數一樣起作用的最pythonic方法是什麼?

有幾種方法可以做到這一點,包括使用lambda和closure。我在下面列出了一些例子,但我想知道是否有一個標準的機制來實現相同的效果。

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> 

回答

8

將傳遞的方法綁定到實例的工作?如果是這樣,你不必做任何特別的事情。

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 
+1

呃......我是個白癡。這樣可行。 – Nick 2009-01-29 04:16:07

0

您可能想澄清一下您的問題。萊恩指出,

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

將導致hello被稱爲具有正確self約束,a1a2。如果您沒有遇到這種情況,則會出現嚴重錯誤,因爲這就是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') 
+0

你展示的不是咖啡 - 這是部分應用。 – 2009-01-29 05:30:12

相關問題