web-dev-qa-db-ja.com

インデントする方法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]
60
dbr

それは彼らがどれくらい長いかに依存します。私はそれらを次のように構成する傾向があります:

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

そして、ラムダが長くなりすぎると、関数に昇格されます。

65
orestis

私が作業している場合、コーディングガイドラインにより、次のようなことが行われます。

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
    )
]
44
guzzloid
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
jfs

私にとってそれは多すぎます。 「type」と「deleted」は明らかにdbクエリの一部であるため、これは恐ろしい例にすぎないかもしれません。

私は、リスト内包が複数行にわたる場合、それはおそらくリスト内包であるべきではないと考えがちです。そうは言っても、私は通常、他の人が持っているような「もし」で物事を分けるだけなので、ここで答えます。

6
Ali Afshar

そのためにリスト内包表記を使用しないでください

リスト内包表記はすばらしい機能ですが、通常のコードではなくショートカットとして使用することを目的としています。

そのような長いスニペットでは、通常のブロックを使用する必要があります:

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)

まったく同じ動作で、より読みやすくなります。グイドはあなたを誇りに思うでしょう:-)

3
e-satis

もしあなたが理解に取り掛かっているなら オレスティスの答え が良い。

そのようなより複雑な内包については、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
3
Henco

どうですか:

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

1
Eli Bendersky