提问人:Karl Knechtel 提问时间:8/15/2022 更新时间:8/15/2022 访问量:199
从 API 实例化类时,我需要提供回调。如何急切地将实例本身绑定到回调?
I need to provide a callback when instantiating a class from an API. How can I bind the instance itself to the callback, eagerly?
问:
我现在在几个不同的主要第三方库和框架中遇到了这个问题。让我试着把它归结为要点:
- API 提供了一个类 ,其中构造函数需要一个参数。当某些事件发生时(由于我无法控制的复杂逻辑),API 将调用该函数。
Example
callback
callback
- 我有一个函数,它接受一个实例并调用各种方法:
modify
Example
def modify(it): it.enabled = True it.visible = True try: it.paint('black') except AProblemComesAlong: it.whip()
- 我想创建一个 .当发生与 关联的事件时,应通过 修改实例。
x
Example
x
x
modify
因此,我想根据 Python 参数绑定器作为参数绑定到。问题是,它还不存在,因为我仍在调用构造函数:x
modify
>>> from functools import partial
>>> x = Example(callback=partial(modify, x))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'x' is not defined
当然,我可以通过允许稍后查找名称来避免:NameError
lambda
>>> x = Example(callback=lambda: modify(x))
但这是后期绑定,因此如果例如我在循环中并且实例
是迭代变量,或者如果稍后由于任何其他原因重新分配,则它无法正常工作。instance
如何完成与自身回调的早期绑定?instance
答:
1赞
Karl Knechtel
8/15/2022
#1
通常,您可以尝试以下任何一种方法:
- 仔细检查 API 是否允许您稍后设置回调(两阶段构造):
from functools import partial instance = Example() # Read the documentation and see if Example provides something like: instance.callback = partial(modify, instance) # or possibly they didn't think of using a decorator for their validation logic: instance.set_callback(partial(modify, instance))
- 对示例进行子类化,以便它从自己的方法调用回调,并调整构造参数以将该方法用作包装器: 这里的想法归功于@tdelaney。
from functools import partial class ContextProvidingExample(Example): def __init__(self, *args, **kwargs): try: my_callback = kwargs['callback'] kwargs['callback'] = partial(my_callback, self) except KeyError: pass super().__init__(*args, **kwargs)
- 如果不需要灵活性,则可以将逻辑直接集成到子类中:
modify
class SelfModifyingExample(Example): def __init__(self, *args, **kwargs): if 'callback' in kwargs.keys(): raise ValueError('cannot override callback') kwargs['callback'] = self._modify super().__init__(*args, **kwargs) def _modify(self): self.enabled = True self.visible = True try: self.paint('black') except AProblemComesAlong: self.whip()
- 作为最后的手段,在字典中注册实例,并安排回调按名称查找它们:这种方式有点笨拙,但您可能会发现实例的字符串名称在代码的其他地方很有用。
from functools import partial hey_you = {} # say my name... def modify_by_name(name): modify(hey_you[name]) # call modify() maybe? # Let's use a simple wrapper to make sure instances get registered. def stand_up(name): result = Example(callback=partial(modify_by_name, name)) hey_you[name] = result return result who = what = stand_up('slim shady')
上一个:保留在闭包中使用的值以备后用
评论