我不想用for迴圈

2021-09-27 16:07:39 字數 4640 閱讀 9456

為什麼要挑戰自己在**裡不寫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 忽然間毫無緣故再多的愛...