En las keys()
Python 3.x keys()
, los values()
y los items()
devuelven vistas . Ahora, mientras que las vistas ciertamente tienen ventajas , también parecen causar algunos problemas de compatibilidad. Por ejemplo con matplotlib
(en última instancia, es con numpy
). Como ejemplo, esto y las respuestas en las preguntas de stackexchange funcionan bien con python 2.x pero generan una excepción al ejecutarlas en python 3.4.
Un ejemplo mínimo sería:
import matplotlib.pyplot as plt d = {1: 2, 2: 10} plt.scatter(d.keys(), d.values())
Lo que plantea el TypeError: float() argument must be a string or a number, not 'dict_values'
con python 3.4.
Mientras que para el ejemplo mínimo la Excepción es bastante clara, esta pregunta surge debido al mismo problema y aquí la Excepción es mucho menos clara: TypeError: ufunc 'isfinite' not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule ''safe''
¿Cuál es la mejor práctica para tratar este problema? ¿Podemos esperar que en una nueva versión de matplotlib
(o en última instancia, numpy
) este problema se numpy
o deberíamos comenzar a escribir cosas como la list(dict.values())
cuando se usa matplotlib
solo para asegurarnos de no tener problemas? con python 3.x?
Más de ese error:
--> 512 return array(a, dtype, copy=False, order=order, subok=True) 513 514 def ascontiguousarray(a, dtype=None): TypeError: float() argument must be a string or a number, not 'dict_values'
Entonces el ejemplo mínimo es:
np.array(d.keys(),dtype=float)
Sin la especificación dtype
In [16]: np.array(d.keys()) Out[16]: array(dict_keys([1, 3]), dtype=object)
Las dict_keys
se tratan como un object
. Por lo general, debe trabajar para evitar que np.array
trate un objeto como una lista de números.
In [17]: np.fromiter(d.keys(),dtype=float) Out[17]: array([ 1., 3.])
np.fromiter
puede manejar d.keys()
, tratándolo como un iterable. Así que hay algunos detalles sobre cómo fromiter
maneja un iterable que es diferente de np.array
.
Una expresión generadora funciona de la misma manera, por ejemplo (i for i in range(4))
. fromiter
puede iterar a través de él, la array
lo trata como un objeto o genera un error.
Si todos los errores que el SO mencionado se redujeron a np.array(...)
manejar un generador, entonces es posible corregir el comportamiento con un numpy
cambio de número. Los desarrolladores ciertamente no querrían modificar cada función y método que pueda aceptar una lista. Pero se siente como un cambio fundamental que debería ser probado a fondo. E incluso entonces es probable que produzca problemas de compatibilidad hacia atrás.
La solución aceptada, desde hace algún tiempo, ha sido pasar su código a través de 2to3
.
https://docs.python.org/2/library/2to3.html
para los diccionarios:
Corrige los métodos de iteración del diccionario. dict.iteritems () se convierte en dict.items (), dict.iterkeys () en dict.keys () y dict.itervalues () en dict.values (). De manera similar, dict.viewitems (), dict.viewkeys () y dict.viewvalues () se convierten respectivamente en dict.items (), dict.keys () y dict.values (). También envuelve los usos existentes de dict.items (), dict.keys () y dict.values () en una llamada a la lista.