首页 > 解决方案 > Python3:列表推导和堆栈框架

问题描述

考虑这个函数:

def quux():
    i = 42 
    print([i for x in [1]])

结果:[42]

因此,我假设本地变量在列表推导中是可见的。

现在考虑一下:

def foo():
    return currentframe().f_back.f_locals["i"]

def quux():
    i = 42 
    print([foo() for x in [1]])

导致:

键错误:'我'

检查堆栈帧,事实证明在 quux 和 foo 的帧之间插入了一个额外的堆栈:

{'x': 1, '.0': <tuple_iterator object at 0x7f59eb94c860>}

好,可以。我感到困惑的是为什么第一个例子看到i. 如果有一个额外的堆栈框架,它不应该是可见的,不是吗?

从更实际的角度来看,我如何获得调用函数的堆栈框架,而不管我的函数是从没有或从列表推导中调用的,或者就此而言,是从多个嵌套列表推导中调用的?

标签: pythonlist-comprehensionstack-frame

解决方案


这是一个非常好的观察(不管它的用处:))。回答您的问题的最佳方法是亲自查看:转储反汇编(dis.dis(quux)在两个版本中使用)。您会注意到两个版本的重要区别是在第一个版本中加载的闭包。这是因为您在列表理解对象中引用了变量 i ,并且通过这样做您使 ia 成为闭包的一部分,并且列表 comp 可以访问它。在第二种情况下,没有这样的事情,所以你得到那个错误。

对于第二部分,既然您理解了,您可能想重新措辞一下?


推荐阅读