列表理解在某些情况下可能很有用,但阅读起来也很恐怖。作为一个稍微夸张的示例,您如何缩进以下内容?
allUuids = [x.id for x in self.db.query(schema.allPostsUuid).execute(timeout = 20) if x.type == "post" and x.deleted is not False]
Answers:
这取决于它们有多长时间。我倾向于这样构造它们:
[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变得太长,它将被提升为函数。
在我工作的地方,我们的编码准则将使我们执行以下操作:
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
)
]
对我来说太多了。也许这只是一个可怕的例子,因为“类型”和“删除”显然是数据库查询的一部分。
我倾向于认为,如果列表理解跨越多行,那么它可能不应该是列表理解。话虽如此,我通常只是像其他人一样在“ if”处拆分内容,并会在此处回答。
您不应该为此使用列表理解。
列表推导是一个很棒的功能,但是它们只是快捷方式,而不是常规代码。
对于这么长的代码段,您应该使用普通的块:
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为您感到骄傲:-)
yield
,或者引入新的变量和函数。
如果您对理解能力有所了解,那么orestis的答案很好。
对于类似的更复杂的理解,我建议使用带有以下内容的生成器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
怎么样:
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?因为否则,仅将条件保留为:f (x.type == "post" and x.deleted)