python python-3.x python-2to3

python 3 list



por qué Python 3 necesita envolver dict.items con list() (5)

Estoy usando Python 3. Acabo de instalar algunos IDE de Python y tengo curiosidad acerca de la siguiente advertencia de código:

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

La advertencia es: "Para Python3, el soporte debería verse como ... list(features.items()) "

También hay mención sobre esto http://docs.python.org/2/library/2to3.html#fixers

También ajusta los usos existentes de dict.items (), dict.keys () y dict.values ​​() en una llamada a la lista.

¿Por qué es tan necesario?



En Python 2, los métodos items() , keys() y values() solían "tomar una instantánea" de los contenidos del diccionario y devolverlo como una lista. Significaba que si el diccionario cambiaba mientras estaba iterando sobre la lista, los contenidos en la lista no cambiarían.

En Python 3, estos métodos devuelven un view cuyo contenido cambia dinámicamente a medida que cambia el diccionario . Por lo tanto, para que el comportamiento de las iteraciones sobre el resultado de estos métodos siga siendo coherente con las versiones anteriores, se debe realizar una llamada adicional a list() en Python 3 para "tomar una instantánea" del contenido del objeto de vista.


Puede ignorar de forma segura esta advertencia de "precauciones adicionales": su código funcionará igual incluso sin una list en ambas versiones de Python. Sería diferente si necesitaras una lista (pero este no es el caso): de hecho, features.items() es una lista en Python 2, pero una view en Python 3. Funcionan igual cuando se usan como iterable, como en tu ejemplo.

Ahora, la herramienta de conversión de Python 2 a Python 3 2to3 equivocada por el lado de la seguridad, y asume que realmente quería una lista cuando usa dict.items() . Este puede no ser el caso (como en la pregunta), en cuyo caso dict.items() en Python 3 (sin list dict.items() ) es mejor (más rápido y menos consumo de memoria, ya que no se dict.items() ninguna lista).

Concretamente, esto significa que el código de Python 2 puede iterar explícitamente sobre la vista: for k, v in features.viewitems() (que se convertirá en Python 3 por 2to3 a features.items() ). Parece que tu IDE cree que el código es Python 2, porque tu declaración es muy buena, en Python 3, por lo que no debería haber ninguna advertencia sobre el soporte de Python 3.


Python 3 devuelve un objeto de vista de diccionario en lugar de una lista que devolvería Python 2 y algunos operadores que cabría esperar que no sean ciertos; también un objeto de vista cambiará si el diccionario subyacente cambia (posiblemente en el código que está iterando a través que podría causar algunas sorpresas desagradables).


En Python 3, dict.items() , dict.keys() y dict.values() son iteradores. Por lo tanto, si está esperando una lista, es posible que obtenga algunos errores al realizar operaciones que funcionen en listas, pero no necesariamente en iteradores, como len(dict.items()) (generará un TypeError ).

CORRECCIÓN

Los dict_items devueltos al llamar a dict.items() en Python 3 sí tienen un __len__() y no generarán un TypeError . El objeto dict_items no es una lista, sin embargo, y no tiene métodos de list , como append() , index() , etc ...

Además, como las otras (diría mucho mejor) respuestas de Hamidi y del estado de Barnes, dict_items es un objeto de vista que cambiará dinámicamente cuando se modifique el dict .