我们通常很熟悉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
将被传递给你用来扩展闭包范围并访问回调的默认参数!
似乎你想要“未来证明”的回调闭包,你被迫坚持你的原始签名,并通过这些论点传递一切。这并不是那么糟糕,但是如果你没有让你的原始签名足够通用,这就会出现问题。
对此问题的任何想法或新方法表示赞赏。
答案 0 :(得分:0)
在写完这个问题后,我意识到你可以通过创建一个新的函数来解决这个问题,用拥有范围来创建闭包。一旦你拥有了它,你只需在循环中调用它:
def create_callback_closure(callback):
def old_style_closure(data, *args, **kwargs):
callback(data, *args, **kwargs)
# ...
closures = []
for cb in list_of_callbacks:
closures.append(create_callback_closure(callback))