Python 3.x's dictionary view objects and matplotlib

匿名 (未验证) 提交于 2019-12-03 02:18:01

问题:

In python 3.x keys(), values() and items() return views. Now while views certainly have advantages, they also seem to cause some compatibility issues. For example with matplotlib (ultimately it's with numpy). As an example this and this answers on stackexchange questions work just fine with python 2.x but raise an Exception when executing them in python 3.4.

A minimal example would be:

import matplotlib.pyplot as plt d = {1: 2, 2: 10} plt.scatter(d.keys(), d.values()) 

Which raises TypeError: float() argument must be a string or a number, not 'dict_values' with python 3.4.

While for the minimal example the Exception is quite clear, this question arises because of the same problem and here the Exception is a lot less clear: 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''

What is the best practice to deal with this issue? Can we hope that in a new release of matplotlib (or ultimately numpy) this issue will be dealt with or should we just start to write things like list(dict.values()) when using matplotlib just to be sure not to run into trouble with python 3.x?

回答1:

More of that 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' 

So the minimal example is:

np.array(d.keys(),dtype=float) 

Without the dtype specification

In [16]: np.array(d.keys()) Out[16]: array(dict_keys([1, 3]), dtype=object) 

The dict_keys is treated as an object. Usually you have to work at keeping np.array from treating an object as a list of numbers.

In [17]: np.fromiter(d.keys(),dtype=float) Out[17]: array([ 1.,  3.]) 

np.fromiter can handle d.keys(), treating it as a iterable. So there's some detail in how fromiter handles an iterable that is different from np.array.

A generator expression works the same way, e.g. (i for i in range(4)). fromiter can iterate through it, array either treats it as an object or raises an error.

If all the errors that the SO mentioned boiled down to np.array(...) handling a generator, then it might be possible to fix the behavior with one numpy change. Developers certainly wouldn't want to tweak every function and method that might accept a list. But it feels like a fundamental change that would have to be thoroughly tested. And even then it's likely to produce backward compatibility issues.

The accepted fix, for some time now, has been to pass your code through 2to3.

https://docs.python.org/2/library/2to3.html

for dictionaries:

Fixes dictionary iteration methods. dict.iteritems() is converted to dict.items(), dict.iterkeys() to dict.keys(), and dict.itervalues() to dict.values(). Similarly, dict.viewitems(), dict.viewkeys() and dict.viewvalues() are converted respectively to dict.items(), dict.keys() and dict.values(). It also wraps existing usages of dict.items(), dict.keys(), and dict.values() in a call to list.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!