Search code examples
pythondictionarysetenumerate

Why enumerate should accept a set as an input?


A pyton set is meant as not ordered, so why enumerate accepts them as input?

The same question would apply to dictionary.

From my point of view these are giving the false impression that there is a predictable way of enumerating them, but there is not.

This is quite misleading. I would have expected at least a warning from enumerate whens I request the enumerate(set) or enumerate(dict).

Can anyone explain why this warning is not there? is it "pythonic" to allow enumeration which can be not predictable?


Solution

  • There is a distinction between a container and its iterator. Technically, enumerate doesn't work with set, dict, or list, because none of those types is an iterator. They are iterable, though, meaning enumerate can get an iterator from each by implicitly using the iter function (i.e., enumerate(some_list_dict_or_set) == enumerate(iter(some_list_dict_or_set)))

    >>> iter([1,2,3])
    <list_iterator object at 0x109d924e0>
    >>> iter(dict(a=1, b=2))
    <dict_keyiterator object at 0x109d4b818>
    >>> iter({1,2,3})
    <set_iterator object at 0x109d53ab0>
    

    So while a given container may not have any inherent ordering of its elements, its iterator can impose an order, and enumerate simply pairs that ordering with a sequence of int values.

    You can really see the difference between inherent ordering and imposed ordering when comparing dict and OrderedDict in Python 3.7 or later. Both remember the order in which its keys were added, but that order isn't an important part of a dict's identity. That is, two dicts with the same keys and values mapped to those keys are equivalent, no matter what order the keys were added.

    >>> dict(a=1, b=2) == dict(b=2, a=1)
    True
    

    The same is not true of two OrderedDicts, which are only equal they have the same keys, the same values for those keys, and the keys were added in the same order.

    >>> from collections import OrderedDict
    >>> OrderedDict(a=1, b=2) == OrderedDict(b=2, a=1)
    False