动态改变自我绑定

时间:2017-04-27 17:00:21

标签: python functional-programming late-binding

在Javascript中,bindcallapply允许您根据需要更改对this的引用。我正在研究Python中的情况,如果我能够执行此操作而不是使用getattr,代码看起来会更好。

我想传递对方法的引用,但是更改方法在线程中引用的实例。在Javascript中,我想这样做:

function produce (x) {
   enqueue(this.api.delete.bind(this.api, x))
}

function consume () { 
   api = new API()
   task = dequeue()
   task.call(api)
}

在Python中,我必须这样做:

def produce(self, x):
   enqueue(partial(self.api.delete, x))

def consume(self):
   api = API()
   task = dequeue() # callable
   ?????????

这可能看起来有点奇怪,但是发生的事情是每个api实例都在一个单独的线程上运行。 getattr有效,但我更愿意将动词而不是名词传递给队列。

2 个答案:

答案 0 :(得分:2)

您可以将lambda排队等候x并等待其api个实例:

enqueue(lambda api: api.delete(x))

稍后只需传递API对象:

task = dequeue()
task(api)

您还可以获得"未绑定的方法参考"在Python 3中,您可以稍后通过简单命名类成员来传递self

>>> class A:
...    def foo(self, x):
...       print(x)
... 
>>> f = A.foo
>>> f(A(), 1)  # equivalent to A().foo(1)
1
>>> f
<function A.foo at 0x7f86c9b872f0>

(IIRC,它在Python 2中的行为相同,但f的类型将是特别的。)

答案 1 :(得分:2)

与phg的答案相关(OK,基本相同),operator模块提供methodcaller函数,该函数采用方法名称(以及可选的方法参数)和返回一个新的可调用对象,当使用对象调用时,使用给定的参数调用对象上的命名方法。

from operator import methodcaller

# methodcaller('foo', arg1)(thing) == thing.foo(arg1)

def produce(self, x):
   enqueue(methodcaller('delete', x))

def consume(self):
   api = API()
   task = dequeue() # callable
   task(api)