【问题标题】:Future Proof Scoping In Callback Closures [Python]回调闭包中的未来证明范围 [Python]
【发布时间】: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


    【解决方案1】:

    写完这个问题后,我意识到你可以通过创建一个新函数来解决这个问题,拥有作用域来创建闭包。一旦你有了它,你只需将它称为循环:

    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))
    

    【讨论】:

      猜你喜欢
      • 2015-12-28
      • 2018-02-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多