[PYTHON] How to get rid of long comprehensions

Long inclusions are tough

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?

Generator + collector

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)

More concise

↑ 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

Former story

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

How to get rid of long comprehensions
How to get rid of server custom emoji in message.content
How to get dictionary type elements of Python 2.7
Get rid of python's KeyError
manage to get rid of heavy pyls in vim-lsp
[Linux] [C / C ++] Summary of how to get pid, ppid, tid
How to get a list of built-in exceptions in python
How to get an overview of your data in Pandas
How to get a list of links from a page from wikipedia
How to get a quadratic array of squares in a spiral!
Get rid of slow scp -pr
Summary of how to use pandas.DataFrame.loc
Summary of how to use pyenv-virtualenv
How to get the Python version
How to get started with Scrapy
How to get started with Python
How to get started with Django
Summary of how to use csvkit
How to get the ID of Type2Tag NXP NTAG213 with nfcpy
[Python] How to get divisors of natural numbers at high speed
[Python] How to get the first and last days of the month
Here's a brief summary of how to get started with Django
How to save only a part of a long video using OpenCV
How to get the vertex coordinates of a feature in ArcPy
Python techniques for those who want to get rid of beginners
How to get rid of the "Tags must be an array of hashes." Error in the qiita api
[Python] Summary of how to use pandas
How to speed up instantiation of BeautifulSoup
How to get parent id with sqlalchemy
How to check the version of Django
How to get IP when Tornado + nginx
How to install CatBoost [as of January 2020]
How to calculate Use% of df command
How to get a stacktrace in python
[Python2.7] Summary of how to use unittest
How to get colored output to the console
Jupyter Notebook Basics of how to use
Basics of PyTorch (1) -How to use Tensor-
Summary of how to use Python list
[Python2.7] Summary of how to use subprocess
How to get started with laravel (Linux)
Summary of how to write AWS Lambda
Get rid of DICOM images in Python
[Question] How to use plot_surface of python
How to calculate the volatility of a brand
How to use folium (visualization of location information)
How to find the area of the Voronoi diagram
[Python] How to use two types of type ()
Summary of how to import files in Python 3
How to get results from id in Celery
[NNabla] How to get the output (variable) of the middle layer of a pre-built network
[Django] How to get data by specifying SQL.
How to get help in an interactive shell
Not much mention of how to use Pickle
Summary of how to use MNIST in Python
[Python] Get rid of dating with regular expressions
How to specify attributes with Mock of python
How to implement "named_scope" of RubyOnRails with Django
How to get article data using Qiita API
I want to get League of Legends data ③
I want to get League of Legends data ②