【发布时间】:2017-03-07 22:26:42
【问题描述】:
由于它的作用域,我们通常熟悉 Python 中的这个“陷阱”:
functions = []
for i in range(3):
functions.append(lambda : i)
out = [f() for f in functions]
# naive expectation = [0, 1, 2]
# actual result = [2, 2, 2]
而且我们通常熟悉如何满足我们的期望:
functions.append(lambda i=i: i)
但是,在尝试创建“面向未来”的回调闭包时,我遇到了一个问题,即扩展回调签名的可能性会破坏用于定义闭包范围的默认参数。
考虑这种情况:
def old_style_callback(data, *args, **kwargs):
# ...
# define a bunch of closures
closures = []
for cb in list_of_callbacks:
def old_style_closure(data, callback=cb, *args, **kwargs):
cb(data, *args, **kwargs)
# ...
closures.append(old_style_closure)
但是,如果您需要添加一个适应某些新功能的新参数怎么办?
def new_style_callback(data, metadata, *args, **kwargs):
# ...
现在您的old_style_closure 已损坏,因为metadata 将被传递给您用于扩展闭包范围和访问回调的默认参数!
似乎如果你想要“面向未来”的回调闭包,你就不得不坚持原来的签名,并通过这些参数传递所有内容。这并没有那么糟糕,但是如果您没有使原始签名足够通用,就会出现问题。
感谢您对此问题的任何想法或新方法。
【问题讨论】:
标签: python callback closures scoping