开发者

Why does python's dictionary iteration seemingly work with a copy?

I am confused how python is iterating through this dictionary. From python's documentation, the itervalues returns an iterator over the dictionary's valu开发者_开发百科es.

dict = {"hello" : "wonderful", "today is" : "sunny", "more text" : "is always good"}

for x in dict.itervalues():
    x = x[2:]   

print dict

This prints out the original dictionary unchanged. Why is that? If I am saying the value at position x is "blabla", why is it not getting set?


This has nothing to do with strings or lists. The devil is in how the for is unfolded.

Doing

for x in d.iteritems():
    # loop body

is more-or-less equivalent to doing

iter = d.itervalues()
while True:
    try:
        x = next(iter)
        # loop body
    except StopIteration:
        break

So with this in mind it's not very hard to see that we are just reassigning x, which holds a result from a function call.

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


The only thing the line

x = x[2:]

does is creating the string slice x[2:] and rebinding the name x to point to this new string. It does not change the string x pointed to before. (Strings are immutable in Python, they can't be changed.)

To achieve what you actually want, you need to make the dictionary entry point to the new string object created by the slicing:

for k, v in my_dict.iteritems():
    my_dict[k] = v[2:] 


As Sven Marnach points out, strings are immutable and you are just rebinding x to a new string created by the slice notation. You can demonstrate that x does point to the same object in the dictionary by using id:

>>> 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)]

You can use iteritems to iterate over key and value together to do what you want:

for k,v in dict.iteritems():
    dict[k] = v[2:]
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜