Вопрос

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

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

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

Это было полезно?

Решение

Фактически вы получаете список.Это просто не копия внутреннего списка, а нечто, что действует так, как будто это список, но представляет только внутреннее состояние.

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

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

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

Другие советы

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

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

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

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

Редактировать:

@Антонихэтчкинс:причина, по которой он не возвращает функцию генератора, заключается в том, что он не допускает быстрого 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.

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top