如何缩进Python列表parsing?

列表parsing在某些情况下可能是有用的,但是它们也可能是相当可怕的阅读。作为一个稍微夸张的例子,你将如何缩进?

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

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

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

这样每个expression式都有自己的路线。

如果任何一行变得太大,我喜欢用lambda或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)] 

然后,如果一个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 ) ] 

对我来说太过分了 也许这只是一个可怕的例子,因为“types”和“删除”显然是数据库查询的一部分。

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

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

你不应该使用列表理解

列表parsing是一个很棒的function,但是它们只是捷径,而不是普通的代码。

对于如此长的片段,您应该使用普通的区块:

 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) 

完全一样的行为,更可读。 圭多会为你感到骄傲:-)

怎么样:

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

一般来说,通过预先计算variables的子expression式可以避免长行,这可能会增加一个很小的性能成本:

 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 '的多余的? 你是否在区分“无”和“否”? 因为否则,只要将条件保留为:i f (x.type == "post" and x.deleted)

如果你在理解上设定的话, 那么这个答案是很好的。

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