Search code examples
pythonpython-2.7python-3.4python-c-api

What can you do with a PyDictValues_Type?


While trying to convert some Python/C API code to work in both 2 & 3, I found that, given the following Python

DICT = { … }

class Example(object):
  ITEMS = DICT.values()

and then calling PyObject_GetAttrString(an_example, "ITEMS") would yield a PyObject for which PySequence_Check would return true in 2.7. Now in 3.4, it's yielding a PyObject whose type is PyDictValues_Type and PySequence_Check doesn't return true. The documentation on PyDictValues is, ahem, sparse. What can one do with it? It also response false to PyIter_Check.


Solution

  • In Python 2, dict.values() returns a list, but in Python 3, it's a view of dictionary values. The equivalent in Python 2.7 is dict.viewvalues().

    In particular views are not sequences because dictionaries don't have orders. So dict.viewkeys() and dict.viewitems() are set-like, because keys have to be unique. dict.viewvalues() is multi-set-like. You can iterate over it, get the length, and do contains checks against it. But you can't index into it like a sequence.