Почему Python 3 нуждается в том, чтобы dict.items был обернут списком()?

Я использую Python 3. Я только что установил Python IDE, и мне интересно узнать следующее предупреждение:

features = { ... }
for k, v in features.items():
    print("%s=%s" % (k, v))

Предупреждение: "Для поддержки Python3 должен выглядеть как... list(features.items()) "

Также упоминается об этом на http://docs.python.org/2/library/2to3.html#fixers

Он также обертывает существующие обычаи dict.items(), dict.keys() и dict.values() в вызове списка.

Почему это необходимо?

Ответ 1

Вы можете смело игнорировать это предупреждение "Дополнительные меры предосторожности": ваш код будет работать одинаково даже без list в обеих версиях Python. Это было бы иначе, если бы вам нужен список (но это не так): на самом деле, features.items() - это список в Python 2, но представление в Python 3. Они работают одинаково, когда используются как итеративные, как в вашем примере.

Теперь инструмент 2to3 преобразования Python 2 в Python 3 ошибается на стороне безопасности и предполагает, что вам действительно нужен список, когда вы используете dict.items(). Это может быть не так (как в вопросе), и в этом случае dict.items() в Python 3 (без list обертывания) лучше (быстрее и меньше потребляет память, так как не dict.items() список).

Конкретно это означает, что код Python 2 может явно перебирать представление: for k, v in features.viewitems() (которые будут преобразованы в Python 3 на 2to3 в features.items()). Похоже, ваша IDE думает, что код Python 2, потому что ваш оператор for очень хорош, в Python 3, поэтому не должно быть предупреждения о поддержке Python 3.

Ответ 2

В Python 2 методы items(), keys() и values() используются для "получения моментального снимка" содержимого словаря и возврата его в виде списка. Это означало, что если словарь изменился во время повторного просмотра списка, содержимое в списке не изменилось бы.

В Python 3 эти методы возвращают объект вида, содержимое которого динамически изменяется при изменении словаря. Поэтому для того, чтобы поведение итераций в результате этих методов оставалось согласованным с предыдущими версиями, в Python 3 необходимо выполнить дополнительный вызов list() для "получения моментального снимка" содержимого объекта представления.

Ответ 3

Python 3 возвращает объект View View Dictionary, а не список, который будет возвращать Python 2, и некоторые операторы, которые вы ожидаете, могут быть неверными. Также объект View Object будет меняться, если изменяется базовый словарь (возможно, в коде, который вы повторяете через что может вызвать некоторые неприятные сюрпризы).

Ответ 4

В Python 3, dict.items(), dict.keys() и dict.values() являются итераторами. Поэтому, если вы ожидаете список, вы можете получить некоторые ошибки при выполнении операций, которые работают над списками, но не обязательно на итераторах, таких как len(dict.items()) (создаст TypeError).

КОРРЕКЦИЯ

dict_items возвращаемые вызовом dict.items() в Python 3, действительно имеют __len__() и не будут генерировать TypeError. dict_items объект dict_items не является списком и не имеет методов list, таких как append(), index() и т.д....

Кроме того, как и другие (я бы сказал гораздо лучше) ответы Хамиди и состояния Барнса, dict_items - это объект вида, который будет динамически изменяться при изменении dict.

Ответ 5

При преобразовании проекта в python 3 с использованием 2to3 вы можете отключить его, исключив фиксатор dict для более сжатого вывода:

$ 2to3 -x dict *

Следите за iteritems(), iterkeys() https://docs.python.org/2/library/2to3.html#2to3fixer-dict и исправляйте вручную.