2008-11-22 47 views
46

列表解析在某些情況下可能有用,但它們也可能相當可怕地閱讀。作爲一個稍微誇張的示例,您將如何縮進以下內容?如何縮進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] 

回答

55

這取決於它們有多長。我傾向於像這樣構造它們:

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

然後,如果一個lambda變得太長時間被提升到一個函數。

1

如何:

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'種類多餘?你擔心區分「無」還是「否」?因爲不然,只要保留條件就足夠了:i f (x.type == "post" and x.deleted)

+0

我第二次說。在所有語言中應避免使用超過80個字符的行。 – 2008-11-22 18:19:22

+0

同意,但Python的語法規則通常會鼓勵/強制更長的行。它的空白處理通常是關於我對語言的唯一抱怨。 – 2008-11-22 18:27:59

+0

通過仔細選擇變量,並用括號或括號分割線條,我從來不必訴諸太長的線條(問題更多的是爲了避免self.long_foo.very_long_bar.baz(....)使用臨時對象) – 2008-11-22 18:33:31

5

對我來說這太多了。也許這只是一個可怕的例子,因爲「type」和「deleted」顯然是db查詢的一部分。

我傾向於認爲,如果一個列表理解跨越多行,它可能不應該是一個列表理解。話雖如此,我通常只是在「如果」像其他人一樣將事物分解並在這裏回答。

37

我在哪裏工作,我們的編碼準則將讓我們做這樣的事情:

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 
    ) 
] 
5
allUuids = [x.id 
      for x in self.db.query(schema.allPostsUuid).execute(timeout = 20) 
      if x.type == "post" and x.deleted is not False] 
5

你不應該使用列表理解爲

列表解析是一個很棒的功能,但它們的目的是作爲捷徑,而不是普通的代碼。

這麼長的片段,你應該使用普通集團:

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) 

完全一樣的行爲,更具有可讀性。圭多會爲你感到驕傲:-)

0

如果你設置了理解orestis's answer是好的。

對於更復雜的內涵一樣,我建議使用一個發電機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