【问题标题】:Why can't I iterate over locals() and within the iteration use returned item as a key?为什么我不能迭代 locals() 并在迭代中使用返回的项目作为键?
【发布时间】:2020-04-18 16:47:13
【问题描述】:

我有一个名为 Promotions 的模块,其中包含一些函数,并且我有一个变量来存储名称中包含“_promo”的所有函数的列表。

promos = [
    locals()[name] for name in locals() # Iterate over each name in the dictionary returned by locals()
    if name.endswith("_promo") # Select only names that end with the _promo suffix.
    ] 

当我在另一个地方导入促销并要求检索促销时,我得到一个KeyError

但是,如果我做同样的事情,但将 locals() 替换为 globals(),我不会得到 KeyError

有人知道为什么吗?

编辑: 是不是因为我第二次打电话给locals()(在locals()[name])我不在同一个范围内了?

【问题讨论】:

标签: python global local symbol-table


【解决方案1】:

是否因为我第二次调用 locals()(在 locals()[name] 中)我不再在同一个范围内?

确实如此。列表推导和函数一样有自己的作用域,但 locals() 上的迭代器是在外部作用域中创建的。

import inspect

class LoudIterable:
    def __iter__(self):
        print(inspect.currentframe())
        return iter([1, 2])

x = [print(inspect.currentframe()) for i in LoudIterable()]

# <frame at 0x0000021795BFD4B8, file '', line 5, code __iter__>
# <frame at 0x0000021795CF8AF8, file '', line 8, code <listcomp>>
# <frame at 0x0000021795CF8AF8, file '', line 8, code <listcomp>>

您会看到每次迭代都有相同的帧,但 __iter__ 在另一个帧中被调用。

当您想到生成器时,这是有道理的。

non_iterable = 2
x = (i for i in non_iterable)

iter 以急切的方式在可迭代对象上调用,即使我们还没有开始迭代,您也会立即看到错误: TypeError: 'int' object is not iterable

无论如何,简单的解决方法是这样的:

promos = [v for k, v in locals().items() if k.endswith("_promo")]

【讨论】:

    猜你喜欢
    • 2016-09-23
    • 2011-02-05
    • 2017-02-09
    • 1970-01-01
    • 2020-01-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-30
    相关资源
    最近更新 更多