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

Я использую 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

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

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

5 ответов

Решение

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

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

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

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

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

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

При конвертации проекта в Python 3 с помощью 2to3Вы можете отключить это, исключив dict Исправление для более краткого вывода:

$ 2to3 -x dict *

Берегись iteritems(), iterkeys() https://docs.python.org/2/library/2to3.html и исправьте вручную.

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

КОРРЕКЦИЯ

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

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

Другие вопросы по тегам