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
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.