为什么Python的字典迭代似乎使用了副本?
我对Python是怎么遍历这个字典的感到困惑。从Python的文档来看,itervalues会返回一个字典值的迭代器。
dict = {"hello" : "wonderful", "today is" : "sunny", "more text" : "is always good"}
for x in dict.itervalues():
x = x[2:]
print dict
这段代码打印出来的字典和原来的一样,没有变化。为什么会这样呢?如果我说位置x的值是“blabla”,为什么没有被设置呢?
3 个回答
1
正如Sven Marnach所提到的,字符串是不可变的,也就是说你不能改变它的内容。你只是把x
重新指向了一个通过切片操作创建的新字符串。你可以用id
来证明x
确实指向字典中的同一个对象:
>>> obj = 'hello'
>>> id(obj)
<<< 4318531232
>>> d = {'key': obj}
>>> [id(v) for v in d.values()]
<<< [4318531232]
>>> [id(v) for v in d.itervalues()]
<<< [4318531232]
>>> [(k, id(v)) for k, v in d.items()]
<<< [('key', 4318531232)]
>>> [(k, id(v)) for k, v in d.iteritems()]
<<< [('key', 4318531232)]
你可以使用iteritems
来同时遍历键和值,这样就能实现你想要的功能:
for k,v in dict.iteritems():
dict[k] = v[2:]
5
这行代码
x = x[2:]
只是创建了一个字符串的切片 x[2:]
,并把名字 x
重新指向这个新的字符串。它并没有改变之前 x
指向的字符串。(在Python中,字符串是不可变的,不能被修改。)
要实现你真正想要的效果,你需要让字典中的条目指向这个通过切片创建的新字符串对象:
for k, v in my_dict.iteritems():
my_dict[k] = v[2:]
7
这和字符串或列表没有关系。关键在于for
是怎么展开的。
做
for x in d.iteritems():
# loop body
基本上等同于做
iter = d.itervalues()
while True:
try:
x = next(iter)
# loop body
except StopIteration:
break
所以考虑到这一点,我们很容易看出,我们只是在重新给x
赋值,而x
保存的是一个函数调用的结果。
iter = d.itervalues()
while True:
try:
x = next(iter)
x = 5 # There is nothing in this line about changing the values of d
except StopIteration:
break