Для словаря Python ли iterkeys предлагают какие-либо преимущества перед viewkeys?
В Python 2.7 словари имеют как метод iterkeys
, так и метод viewkeys
(и аналогичные пары для значений и элементов), предоставляя два разных способа лениво перебирать ключи словаря. Метод viewkeys
обеспечивает основную функцию iterkeys
, при этом iter(d.viewkeys())
эффективно эквивалентен d.iterkeys()
. Кроме того, объекты, возвращаемые viewkeys
, имеют удобные функции, подобные множеству. Таким образом, есть веские основания утверждать viewkeys
более iterkeys
.
Как насчет другого направления? Помимо совместимости с более ранними версиями Python, есть ли способы, в которых iterkeys
было бы предпочтительнее viewkeys
? Будет ли что-то потеряно, просто используя viewkeys
?
Ответы
Ответ 1
Нет, нет преимущества iterkeys
над viewkeys
, таким же образом, что нет никакого преимущества для keys
по любому из них. iterkeys
поддерживается только для совместимости. Действительно, в Python 3, viewkeys
является единственным поведением, которое все еще существует, и оно было переименовано в keys
- метод viewkeys
на самом деле является backport поведения Python 3.
Ответ 2
Словарь обновляет словаря, как и словарь, в то время как итератор не обязательно делает это.
Это означает, что если вы работаете с представлением, измените словарь, а затем снова работайте с представлением, представление изменится, чтобы отразить новое состояние словаря.
Они обеспечивают динамический просмотр записей словарей, что означает, что при изменении словаря представление отражает эти изменения. Источник
Пример:
>>> test = {1: 2, 3: 4}
>>> a = test.iterkeys()
>>> b = test.viewkeys()
>>> del test[1]
>>> test[5] = 6
>>> list(a)
[3, 5]
>>> b
dict_keys([3, 5])
Когда будут внесены изменения в размер, будет выбрано исключение:
>>> test = {1: 2, 3: 4}
>>> a = test.iterkeys()
>>> b = test.viewkeys()
>>> test[5] = 6
>>> list(a)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
RuntimeError: dictionary changed size during iteration
>>> b
dict_keys([1, 3, 5])
Также стоит отметить, что вы можете перебирать только одно ключевое слово:
>>> test = {1: 2, 3: 4}
>>> a = test.iterkeys()
>>> list(a)
[1, 3]
>>> list(a)
[]
>>> b = test.viewkeys()
>>> b
dict_keys([1, 3])
>>> b
dict_keys([1, 3])
Ответ 3
Функционально, как вы заметили, взгляды лучше. Совместимость - они хуже.
Некоторые показатели производительности, взятые из Python 2.7.2 на 64-разрядной машине Ubuntu:
>>> from timeit import timeit
Работа с пустым словарем:
>>> emptydict = {}
>>> timeit(lambda: emptydict.viewkeys())
0.24384498596191406
>>> timeit(lambda: list(emptydict.viewkeys()))
0.4636681079864502
>>> timeit(lambda: emptydict.iterkeys())
0.23939013481140137
>>> timeit(lambda: list(emptydict.iterkeys()))
1.0098130702972412
Построение представления немного дороже, но потребление представления значительно быстрее, чем итератор (бит в два раза быстрее).
Работа с тысячным элементом словаря:
>>> fulldict = {i: i for i in xrange(1000)}
>>> timeit(lambda: fulldict.viewkeys())
0.24295306205749512
>>> timeit(lambda: list(fulldict.viewkeys()))
13.447425842285156
>>> timeit(lambda: fulldict.iterkeys())
0.23759889602661133
>>> timeit(lambda: list(fulldict.iterkeys()))
15.45390510559082
Те же результаты, хотя и менее выраженные; построение обзора очень немного дороже, но потребление его довольно определенно быстрее (на 15% быстрее).
Для справедливого сравнения с list(dict.viewkeys())
и list(dict.iterkeys())
, dict.keys()
является отчетливым:
>>> timeit(lambda: emptydict.keys())
0.2385849952697754
>>> timeit(lambda: fulldict.keys())
7.842105150222778
Резюме: это компромисс; улучшенная функциональность (которую вы редко используете) и производительность (что будет очень редко быть достаточно значительным, чтобы вас беспокоить), если вы заботитесь о таких вопросах производительности, вы, вероятно, уже находитесь в регионе, где вам нужно работать с numpy/scipy ) против лучшей совместимости и использования памяти мышц.
Лично, если уже в зависимости от функциональности с 2,7 или если я полностью контролирую среду выполнения, я бы избегал словарных представлений в коде Python 2. Даже в этих случаях мои пальцы все еще хотят набрать iter
вместо view
, поэтому я даю им!
Ответ 4
Как видно из названия (и ), методы viewkeys()
, viewvalues()
и viewitems()
возвращают представление о текущих элементах словаря, что означает что если словарь изменяется, то и вид; просмотров lazy. В общем случае вид ключей задан, и представления элементов только заданы, если значения хешируются.
В каких случаях лучше использовать стандартные методы keys()
, values()
и items()
? Вы упомянули очень важную: обратную совместимость. Кроме того, когда вам нужно иметь простой список всех ключей, значений или элементов (а не как набор, а не итератор), когда вам нужно изменить возвращенный список без изменения оригинального словаря и когда вам нужен снимок словарные ключи, значения или элементы в момент времени, независимо от любых последующих модификаций по словарю.
А как насчет iterkeys()
, itervalues()
и iteritems()
? Они являются подходящей альтернативой, когда вам нужен однократный, постоянный пробел, ленивый снимок итератора содержимого словаря, который скажет вам, изменился ли словарь во время итерации (через RuntimeError
), также они очень важны для обратной совместимости.