pythonpython-3.xdictionarydictview

How to convert a dictionary into a subscriptable array?


I know how to convert a dictionary into a list in Python, but somehow when I try to get, say, the sum of the resulting list, I get the error 'dict_values' object is not subscriptable. Also, I plan to sum only several items in the list.

dict = {A:1, B:2, C:3, D:4}
arr = dict.values()
the_sum = sum(arr[1:3])

Upon closer inspection, I noticed that when the resulting list is printed out, it always gives dict_values(......) as the output which I can't remove. How do I get around this?


Solution

  • In Python 3, dict.values() returns a dict_values object, which is a view object providing a dynamic representation of the dictionary's values. This differs from Python 2, where it returned a list. The dict_values object offers several advantages and characteristics such as the followings:

    1. Dynamic View: It reflects real-time changes to the dictionary without creating a separate copy of the values.

    2. Memory Efficiency: As a view, it doesn't create a new list of values, saving memory.

    3. No Indexing or Slicing: Unlike lists, dict_values objects don't support indexing or slicing operations.

    While dict_values objects don't have specific optimizations for membership checking, the underlying PyDictValues structure in CPython contributes to efficient dictionary operations:

    typedef struct {
        uint8_t size;
        uint8_t embedded : 1;
        uint8_t valid : 1;
        uint8_t capacity;
        PyObject *values[1];
    } PyDictValues;
    

    Key optimizations in the CPython implementation include:

    1. Embedded Values: For small dictionaries, values might be stored directly in the object structure, improving access speed and memory usage.

    2. Capacity Management: The capacity field allows for efficient resizing operations.

    3. Valid Flag: Quick state checking for certain operations or consistency checks.

    4. Size Limitation: The assertion assert(size < 256) suggests an upper limit on the number of embedded values, balancing between optimization and general use cases.

    If you need list-like functionality, you can convert a dict_values object to a list:

    d = {'a': 1, 'b': 2, 'c': 3}
    values_list = list(d.values())
    print(sum(values_list[1:]))
    

    This conversion creates a new list object, allowing for indexing and slicing, but at the cost of additional memory usage and losing the dynamic view property.