Search code examples
python-3.xiteratorlist-comprehension

Python – next function – list comprehension


I am trying to understand why code written in a compact style works and the “same code-ish” in a more verbose style does not work.

This code yields the correct answer:

which_days = [5, 12, 19, 26]
buy_day = next((i for i in which_days if i in range(13, 20)), None)
print(buy_day)
>>> 19 <- correct answer

This code does yields a pair of brackets:

which_days = [5, 12, 19, 26]
buy_day = []
for i in which_days:
    if i in range((13, 20), None):
        next(which_days)
print(buy_day)
>>>[] <- This is a pair of brackets

Solution

  • Here is the long form of the correct code:

    which_days = [5, 12, 19, 26]
    def _tmp_variable():
        for i in which_days:
            if i in range(13, 20):
                yield i
    buy_day = next(_tmp_variable(), None)
    del _tmp_variable
    

    The incorrect code does not work because it is doing something entirely different (not to mention illegal; you can't call next() on a list in Python 3).

    Here's a different long form, which builds the entire list eagerly instead of lazily yielding one element at a time:

    which_days = [5, 12, 19, 26]
    _tmp_variable = []
    for i in which_days:
        if i in range(13, 20):
            _tmp_variable.append(i)
    buy_day = _tmp_variable[0] if _tmp_variable else None
    del _tmp_variable
    

    As you can see, this is wasteful because it builds up an entire list and then only uses the first element. Fortunately, the short version of your code does not do this.