如何缩进Python列表推导?

时间:2008-11-22 18:08:19

标签: python coding-style

列表推导在某些情况下可能很有用,但它们也可能相当可怕阅读..作为一个有点夸张的例子,你会如何缩进以下内容?

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

7 个答案:

答案 0 :(得分:63)

这取决于它们有多长。我倾向于像这样构造它们:

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

这样每个表达式都有自己的行。

如果任何一行太大,我想用lambda或表达式提取出来:

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)]

然后如果一个lambda变得太长,它就会被提升为一个函数。

答案 1 :(得分:43)

在我工作的地方,我们的编码指南会让我们做这样的事情:

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
    )
]

答案 2 :(得分:7)

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

答案 3 :(得分:5)

对我而言太过分了。也许这只是一个可怕的例子,因为“type”和“deleted”显然是db查询的一部分。

我倾向于认为如果列表理解跨越多行,则可能不应该是列表理解。话虽如此,我通常只是像其他人一样将这个东西拆分为“if”并在这里回答。

答案 4 :(得分:3)

您不应该使用列表推导

列表推导是一个很棒的功能,但它们应该是快捷方式,而不是常规代码。

对于这么长的片段,你应该使用普通的集团:

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)

完全相同的行为,更具可读性。 Guido会为你感到骄傲: - )

答案 5 :(得分:3)

如果你理解orestis's answer是好的。

对于更复杂的理解,我建议使用带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

答案 6 :(得分:1)

怎么样:

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

通常,通过将子表达式预先计算为变量可以避免长行,这可能会增加极小的性能成本:

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)]

顺便说一下,“is not False”不是多余的吗?你是否担心区分None和False?因为否则,只需将条件保留为:i f (x.type == "post" and x.deleted)