Почему итерация словаря python, похоже, работает с копией? - PullRequest
7 голосов
/ 10 августа 2011

Я запутался, как 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 - «блабла», почему оно не устанавливается?

Ответы [ 3 ]

7 голосов
/ 10 августа 2011

Это не имеет никакого отношения к строкам или спискам. Дьявол в том, как разворачивается for.

делает

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

более или менее эквивалентно действию

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

Таким образом, учитывая это, не очень сложно понять, что мы просто переназначаем 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
5 голосов
/ 10 августа 2011

Единственная строка

x = x[2:]

делает создание фрагмента строки x[2:] и связывает имя x, чтобы указать на эту новую строку. Это не меняет строку x, указанную ранее. (Строки неизменны в Python, их нельзя изменить.)

Чтобы достичь того, чего вы на самом деле хотите, вам нужно сделать точку входа в словарь новым строковым объектом, созданным нарезкой:

for k, v in my_dict.iteritems():
    my_dict[k] = v[2:] 
1 голос
/ 10 августа 2011

Как указывает Свен Марнах , строки являются неизменяемыми, и вы просто привязываете x к новой строке, созданной нотацией среза.Вы можете продемонстрировать, что x действительно указывает на один и тот же объект в словаре, используя 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)]

. Вы можете использовать iteritems, чтобы перебрать ключ и значение вместеделать то, что вы хотите:

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