How to indent Python list-comprehensions?

List comprehensions can be useful in certain situations, but they can also be rather horrible to read.. As a slightly exaggerated example, how would you indent the following?

allUuids = [x.id for x in self.db.query(schema.allPostsUuid).execute(timeout = 20) if x.type == "post" and x.deleted is not False]


Asked by: Arthur780 | Posted: 24-09-2021






Answer 1

It depends on how long they are. I tend to structure them like so:

[x.id for x
 in self.db.query(schema.allPostsUuid).execute(timeout=20)
 if x.type == 'post' 
    and x.deleted is not False
    and ...
    and ...]

That way every expression has its own line.

If any line becomes too big I like to extract it out in a lambda or expression:

transform = lambda x: x.id
results = self.db.query(schema.allPostsUuid).execute(timeout=20)
condition = lambda x: x.deleted is not False and ... and ...
[transform(x) for x in results if condition(x)]

And then if a lambda becomes too long it gets promoted to a function.

Answered by: Carina789 | Posted: 25-10-2021



Answer 2

Where I work, our coding guidelines would have us do something like this:

all_posts_uuid_query = self.db.query(schema.allPostsUuid)
all_posts_uuid_list = all_posts_uuid_query.execute(timeout=20)
all_uuid_list = [
    x.id 
    for x in all_posts_uuid_list 
    if (
        x.type == "post" 
        and 
        not x.deleted  # <-- if you don't care about NULLs / None
    )
]

Answered by: Fenton956 | Posted: 25-10-2021



Answer 3

allUuids = [x.id 
            for x in self.db.query(schema.allPostsUuid).execute(timeout = 20) 
            if x.type == "post" and x.deleted is not False]

Answered by: Daisy858 | Posted: 25-10-2021



Answer 4

For me that's too much. Maybe it's just a terrible example, since "type" and "deleted" would clearly be part of the db query.

I tend to think that if a list comprehension spans multiple lines it probably shouldn't be a list comprehension. Having said that, I usually just split the thing at "if" like other people have and will answer here.

Answered by: Sienna640 | Posted: 25-10-2021



Answer 5

You should not use a list comprehension for that.

List comprehensions are an awesome feature, but they are meant to be shortcuts, not regular code.

For such a long snippet, you should use ordinary blocs :

allUuids = []
for x in self.db.query(schema.allPostsUuid).execute(timeout = 20) :
    if x.type == "post" and x.deleted is not False :
        allUuids.append(x.id)

Exactly the same behavior, much more readable. Guido would be proud of you :-)

Answered by: Rafael630 | Posted: 25-10-2021



Answer 6

If you're set on a comprehension orestis's answer is good.

For more complex comprehensions like that I'd suggest using a generator with yield:

allUuids = list(self.get_all_uuids())


def get_all_uuids(self):
    for x in self.db.query(schema.allPostsUuid).execute(timeout = 20):
        if x.type == "post" and x.deleted is not False:
            yield x.id

Answered by: Emily203 | Posted: 25-10-2021



Answer 7

How about:

allUuids = [x.id for x in self.db.query(schema.allPostsUuid).execute(timeout = 20) 
                   if (x.type == "post" and x.deleted is not False)]

Generally, long lines can be avoided by pre-computing subexpressions into variables, which might add a minuscule performance cost:

query_ids = self.db.query(schema.allPostsUuid).execute(timeout = 20)
allUuids = [x.id for x in query_ids
                   if (x.type == "post" and x.deleted is not False)]

By the way, isn't 'is not False' kind-of superfluous ? Are you worried about differentiating between None and False ? Because otherwise, it suffices to leave the condition as only: if (x.type == "post" and x.deleted)

Answered by: Lily506 | Posted: 25-10-2021



Answer 8

    allUuids = [
        x.id
        for x in self.db.query(schema.allPostsUuid).execute(timeout = 20)
        if x.type == "post"
            and x.deleted
    ]

Answered by: Alford787 | Posted: 25-10-2021



Similar questions

refactoring - lisp-style style `let` syntax in Python list-comprehensions

Consider the following code: &gt;&gt;&gt; colprint([ (name, versions[name][0].summary or '') for name in sorted(versions.keys()) ]) What this code does is to print the elements of the dictionary versions in ascending order of its keys, but since the value is another sorted list, only the summary of its first element (the '...


python - Are list-comprehensions and functional functions faster than "for loops"?

In terms of performance in Python, is a list-comprehension, or functions like map(), filter() and reduce() faster than a for loop? Why, technically, they run in a C speed, while the for loop runs in the python virtual machine speed?. Suppose that in a game that I'm developing I need to draw complex and huge maps using for loops. This question ...


django - Python Complex List-Comprehensions

Is it any way to write this for loops with List-Comprehensions p_list = [] pt_list = [] for pt in part_task_list: pt.progress = pt.progress * pt.project_task.weight pt_list.append(pt) for p in part_list: for pt in pt_list: if pt.part.id == p.id: p.final_progress += pt.progress p.finla_progress = p.final_progress/100 p_list.append(p)


list-comprehensions problem in python - list dispear after run once

This question already has answers here:






Still can't find your answer? Check out these communities...



PySlackers | Full Stack Python | NHS Python | Pythonist Cafe | Hacker Earth | Discord Python



top