[英]lisp-style style `let` syntax in Python list-comprehensions
[英]How to indent Python list-comprehensions?
列表推导在某些情况下可能很有用,但它们读起来也很糟糕。作为一个稍微夸张的例子,您将如何缩进以下内容?
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 ...]
这样每个表达式都有自己的行。
如果任何行变得太大,我想在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
)
]
allUuids = [x.id
for x in self.db.query(schema.allPostsUuid).execute(timeout = 20)
if x.type == "post" and x.deleted is not False]
对我来说太多了。 也许这只是一个可怕的例子,因为“type”和“deleted”显然是db查询的一部分。
我倾向于认为如果列表理解跨越多行,那么它可能不应该是列表理解。 话虽如此,我通常只是像其他人一样将这个东西拆分为“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)
完全相同的行为,更具可读性。 圭多会为你感到自豪:-)
如果你理解了,那么你的答案是好的。
对于更复杂的理解,我建议使用带有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? 因为否则,只需将条件保留为:i f (x.type == "post" and x.deleted)
allUuids = [
x.id
for x in self.db.query(schema.allPostsUuid).execute(timeout = 20)
if x.type == "post"
and x.deleted
]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.