Python 3.0 - методы dict возвращают представления - почему? - PullRequest
12 голосов
/ 04 декабря 2008

методы dict dict.keys (), dict.items () и dict.values ​​() возвращают «просмотры» вместо списков. http://docs.python.org/dev/3.0/whatsnew//3.0.html

Прежде всего, как представление отличается от итератора? Во-вторых, в чем выгода этого изменения? Это только из соображений производительности?

Это не кажется мне интуитивно понятным, то есть я прошу список вещей (дайте мне все ваши ключи), и я возвращаю что-то еще. Это смущает людей?

Ответы [ 3 ]

13 голосов
/ 04 декабря 2008

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

Это так же, как это реализовано в Java (и, вероятно, во многих других языках / средах).

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

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

6 голосов
/ 26 января 2012

Ответ Йоахима Зауэра очень хорошо объясняет, почему list не возвращается. Но остается вопрос, почему эти функции не будут возвращать итераторы, как iteritems и т. Д. В Python 2.

Итератор гораздо более строг, чем контейнер. Например, итератор не допускает более одного прохода; если вы попробуете второй проход, вы обнаружите, что он пуст. Следовательно, такие операции, как elem in cont, поддерживаются контейнерами, но не могут поддерживаться итераторами: как только вы проверяете, находится ли элемент в итераторе, итератор уничтожается!

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

Объект view обладает лучшим из обоих миров: он ведет себя как контейнер, но при этом не создает копию словаря! Фактически, это своего рода виртуальный контейнер, доступный только для чтения, который работает путем ссылки на базовый словарь. Я не знаю, видел ли это где-нибудь еще в стандартном Python.

Edit:

@ AntonyHatchkins: причина, по которой он не возвращает функцию генератора, заключается в том, что она не позволяет выполнять быструю in операцию. Да, in работает для функций генератора (когда вы их вызываете). То есть вы можете сделать это:

def f():
  for i in range(10):
    yield i

5 in f() # True

Но в соответствии с определением in, если правая сторона является генератором, python будет проходить через все элементы n генератора, что приведет к O(n) сложности времени. Вы ничего не можете с этим поделать, потому что это единственное осмысленное поведение произвольного генератора.

С другой стороны, в случае представления словаря вы можете реализовать in любым удобным вам способом, потому что вы знаете больше о данных, которыми вы управляете. И на самом деле in реализован со сложностью O(1) с использованием хеш-таблицы. Вы можете проверить это, запустив

>>> d = dict(zip(range(50000000), range(50000000)))
>>> 49999999 in d
True
>>> 49999999 in iter(d) # kinda how generator function would work
True
>>>

и замечая, как быстро первое in сравнивается со вторым in.

0 голосов
/ 24 октября 2014

Как уже упоминалось в связанном вопросе, представление имеет метод len(), которого нет в итераторе (пока в списке есть).

Еще одно преимущество возврата представления вместо списка состоит в том, что по крайней мере для ключей он имеет оптимизированное тестирование членства в операциях O (1) вместо O (N) для списка (или итератора).

...