Ответ 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()