Search code examples
pythonlist-comprehensiondictionary-comprehension

How to implement comprehension in a class


As far as I know, comprehensions in Python only work with lists, dictionaries, tuples and sets. There is nothing on comprehension in the Python data model.

The syntax for tuples is quite interesting

>>> tuple(i for i in range(3))
(0, 1, 2)

Following the same pattern, I'd like to write a comprehension for my custom class.

>>> MySequence(i for i in range(3))
MySequence(0, 1, 2)
>>> MyMapping{str(i): i for i in range(3)}
MyMapping({'0': 0, '1': 1, '2': 2})

How can I achieve that?


Solution

  • You are mixing up two things that are not related: class instantiation and (generator-)comprehensions.

    tuple(i for i in range(3))
    

    is equivalent to

    tuple((i for i in range(3)))
    

    which is equivalent to

    generator = (i for i in range(3))
    tuple(generator)
    

    The generator-comprehension is evaluated before tuple.__init__ (or __new__) is called. In general, all arguments in Python are evaluated before being passed to a callable.

    Any class can accept an iterable (such as generators) for instantiation if you code __init__ accordingly, e.g.

    class AcceptIterable:
        def __init__(self, it):
            for x in it:
                print(x)
    

    Demo:

    >>> a = AcceptIterable(i for i in range(3))
    0
    1
    2
    >>> a = AcceptIterable([i for i in range(3)])
    0
    1
    2
    >>> a = AcceptIterable(range(3))
    0
    1
    2
    >>> a = AcceptIterable([0, 1, 2])
    0
    1
    2