为什么我不能迭代 locals() 并在迭代中使用返回的项目作为键?
Why can't I iterate over locals() and within the iteration use returned item as a key?
我有一个名为 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]
)我已经不在同一个范围内了?
Is it because the second time I call locals() (in locals()[name]) I am no longer in the same scope?
正是如此。列表理解有它自己的作用域,就像函数一样,但是 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")]
我有一个名为 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]
)我已经不在同一个范围内了?
Is it because the second time I call locals() (in locals()[name]) I am no longer in the same scope?
正是如此。列表理解有它自己的作用域,就像函数一样,但是 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")]