In Python, collections are generally generated in comprehensions (I think).
But when it gets a little complicated, the comprehensions are hard to read.
#Forcibly include the Fizz Buzz list
fb = ["Fizz Buzz" if i % 15 == 0 
      else "Fizz" if i % 3 == 0 
      else "Buzz" if i % 5 == 0 
      else i 
      for i in range(30)]
In this case, it is easier to see if you write a for statement.
However, the writing style of making small changes while exposing the object before initialization is somewhat guilty (if the functional preference is strong).
fb = []
for i in range(30):
    if i % 15 == 0:
        fb.append("Fizz Buzz")
    elif i % 3 == 0:
        fb.append("Fizz")
    elif i % 5 == 0:
        fb.append("Buzz")
    else:
        fb.append(i)
what to do?
It is possible to define a generator with yield and create a collection based on it.
def _fb():
    for i in range(30):
        if i % 15 == 0:
            yield "Fizz Buzz"
        elif i % 3 == 0:
            yield "Fizz"
        elif i % 5 == 0:
            yield "Buzz"
        else:
            yield i
fb = list(_fb)
↑ is not bad, but after defining the generator, the procedure of assigning it to a variable through the list function is complicated.
Also, if you forget to list it and receive the iterator directly as a variable, it can be a hotbed of bugs.
I want the definition using yield to be interpreted as the definition of the list as it is.
This can be achieved with a decorator.
def comprehension(collector):
    def ret(func):
        return collector(func())
    return ret
#When you execute the following, the list is assigned to the variable "fb".
@comprehension(list)
def fb():
    for i in range(30):
        if i % 15 == 0:
            yield "Fizz Buzz"
        elif i % 3 == 0:
            yield "Fizz"
        elif i % 5 == 0:
            yield "Buzz"
        else:
            yield i
The first source material is the decorator called collecting in the library funcy. Turn the generator function into a function that returns a list. With it, Fizz Buzz can be written as:
from funcy import collecting
@collecting
def _fb():
    for i in range(30):
        if i % 15 == 0:
            yield "Fizz Buzz"
        elif i % 3 == 0:
            yield "Fizz"
        elif i % 5 == 0:
            yield "Buzz"
        else:
            yield i
fb = _fb()
However, it is troublesome to define the function once.
Racket's [for / list](https://docs.racket-lang.org/reference/for.html#%28form._%28%28lib._racket%2Fprivate%2Fbase..rkt%29._for%2Flist% I thought if I could write something like 29% 29), I came up with a solution that does not return a function with a decorator.
Recommended Posts