PYTHON:Globals().Items()迭代尝试更改字典
问题描述
在cso.data.__init__.py
中,我正在尝试执行以下操作:
from cso.data._features import * # import sumbodule
for k, v in globals().items():
if isinstance(v, entity):# entity is some type
print(k,v)
令我惊讶的是,我得到了:
Traceback (most recent call last):
File "X:ProgrammingworkspaceEclipsePyCommonSencesrccsodata\__init__.py", line 20, in <module>
from cso.data._features import *
File "X:ProgrammingworkspaceEclipsePyCommonSencesrccsodata\__init__.py", line 49, in <module>
for k, v in globals().items():
RuntimeError: dictionary changed size during iteration
出于某种原因,它试图以某种方式修改迭代的全局变量。怎么会这样呢?
有没有其他更好的方法来列出包中所有模块的name: value
形式的所有变量?
列表理解等效项工作正常,但打印两次:
print([ (k, v) for k, v in globals().items() if isinstance(v, entity)])
这里发生了什么?
解决方案
当您在全局范围内运行代码时,分配给的名称也是全局名称。k
和v
在开始迭代globals().items()
之后首先被分配,这将在globals()
词典中添加'k'
和'v'
的条目。
您可以通过在迭代前显式复制dict
来避免这种情况,例如:
for k, v in globals().copy().items():
或在函数中执行工作(该函数将在局部作用域中存储迭代变量):
def print_global_entities():
for k, v in globals().items():
if isinstance(v, entity):# entity is some type
print(k,v)
if __name__ == '__main__':
print_global_entities()
这样做实际上会加快代码的引导速度;在函数外部,k
和v
对k
和v
的每次存储和加载都涉及dict
查找,而在函数内部,Python可以(CPython引用解释器确实如此)使用简单的C数组查找和编译时计算的索引。
k
和v
预先存在,这样globals()
dict
就不会添加或删除项。您只需添加:
k = v = None
就在for
循环之前。
相关文章