动态改变自绑定

Dynamically Change Self 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 有效,但我更愿意将动词而不是名词传递到队列中。

您可以将关闭 x 的 lambda 入队并等待其 api 实例:

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

稍后只需传递 API 对象:

task = dequeue()
task(api)

您还可以在 Python 3 中获得一个 "unbound method reference",稍后您可以将 self 传递给它,只需将 class 成员命名为:

>>> 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 的类型会有些特殊。)

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

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)