Я не уверен, что это вполне ответ на ваши вопросы, но, надеюсь, это немного объясняет разницу между Python 2 и 3 в этом отношении.
В Python 2iter(d.keys())
и d.iterkeys()
не совсем эквивалентны, хотя они будут вести себя одинаково.В первом случае keys()
вернет копию списка ключей словаря, а iter
вернет объект-итератор над этим списком, а во втором копия полного списка ключей никогда не будет создана.
Объекты представления, возвращаемые d.keys()
в Python 3, являются iterable (т.е. из них можно сделать итератор), поэтому, когда вы говорите 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()