我有一个函数,想要传递给它的参数。我尝试通过locals()
实现这一目标,但我最终获得了locals()
的密钥,而不是价值对:
>>>def print_params(i,j,k):
for x in locals():
print(x)
>>>print_params('a','b','c')
j
i
k #<--I want to get back 'a','b','c'.
我希望从locals()
获取值而不是键。
正常的词典,我知道我可以这样做:
>>> m = {
... 'a' : 'b',
... 'y' : 'z'}
>>> m
{'a': 'b', 'y': 'z'}
>>> for x in m:
... print(x)
...
a # <--Keys
y
>>> for x in m:
... print(m[x])
...
b # <--Values
z
但是,如果我使用locals()
尝试此操作,则会创建一个RuntimeError。
>>> def print_args(i,j,k):
... for x in locals():
... print(locals()[x])
...
>>> print_args('a','b','c')
b # <--Got one!
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in y
RuntimeError: dictionary changed size during iteration
有人能解释一下发生了什么吗?从我打印的单个值(在它出错之前),我可以看到当循环尝试迭代到locals()
的下一个元素时出现错误;然后,随着dict被修改,它失去了它的位置。但是,我无法理解为什么字典大小应该改变。我推断,在每次通过for
循环时,变量x
被销毁,然后重新创建以便下一次循环通过循环。然而,这看起来很奇怪,因为我认为保持x
&#34;活着&#34;会更有效率。并在每次迭代时将其重新分配给新值。
最终,我想我可以做local_args = locals()
,但我仍然很好奇究竟发生了什么阻止我简单地循环locals()
。我不确定我是否正确x
被摧毁/重建;如果我是,我不得不想知道为什么会这样,如果我不是,那么我对于发生的事情更加好奇。
答案 0 :(得分:1)
有人可以解释发生了什么吗?从我打印的单个值(在它出错之前),我可以看到当循环尝试迭代到locals()的下一个元素时出现错误;然后,随着dict被修改,它失去了它的位置。但是我无法理解为什么字典大小应该改变。我推断,在每次通过for循环时,变量x都被破坏,然后重新创建,以便下一次循环通过循环。然而,这看起来很奇怪,因为我认为保持x“活着”并且在每次迭代时将其重新分配给新值会更有效。
变量x
只创建一次,但是在开始迭代locals()
之后才会创建它,因为for
循环的源迭代在任何事情之前都会被评估分配给循环变量。然而,错误消息是由dict本身(或者更确切地说,它的迭代器)引发的:当某些东西试图迭代它并且自上次迭代以来它已经改变时它会“注意到”。那么会发生什么:
locals()
被评估并为您提供词典for
循环在dict上创建一个迭代器并获取第一个元素x
并将其设置为第一个元素for
循环尝试从dict迭代器中获取另一个元素x
),因此它引发了错误。一个简单的解决方法是在循环之前创建带有一些虚拟值的变量x
。然后它会在您访问locals()
之前就已存在,并且在循环期间不会创建新变量:
def print_args(i,j,k):
x = None
for x in locals():
print(locals()[x])
>>> print_args('a', 'b', 'c')
a
x
c
b
当然,请注意,在此迭代过程中,您自己也会获得x
。
正如其他人在评论中提到的那样,为什么你这样做根本就不清楚。 locals()
是一个相当滑的野兽,通常,如果你想要完成一些实际任务,有一种更好的方法可以不使用locals()
。
答案 1 :(得分:0)
当您致电for x in locals()
时,会对locals()
进行评估,然后将其第一项存储在x
中。之前未定义x
,因此在第一个循环期间将其添加到locals
字典,第二个循环通知更改。
解决此问题的一种方法是预先复制locals
字典,如您所述:
def print_args(i,j,k):
local_args = dict(locals())
for x in local_args:
print(local_args[x])
print_args('a','b','c')