Python 3.x's dictionary view objects and matplotlib
Question: In python 3.x `keys()`, `values()` and `items()` return
[views](https://docs.python.org/3/library/stdtypes.html#dict-views). Now while
views certainly have [advantages](http://stackoverflow.com/a/8960727/1622937),
they also seem to cause some compatibility issues. For example with
`matplotlib` (ultimately it's with `numpy`). As an example
[this](http://stackoverflow.com/a/16014873/1622937) and
[this](http://stackoverflow.com/a/21832451/1622937) 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](http://stackoverflow.com/questions/31753621/stackplot-using-list-of-
dictionary-values-python-3-x) 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?


Answer: 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.

