2013-03-13 35 views
1
def thing(mode, data): 
    return [ 
     item for item in data 
     if { 
      'large': lambda item: item > 100, 
      'small': lambda item: item < 100, 
     }[mode](item) 
    ] 

此列表理解生成lambdas字典,通過mode參數檢索一個lambda,並將其應用於當前正在處理的列表項。我的問題是:這是什麼性能特點?在列表理解期間Python如何執行?

在listcomp的每次迭代期間是否從頭開始創建整個字典?還是它創建一次並用於每個項目?

+0

它每次創建。它還將在每個循環中創建2個函數 – JBernardo 2013-03-13 02:05:02

+2

提示:'import dis; dis.dis(事)'。 – DSM 2013-03-13 02:05:23

回答

4

是在listcomp

是每個迭代期間從頭開始創建整個字典。

還是它創建一次,並在每個項目上使用?


幸運的是,在這種情況下(和所有其他人一樣它是我能想到的),可以很容易地只是生成字典的時間提前:

d = { 
     'large': lambda item: item > 100, 
     'small': lambda item: item < 100, 
     } 
return [item for item in data if d[mode](item)] 

甚至,

func = { 
     'large': lambda item: item > 100, 
     'small': lambda item: item < 100, 
     }[mode] 
return [item for item in data if func(item)] 
+0

@JBernardo - 但OP問了一個是或否的問題;-)。我已更新。 – mgilson 2013-03-13 02:08:46

+0

幹得好,這是一個很棒的答案。 – 2013-03-13 02:24:33

2

我敢肯定,這將導致整個迪克斯從頭開始爲列表的每個元素創建。 Python的列表內涵的基本語法如下,

[ E1 for ID in E2 if E3 ]

,其中E1,E2和E3是表達式。當解釋者開始評估列表理解時,E2被評估一次。針對E2評估的集合的每個成員評估E1和E3。所以,是的。在你的問題中,字典是每次從頭開始構建的,但是你可以通過在列表理解之前聲明字典來輕鬆解決這個問題。

1

你的字典在每週迴路形成,使大約比一個在那裏你緩存字典兩次較慢列表理解:

>>> %timeit thing1('small', [1, 2, 3, 4, 5, 6]) 
100000 loops, best of 3: 2.4 us per loop 
>>> %timeit thing2('small', [1, 2, 3, 4, 5, 6]) 
1000000 loops, best of 3: 1.06 us per loop 

thing1是你的原始功能。 thing2是:

d = { 
    'large': lambda item: item > 100, 
    'small': lambda item: item < 100, 
} 

def thing3(mode, data): 
    return list(filter(d[mode], data)) 

filter(f, data)item for item in data if f(item)簡寫。在Python 3中,它會創建一個迭代器,只有在迭代它時纔會過濾掉項目。