為什麼要挑戰自己在**裡不寫for loop?因為這樣可以迫使你去使用比較高階、地道的語法或庫。文中以python為例子,講了不少大家其實在別人的**裡都見過、但自己很少用的語法。
這是乙個挑戰。我要你避免在任何情況下寫for迴圈。同樣的,我也要你找到一種場景——除了用for迴圈以外,用其他方法寫都太難。請分享你的發現,我非常想聽到這些
距離我開始探索超棒的python語言特性已經有一段時間了。一開始,這只是我給自己的乙個挑戰,練習使用更多的語言特性來替代我從其他程式語言那裡所學到的。但是事情漸漸變得更有趣了!**不止變得更簡短整潔,而且看起來更加結構化和有規律,在這篇文章中我將更多地介紹這些好處。
首先,讓我們退一步看看在寫乙個for迴圈背後的直覺是什麼:
遍歷乙個序列提取出一些資訊
從當前的序列中生成另外的序列
寫for迴圈已經是我的第二天性了,因為我是乙個程式設計師
幸運的是,python裡面已經有很棒的工具幫你達到這些目標!你需要做的只是轉變思想,用不同的角度看問題。
不到處寫for迴圈你將會獲得什麼
更少的**行數
更好的**閱讀性
只將縮排用於管理**文字
let』s see the code skeleton below:
看看下面這段**的構架:
# 1
with..
.:for...
:if..
.:try:
except
:else
:
這個例子使用了多層巢狀的**,這是非常難以閱讀的。我在這段**中發現它無差別使用縮排把管理邏輯(with, try-except)和業務邏輯(for, if)混在一起。如果你遵守只對管理邏輯使用縮排的規範,那麼核心業務邏輯應該立刻脫離出來。
為了避免for迴圈,你可以使用這些工具
1. 列表解析/生成器表示式
看乙個簡單的例子,這個例子主要是根據乙個已經存在的序列編譯乙個新序列:
'''
'''result =
for item in item_list:
new_item = do_something_with(item)
result =
[do_something_with(item)
for item in item_list]
同樣的,如果你只是想要獲取乙個迭代器,你可以使用語法幾乎相通的生成器表示式。(你怎麼能不愛上python的一致性?)
result =
(do_something_with(item)
for item in item_list)
2. 函式
站在更高階、更函式化的變成方式考慮一下,如果你想對映乙個序列到另乙個序列,直接呼叫map函式。(也可用列表解析來替代。)
doubled_list =
map(
lambda x: x *
2, old_list)
如果你想使乙個序列減少到乙個元素,使用reduce
from functools import
reduce
summation =
reduce
(lambda x, y: x + y, numbers)
另外,python中大量的內嵌功能可/會(我不知道這是好事還是壞事,你選乙個,不加這個句子有點難懂)消耗迭代器:
'''
'''>>
> a =
list
(range(10
))>>
> a[0
,1,2
,3,4
,5,6
,7,8
,9]>>
>
all(a)
false
>>
>
any(a)
true
>>
>
max(a)
9>>
>
min(a)
0>>
>
list
(filter
(bool
, a))[
1,2,
3,4,
5,6,
7,8,
9]>>
>
set(a)
>>
>
dict
(zip
(a,a)
)>>
>
sorted
(a, reverse=
true)[
9,8,
7,6,
5,4,
3,2,
1,0]
>>
>
str(a)
'[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]'
>>
>
sum(a)
45
3. 抽取函式或者表示式
上面的兩種方法很好地處理了較為簡單的邏輯,那更複雜的邏輯怎麼辦呢?作為乙個程式設計師,我們會把困難的事情抽象成函式,這種方式也可以用在這裡。如果你寫下了這種**:
results =
for item in item_list:
# setups
# condition
# processing
# calculation
顯然你賦予了一段**太多的責任。為了改進,我建議你這樣做:
'''
'''def
process_item
(item)
:# setups
# condition
# processing
# calculation
return result
results =
[process_item(item)
for item in item_list]
巢狀的for迴圈怎麼樣?
results =
for i in
range(10
):for j in
range
(i):
(i, j)
)
列表解析可以幫助你:
results =
[(i, j)
for i in
range(10
)for j in
range
(i)]
如果你要儲存很多的內部狀態怎麼辦呢?
# finding the max prior to the current item
a =[3,
4,6,
2,1,
9,0,
7,5,
8]results =
current_max =
0for i in a:
current_max =
max(i, current_max)
# results = [3, 4, 6, 6, 6, 9, 9, 9, 9, 9]
讓我們提取乙個表示式來實現這些:
'''
'''def
max_generator
(numbers)
:current_max =
0for i in numbers:
current_max =
max(i, current_max)
yield current_max
a =[3,
4,6,
2,1,
9,0,
7,5,
8]results =
list
(max_generator(a)
)
「等等,你剛剛在那個函式的表示式中使用了乙個for迴圈,這是欺騙!」
好吧,自作聰明的傢伙,試試下面的這個。
4. 你自己不要寫for迴圈,itertools會為你代勞
from itertools import accumulate
a =[3,
4,6,
2,1,
9,0,
7,5,
8]resutls =
list
(accumulate(a,
max)
)
另外,如果你在迭代組合的序列,還有product(),permutations(),combinations()可以用。
結論
大多數情況下是不需要寫for迴圈的。
應該避免使用for迴圈,這樣會使得**有更好的閱讀性。
行動
再看一遍你的**,找出任何以前憑直覺寫下for迴圈的地方,再次思考一下,不用for迴圈再寫一遍是不是有意義的。
分享你很難不使用for迴圈的例子。
我不想做木偶
我不想做木偶 我是乙個有思想的人,我不是木偶,也不想做木偶。人生在世,如白駒之過隙。須臾之間,為了不白活於世,為了知道自己來這到這個世界上是幹什麼來了。我發誓我要把自己的精神永留於世。自從我選擇了這個職業,我發現了很多的樂趣。也讓我的生活十分的豐富與精彩。在工作中我會面臨各種各樣的問題。每當乙個專案...
我不想說再見
我不想說再見 本科畢業 暑假在家,夜夢,醒後作 深夜裡忽然從夢中驚醒,窗外月光正皎潔如晝。我坐起來,看著外面婆娑的樹影,想起剛才的夢來。我夢見列車載著我們新生駛入校園。一會兒我們便在操場上開始了佇列訓練。休息時,我看清了我的學友 簡子 錫安 大個子孫峰等。我好高興,剛想問一聲 真的是你們回來了嗎 便...
我也不想這樣
不記得是在 第一次聽這首歌,網上一搜,原來已經是很老的了。老規老,但是王菲獨特的嗓音無懈可擊,就像班得瑞的天籟之音那樣,如雨後空氣那般清新。祝福她吧,或許這首歌很適合現在的她。我也不想這樣 歌手 王菲 你快樂 所以我快樂 你快樂 所以我快樂 作詞 林夕 作曲 alex san 忽然間毫無緣故再多的愛...