リスト内包表記は特定の状況で役立つ場合がありますが、読むのがかなりひどい場合もあります。少し誇張された例として、以下をどのようにインデントしますか?
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 ...]
これにより、すべての式に独自の行があります。
行が大きくなりすぎた場合は、ラムダまたは式で抽出します。
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)]
そして、ラムダが長くなりすぎると、関数に昇格されます。
私が作業している場合、コーディングガイドラインにより、次のようなことが行われます。
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クエリの一部であるため、これは恐ろしい例にすぎないかもしれません。
私は、リスト内包が複数行にわたる場合、それはおそらくリスト内包であるべきではないと考えがちです。そうは言っても、私は通常、他の人が持っているような「もし」で物事を分けるだけなので、ここで答えます。
そのためにリスト内包表記を使用しないでください。
リスト内包表記はすばらしい機能ですが、通常のコードではなくショートカットとして使用することを目的としています。
そのような長いスニペットでは、通常のブロックを使用する必要があります:
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の違いを心配していますか?それ以外の場合は、条件をそのままにしておくだけで十分です:if (x.type == "post" and x.deleted)