2012-10-19 69 views
1

我需要建立空巢字典的大樹,並想知道如果下面的代碼是Python化:在發電機內嵌套發電機是Pythonic嗎?

dictionary_name = dict((year, dict((month, dict((day, []) for day in days)) 
         for month in months)) for year in years) 
  • 如果這是不好的做法,什麼是寫在上面的代碼的最Python的方式?
  • 如果這是不壞的做法,我應該用換行符保持這種清晰,「Python化」。另外,嵌套它們時發電機的速度優勢仍然存在?

備註:這個問題也適用於列表解析。如果你認爲我應該把這個問題分解成多個問題,請告訴我。

+5

如果是更具可讀性,它的「Python化」。 –

+0

是的,非常如此。你認爲什麼是pythonic替代方案? – 2012-10-19 13:10:05

+0

我應該將問題重命名爲「對[[]]有效嗎?」 – TimY

回答

5

你有什麼上面是有點太密對我的口味......其實我一般避免嵌套表達式一樣,因爲我有一個很難記住他們是否得到由內而外的閱讀,或外面,或者通過一些奇怪的魔法隨機方法。這就是說,我知道有其他人誰寫偉大的Python代碼誰窩有時候,我覺得你不嵌套太深這是確定的,只要。

就個人而言,我可能會創建一個dict它使用的元組索引它 - 我可能會考慮使用defaultdict

from collections import defaultdict 
dictionary_name = defaultdict(list) 
dictionary_name[(year,month,day)].append(data) 
#your way would be: `dictionary_name[year][month][day].append(data)` 

這是(恕我直言)一個更容易理解比的代碼是什麼你有以上(即更pythonic)。

如果你不想做defaultdict,你可以使用itertools.product構建字典:

dictionary_name = dict((k,[]) for k in it.product(years,months,days)) 

dictionary_name = { k:[] for k in it.product(years,months,days) } #py2.7+ 
+0

請注意,您甚至不需要使用()作爲索引;在[]中,逗號分隔的項目會自動變成一個元組 –

+0

儘管原始嵌套數據結構和此扁平化字典之間的用法存在實際差異。這失去了原來存在的結構。 – chepner

+0

@chepner - 是的(有沒有爭用) - 這可能會使這個交易斷路器。我只是說爲數據選擇合適的結構是'pythonic'的一部分,但這依賴於我們不知道的信息。 – mgilson

2

列表理解的複雜性是更加個性化的/ dev的問題。團隊風格,而不是純粹的「被Pythonic」問題。對於這樣的情況下很好的潛力的參考工具是Google Python Style Guide。他們的section on listcomps說:

好的用於簡單的情況。

與「決定」(即谷歌內部怎麼下來的問題):

好以用於簡單情況。每個部分必須符合一行:映射表達式,用於子句,過濾器表達式。多個for子句或過濾器表達式是不允許的。當事情變得更加複雜時,請使用循環。

就個人而言,我只要他們立即是可以理解的去嵌套listcomps ,否則分解成多個部分,功能等

其他說明您的問題:

  • 是的,你可以做listcomps換行符,它有時幫助可讀性。
  • 對於速度,答案是「它取決於」,可能更多的是堆棧溢出的單獨問題(我相當有信心你會在這裏找到一些好的起點)。如果沒有別的:(1)確保這是一個瓶頸,然後(2)基準替代品。

最終,風格問題是「使用你的判斷」的問題 - 只是考慮其他開發者,他們以後會遇到你的代碼。

5

如果你不介意使用defaultdict,我會用

from collections import defaultdict 
import itertools 
dd = defaultdict(defaultdict) 
for y, m, d in itertools.product(years, months, days): 
    dd[y][m][d] = [] 
+0

不錯的解決方案!即使我仍然避免嵌套它們。 – Bakuriu

+0

我希望我可以選擇2個答案!你的可能更符合我最初發布的內容,但是mgilson對我的確切目的更實用。 – TimY

0

去雖然我與其他的海報,這個說法有些密集的同意,這可能是打破一個好主意它以另一種方式,如果你去寫密的東西,稍微縮進的調整可以走很長的路到使它更具可讀性:

dictionary_name = dict(
    (year, dict((month, dict((day, []) 
          for day in days)) 
       for month in months)) 
    for year in years)