使用一行循環,甚至是嵌套循環在Python中總是一個好習慣?我看到很多人都喜歡「單行」,但對我而言,他們有時候很難閱讀,特別是如果我們談論嵌套循環。Python中單行語句的用處
而且大多數我見過的嵌套循環遠超過每行推薦的79個字符。
所以我想知道,如果「單行」提供額外的東西除了緊湊?他們可能會使用更少的內存嗎?
使用一行循環,甚至是嵌套循環在Python中總是一個好習慣?我看到很多人都喜歡「單行」,但對我而言,他們有時候很難閱讀,特別是如果我們談論嵌套循環。Python中單行語句的用處
而且大多數我見過的嵌套循環遠超過每行推薦的79個字符。
所以我想知道,如果「單行」提供額外的東西除了緊湊?他們可能會使用更少的內存嗎?
是的,他們能更快地很容易,因爲更多的代碼可以用C運行(在顯式循環所有的緊急措施必須是可用來解釋器,在一個班輪列表理解它不必)。還有避免了這一切.append
方法呼叫的方法,查找等。在列表理解的開銷:
import timeit
def f1():
result = []
for x in range(100):
for y in range(100):
result.append(x * y)
return result
def f2():
return [x * y for y in range(100) for x in range(100)]
print('loop: ', timeit.timeit(f1, number=1000))
print('oneliner:', timeit.timeit(f2, number=1000))
結果(Python 3中):
loop: 1.2545137699926272
oneliner: 0.6745600730064325
很好的答案,正是我所期待的。看起來是時候我深入瞭解列表理解並正確地學習它們。出於好奇:如果我遇到超過79個字符的PEP推薦的長嵌套循環? (我知道我只能指定迭代器'x'或類似的東西來保持它的簡短,但如果即使這樣也會超過79個字符) – narn
[您可以在列表解析中使用換行符](http://stackoverflow.com /問題/ 5809059 /續行換列表內涵,或發電機表達式式的Python)。笛卡兒嵌套循環的另一種常見技術是使用['itertools.product'](https://docs.python.org/3/library/itertools.html#itertools.product)而不是嵌套循環。 –
取決於一襯墊,一些可以是更加有效和非常可讀的。
以列表理解爲例。比方說,你要採取一切數字1到10,輸出乘以他們的產品的清單2.
輸入:[1,2,3,...,9,10]
輸出:[2,4,6,...,18,20]
你可以做一個for循環,如下所示:
output = []
for i in range(1, 11):
output.append(i*2)
或者你也可以使用列表理解:
[i*2 for i in range(1,11)]
你會看到第l理解速度快得多,而且很可讀。
同樣可以說,對於字典理解,設定理解和生成器表達式。只要是可以理解的,我們極力鼓勵使用map()
和filter()
。
是。這是很好的做法。
通常有經驗的程序員使用匿名函數(見拉姆達:http://www.secnetix.de/olli/Python/lambda_functions.hawk)在一個線環,它提供了更好的性能。
討論......他們都這樣做。
「A」列表理解...吸菸的一行... 「B」同樣的事情,但你可以提供一個列表理解中的註釋......它仍然在技術上是一個班輪 「 c'是傳統方法。 如果速度是一個問題,我不太擔心速度,除非我每天執行相同的任務,而且需要很長時間才能完成。當你談論微或納秒時比較速度可能會引起學術界的興趣,但它不會影響絕大多數用戶。 我總是投票表達清晰的代碼的緊湊性。
a = [i**2 for i in range(20) if i > 5 and i < 10]
b = [i**2 # do this
for i in range(20) # using these
if (i > 5) and # where this and
(i < 10) # this is good
]
c = []
for i in range(20):
if (i > 5) and (i < 10):
c.append(i**2)
EDIT 產生的數字範圍的產物給出的例子,是一個很好的指標,該oneliner不必是問題,但所使用的方法來獲得的結果。我將說明如何確定僅使用10個值的產品...如果您喜歡,請嘗試使用100。我會以完整的格式完成它,但如果需要的話,可以將所有內容都減少到一個字符串(不包括進口)。
>>> import numpy as np
>>> a = np.arange(10)
>>> b = np.arange(10).reshape(10,1)
>>> a
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> b
array([[0],
[1],
[2],
[3],
[4],
[5],
[6],
[7],
[8],
[9]])
>>> a*b
array([[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
[ 0, 2, 4, 6, 8, 10, 12, 14, 16, 18],
[ 0, 3, 6, 9, 12, 15, 18, 21, 24, 27],
[ 0, 4, 8, 12, 16, 20, 24, 28, 32, 36],
[ 0, 5, 10, 15, 20, 25, 30, 35, 40, 45],
[ 0, 6, 12, 18, 24, 30, 36, 42, 48, 54],
[ 0, 7, 14, 21, 28, 35, 42, 49, 56, 63],
[ 0, 8, 16, 24, 32, 40, 48, 56, 64, 72],
[ 0, 9, 18, 27, 36, 45, 54, 63, 72, 81]])
或作爲一襯墊
>>> out = np.arange(10) * np.arange(10).reshape(10,1)
,當然也有內置函數來做到這一點沒有充分表達我已經表明。
要點是,速度並不是一切。應該首先考慮清晰的代碼和選擇正確的工具來完成這項工作。
'如果我> 5和我< 10' ->'如果5
查看我的附錄以顯示更好的選擇。當數據輸入非常大時,此選項可以很好地進行縮放......這是另一個考慮因素。並非所有的方法都是統一的,而且通常取決於數據大小。 – NaN
如何說「使用numpy」替代列表解析? numpy是一個專門用於數值計算的(第三方)庫,而列表解析(和其他單行程序)可以是通用的,用於許多與數值計算 – UnholySheep
取決於具體的一行。某些Python結構(例如:list comprehensions)可能會被解釋器優化,以產生「更好」的機器代碼,如果您編寫了一個正常的for-loop來填充列表。然而,正如你指出的那樣,如果你將代碼過度複雜化,代碼的可讀性會受到影響,並且程序員的工作是決定代碼變得無法讀取(因此不可維護)的程度。 – UnholySheep
如果能夠顯示某些難以理解的理解,將會有所幫助。通常它可以通過使用正確的命名和一些空格來補救。但沒有具體的樣本就很難證明。 –
看看我的例子中的堆疊列表理解......即使它技術上是 – NaN