Подтвердить что ты не робот

Итерация по элементам словаря(), значениям(), keys() в Python 3

Если я правильно понял, в Python 2, iter(d.keys()) был таким же, как d.iterkeys(). Но теперь d.keys() - это представление, которое находится между списком и итератором. Какая разница между представлением и итератором?

Другими словами, в Python 3, какая разница между

for k in d.keys()
    f(k)

и

for k in iter(d.keys())
    f(k)

Также, как эти различия обнаруживаются в простом цикле for (если вообще)?

4b9b3361

Ответ 1

Я не уверен, что это довольно ответ на ваши вопросы, но, надеюсь, он немного объясняет разницу между Python 2 и 3 в этом отношении.

В Python 2, iter(d.keys()) и d.iterkeys() не совсем эквивалентны, хотя они будут вести себя одинаково. В первом случае keys() вернет копию словарного списка ключей, а iter вернет объект итератора по этому списку, а вторая копия полного списка ключей никогда не будет построена.

Объекты представления, возвращаемые d.keys() в Python 3, являются итерабельными (т.е. итератор может быть сделан из них), поэтому, когда вы говорите for k in d.keys(), Python создаст для вас итератор. Поэтому ваши два примера будут вести себя одинаково.

Значение при изменении типа возврата для keys() заключается в том, что объект представления Python 3 является динамическим. т.е. если мы скажем ks = d.keys(), а затем добавим к d, то ks отразит это. В Python 2 keys() возвращает список всех ключей, находящихся в настоящее время в dict. Для сравнения:

Python 3

>>> d = { "first" : 1, "second" : 2 }
>>> ks = d.keys()
>>> ks
dict_keys(['second', 'first'])
>>> d["third"] = 3
>>> ks
dict_keys(['second', 'third', 'first'])

Python 2.x

>>> d = { "first" : 1, "second" : 2 }
>>> ks = d.keys()
>>> ks
['second', 'first']
>>> d["third"] = 3
>>> ks
['second', 'first']

Поскольку Python 3 keys() возвращает динамический объект, Python 3 не имеет (и не нуждается) отдельного метода iterkeys.

Дальнейшее уточнение

В Python 3, keys() возвращает объект dict_keys, но если мы используем его в контексте цикла for for k in d.keys(), то итератор неявно создается. Таким образом, разница между for k in d.keys() и for k in iter(d.keys()) является одним из неявных и явных создания итератора.

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

>>> ks = d.keys()
>>> 'first' in ks
True
>>> 'second' in ks
True
>>> i = iter(d.keys())
>>> 'first' in i
True
>>> 'second' in i
False             # because we've already reached the end of the iterator

Также обратите внимание, что если мы создадим явный итератор, а затем изменим dict, то итератор будет недействителен:

>>> i2 = iter(d.keys())
>>> d['fourth'] = 4
>>> for k in i2: print(k)
...
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
RuntimeError: dictionary changed size during iteration

В Python 2, учитывая существующее поведение keys, необходим отдельный метод, чтобы обеспечить способ итерации без копирования списка ключей, сохраняя при этом обратную совместимость. Следовательно, iterkeys()