[GO] Deep nesting in Python makes it hard to read

Deep nesting in Python makes it hard to read

Introduction

When I'm writing Python, I often think that the nesting is deep and difficult to read. Specifically, it is the following cases.


for group in groups:
    for member in group.members:
        for article in member.articles:
            for tag in article.tags:
                """
Various processing
                """

Wouldn't it be nice if this looks like this?


for group, member, article, tag in func(groups):
    """
Various processing
    """

However, I think there is a question, "How can I control the for statement by myself?", So I would like to explain from there.

Implementation

Some programming languages, including Python, have iterators and generators. For Python, the following articles will be helpful. Python Iterators and Generators

This time, we will implement it using this generator.

First, lightly check the operation.


def my_generator():
    yield 10
    yield 20
    yield 30

for num in my_generator():
   print(num)

"""Output result
10
20
30
"""

You can see that the values ​​passed in yield are the arguments of the for statement one after another.

Based on this, after passing the sample groups, create a function that expands to tag and passes it to the argument of for.

def group_generator(groups):
    for group in groups:
        for member in group.members:
            for article in member.articles:
                for tag in article.tags:
                    yield group, member, article, tag


for group, member, article, tag in group_generator(groups):
    print(group)
    print(member)
    print(article)
    print(tag)

Now you have a shallow source code. Let's generalize this further. group_generatorIn generalizing, after the second for statement, the process of extracting the next iterable object from a certain value and turning it with the for statement is common, and you can see that it is recursive. Also, it seems that it can be implemented well by using the yeild part as the base case of the recursive function.

202007_-179.jpg

** Processing to extract the next Iterable object from a certain value ** is iterable_creators, ** Base object ** is `base_iterable```, ** Recursive part ** When implemented as a nest_recursive``` function, it looks like this: If you want to call the generator function inside the function, use `` yield from` ``.

def nests(base_iterable, *iterable_creators):
    def nest_recursive(nested_items: Tuple, current_item, level: int):
        try:
            iterable_creator = iterable_creators[level]
            next_iterable = iterable_creator(current_item)
            for next_item in next_iterable:
                new_stuck = (*nested_items, next_item)
                yield from nest_recursive(new_stuck, next_item, level + 1)
        except IndexError:
            yield nested_items

    for root_item in base_iterable:
        yield from nest_recursive((root_item,), root_item, level=0)

Let's actually use it.

iterable_creators = (lambda group: group.members, lambda member: member.articles, lambda article: article.tags)
for group, member, article, tag in nests(groups, *iterable_creators):
    print(group)
    print(member)
    print(article)
    print(tag)

The nesting has been removed to make it easier to read. It is doubtful whether it is practical, but it was a good study for the generator.

Recommended Posts

Deep nesting in Python makes it hard to read
Read big endian binary in Python and convert it to ndarray
Read DXF in python
I was able to repeat it in Python: lambda
How to read csv containing only integers in Python
A module that makes it easier to write Perl-like filter programs in Python fileinput
To flush stdout in Python
Login to website in Python
Read Euler's formula in Python
Read Outlook emails in Python
Speech to speech in python [text to speech]
How to develop in Python
Nesting ternary operators in python
Read Fortran output in python
Post to Slack in Python
[R] [Python] Memo to read multiple csv files in multiple zip files
Object-oriented in C: Refactored "○ ✕ game" and ported it to Python
[Python] How to do PCA in Python
processing to use notMNIST data in Python (and tried to classify it)
How to install OpenCV on Cloud9 and run it in Python
Read Protocol Buffers data in Python3
Convert markdown to PDF in Python
How to use SQLite in Python
Read PNG chunks in Python (class)
In the python command python points to python3.8
Try to calculate Trace in Python
How to use Mysql in python
How to wrap C in Python
How to use ChemSpider in Python
6 ways to string objects in Python
How to use PubChem in Python
Read files in parallel with Python
Articles to read when Blender Python script code doesn't work in 2.80
How to handle Japanese in Python
An alternative to `pause` in Python
Create and read messagepacks in Python
[TensorFlow 2] It is recommended to read features from TFRecord in batch units.
Read CSV file with Python and convert it to DataFrame as it is
I tried to implement PLSA in Python
Try logging in to qiita with Python
How to access environment variables in Python
Tips to make Python here-documents easier to read
I tried to implement permutation in Python
How to read pydoc on python interpreter
How to dynamically define variables in Python
How to do R chartr () in Python
Pin current directory to script directory in Python
[Itertools.permutations] How to put permutations in Python
PUT gzip directly to S3 in Python
Send email to multiple recipients in Python (Python 3)
Convert psd file to png in Python
Sample script to trap signals in Python
I tried to implement PLSA in Python 2
To set default encoding to utf-8 in python
Decorator to avoid UnicodeEncodeError in Python 3 print ()
How to work with BigQuery in Python
Log in to Slack using requests in Python
How to get a stacktrace in python
How to display multiplication table in python
Easy way to use Wikipedia in Python
How to extract polygon area in Python