溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Python常見的反模式是什么

發(fā)布時(shí)間:2022-05-18 11:54:14 來(lái)源:億速云 閱讀:140 作者:iii 欄目:大數(shù)據(jù)

這篇文章主要介紹“Python常見的反模式是什么”,在日常操作中,相信很多人在Python常見的反模式是什么問(wèn)題上存在疑惑,小編查閱了各式資料,整理出簡(jiǎn)單好用的操作方法,希望對(duì)大家解答”Python常見的反模式是什么”的疑惑有所幫助!接下來(lái),請(qǐng)跟著小編一起來(lái)學(xué)習(xí)吧!

1.對(duì)Iterable對(duì)象使用map()和filter()

內(nèi)置的 map 和 filter 可以幫助我們通過(guò)函數(shù)編程的原理在 Python 中轉(zhuǎn)換 iterable 對(duì)象。

這兩個(gè)方法都接受一個(gè)函數(shù)和一個(gè) iterable 作為參數(shù),并返回相應(yīng)的對(duì)象。

通過(guò)將該對(duì)象作為參數(shù)傳遞到 Python 中的內(nèi)置列表構(gòu)造函數(shù),可以將其轉(zhuǎn)換為列表。

我們經(jīng)常使用 lambda 函數(shù)作為 map、filter 函數(shù)的參數(shù):

my_list = [1, 2, 3, 4 ,5, 6, 7, 8, 9, 10]  # 將每個(gè)元素乘以2 print(list(map(lambda x: x * 2, my_list)))  # [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]  # 過(guò)濾掉偶數(shù) print(list(filter(lambda x: x % 2 == 0, my_list)))  # [2, 4, 6, 8, 10]

上面的代碼看起來(lái)相當(dāng)累贅和不清楚。使用列表理解可以實(shí)現(xiàn)相同結(jié)果:

my_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]  # 與map相同 print([x * 2 for x in my_list]) # [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]  # 與filter相同 print([x for x in my_list if x % 2 == 0]) # [2, 4, 6, 8, 10]

不使用lambda函數(shù)后,列表理解變得更具可讀性和簡(jiǎn)潔性。

2.輸入較大時(shí)使用列表理解

列表理解有助于我們編寫出清晰、簡(jiǎn)潔的代碼。

但是,列表理解總是為 iterable 中的每個(gè)值創(chuàng)建一個(gè)列表。當(dāng)輸入量非常大時(shí),就會(huì)導(dǎo)致內(nèi)存占用過(guò)大的問(wèn)題:我們的機(jī)器可能會(huì)崩潰。

生成器表達(dá)式結(jié)合了列表理解和生成器這兩個(gè)方面的優(yōu)點(diǎn),為處理大型輸入序列提供了更有效的方法。

要?jiǎng)?chuàng)建生成器表達(dá)式,只需將列表中的 [] 方括號(hào)替換為()方括號(hào)。

Python常見的反模式是什么

生成器表達(dá)式并不是創(chuàng)建一個(gè)全新的列表,而是創(chuàng)建一個(gè)迭代器。

這會(huì)降低創(chuàng)建速度并優(yōu)化內(nèi)存分配。我們可以使用 next 函數(shù)或通過(guò)循環(huán)訪問(wèn)生成器表達(dá)式的每個(gè)后續(xù)元素。

my_list = [1, 2, 3, 4 ,5, 6, 7, 8, 9, 10]  my_gen_expr = (x * 2 for x in my_list)  print(next(my_gen_expr)) print(next(my_gen_expr)) # >> # 2 # 4  for x in my_gen_expr:   print(x) # >> # 6 # 8 # 10 # 12 # 14 # 16 # 18 # 20

注:生成器表達(dá)式是有狀態(tài)的,因此在重用時(shí)要注意。如果要多次使用迭代器,則可能需要重新創(chuàng)建迭代器。

3.不使用range()的情況

range 函數(shù)對(duì)迭代整數(shù)很有用。

for i in range(10):     print(i)

當(dāng)?shù)愃屏斜淼臄?shù)據(jù)結(jié)構(gòu)時(shí),我們可以完全依賴for循環(huán)語(yǔ)法來(lái)訪問(wèn)每個(gè)項(xiàng)目。代碼如下:

my_list = [2, 4, 6, 8, 10]  for item in my_list:     print(item)  # Output: # 2 # 4 # 6 # 8 # 10

但是,當(dāng)想要訪問(wèn)索引和元素時(shí),我們可以使用列表長(zhǎng)度下的 range 方法,如下所示:

my_list = [2, 4, 6, 8, 10]  for i in range(len(my_list)):     print("index: ", i, "value: ", my_list[i])      # Output: # index: 0 value: 2 # index: 1 value: 4 # index: 2 value: 6 # index: 3 value: 8 # index: 4 value: 10

代碼看起來(lái)不可讀,因?yàn)槲覀儽仨氃诹斜砩险{(diào)用 len,然后使用 range 方法包裝輸出。為了使代碼更加具有 python  風(fēng)格,我們必須提高代碼的可讀性。

更好的方法是對(duì) list 對(duì)象調(diào)用 enumerate 函數(shù)。這將創(chuàng)建一個(gè)生成器,生成列表項(xiàng)的索引和值。

my_list = [2, 4, 6, 8, 10]  for i, v in enumerate(my_list):     print("index: ", i, "value: ", v)      # Output: # index: 0 value: 2 # index: 1 value: 4 # index: 2 value: 6 # index: 3 value: 8 # index: 4 value: 10

代碼看起來(lái)是不是更加干凈了?

4.字典中鍵丟失的問(wèn)題

字典具有快速訪問(wèn)、分配、插入和刪除的能力,是一種非常流行的數(shù)據(jù)結(jié)構(gòu)。

但是新手開發(fā)人員訪問(wèn)字典中不存在的密鑰時(shí)經(jīng)常會(huì)遇到問(wèn)題。

crypto_price = {   "Bitcoin": 64000,   "Ethereum": 2300,   "Dogecoin": 0.12 }  crypto_price["XRP"]
Python常見的反模式是什么

處理該類問(wèn)題的其中一種方法是檢查字典中是否存在密鑰,代碼如下:

key = "XRP"  if key not in crypto_price:     crypto_price[key] = 1.2      print(crypto_price[key])

另一種方法是使用 try/except 塊,如下所示:

key = "XRP"  try:     xrp = crypto_price[key] except raise KeyError:     xrp = 1.2      crypto_price[key] = xrp

上面的代碼確實(shí)實(shí)現(xiàn)了我們的目標(biāo),但是我們可以通過(guò)使用字典方法 get 進(jìn)一步改進(jìn)。

通過(guò)使用 get 方法來(lái)獲取相應(yīng)鍵的值,而不是使用方括號(hào) [] 來(lái)訪問(wèn)字典的鍵。

另外,如果鍵不存在,get 方法將返回 None,而不是拋出 KeyError。如果缺少鍵而不是無(wú)鍵,還可以將參數(shù)傳遞給 get  方法以獲取默認(rèn)值。

key = "XRP"  if crypto_price.get("XRP") is None:   crypto_price["XRP"] = 1.2
ada = crypto_price.get("ADA", 0)  # Prints 0 print(ada)

5.惰性關(guān)鍵字和位置參數(shù)設(shè)計(jì)

Python函數(shù)能夠同時(shí)接受位置參數(shù)和關(guān)鍵字參數(shù)。

位置參數(shù)是不后跟等號(hào)(=)和默認(rèn)值的名稱。

關(guān)鍵字參數(shù)后面跟一個(gè)等號(hào)和一個(gè)給出其默認(rèn)值的表達(dá)式。

得益于這種設(shè)計(jì),python函數(shù)的創(chuàng)建和重用非常靈活。

但是,定義函數(shù)時(shí),錯(cuò)誤的設(shè)計(jì)選擇可能會(huì)導(dǎo)致代碼中難以修復(fù)的錯(cuò)誤。

我們以計(jì)算復(fù)利的函數(shù)為例:

# 復(fù)利計(jì)算器年/月復(fù)利 def calculate_compound_interest(principal, rate, time_in_years,                                 compounded_monthly, to_string):   t = 1   if compounded_monthly:     t = 12   amt = principal * (1 + rate/(t * 100)) ** (time_in_years * t)   if to_string:     return f"${amt - principal:.2f}"    return amt - principal          calculate_compound_interest(100, 5, 2, False, False)   # 10.25

調(diào)用函數(shù)時(shí)出現(xiàn)的一個(gè)問(wèn)題是,兩個(gè)布爾參數(shù)(compounded_monthly 和結(jié)尾的  to_string)很容易相互混淆。這就會(huì)出現(xiàn)難以追蹤的問(wèn)題。

我們可以通過(guò)如下方式更改函數(shù)定義來(lái)提高可讀性:

# 復(fù)利計(jì)算器年/月復(fù)利 def calculate_compound_interest(principal, rate, time_in_years,                                 compounded_monthly=False, to_string=False):

通過(guò)將兩個(gè)布爾參數(shù)指定為關(guān)鍵字參數(shù),函數(shù)調(diào)用方可以顯式地指定要設(shè)置的布爾值,這些值將覆蓋默認(rèn)值。

calculate_compound_interest(100, 5, 2, compounded_monthly=True) # 10.49413355583269  calculate_compound_interest(100, 5, 2, to_string=True) # '$10.25'

但是,這仍然會(huì)出現(xiàn)問(wèn)題,主要原因是關(guān)鍵字參數(shù)是可選的,因?yàn)闆](méi)有任何強(qiáng)制調(diào)用方將這些作為關(guān)鍵字參數(shù)使用。

因此,我們?nèi)匀豢梢允褂门f方法調(diào)用該函數(shù):

calculate_compound_interest(100, 5, 2, False, False)

解決該問(wèn)題的方法是僅在定義函數(shù)時(shí)強(qiáng)制布爾參數(shù)為關(guān)鍵字:

# 復(fù)利計(jì)算器年/月復(fù)利 def calculate_compound_interest(principal, rate, time_in_years, *, # Changed                                 compounded_monthly=False, to_string=False):

我們看到,*符號(hào)表示位置參數(shù)的結(jié)束和僅關(guān)鍵字參數(shù)的開始。

如果這樣調(diào)用:

calculate_compound_interest(100, 5, 2, False, False)

將發(fā)生以下錯(cuò)誤:

--------------------------------------------------------------------------- TypeError                                 Traceback (most recent call last) <ipython-input-32-faf75d2ad121> in <module> ----> 1 print(calculate_compound_interest(1000, 5, 2, False, False)) TypeError: calculate_compound_interest() takes 3 positional arguments but 5 were given

但是,關(guān)鍵字參數(shù)及其默認(rèn)行為仍將保持不變,如下所示:

alculate_compound_interest(100, 5, 2, compounded_monthly=True) # 10.49413355583269  calculate_compound_interest(100, 5, 2, to_string=True) # '$10.25'

然而,仍然存在一個(gè)問(wèn)題。

假設(shè)調(diào)用者決定對(duì)前三個(gè)必需參數(shù)(principal、rate、time in years)混合使用位置和關(guān)鍵字。

如果這三個(gè)參數(shù)的函數(shù)參數(shù)名稱發(fā)生更改,我們將看到Python解釋器。它會(huì)這樣說(shuō):

# 復(fù)利計(jì)算器年/月復(fù)利 def calculate_compound_interest(p, r, t_in_y, *, # Changed                                 compounded_monthly=False, to_string=False):
calculate_compound_interest(principal=1000, rate=5, time_in_years=2)  calculate_compound_interest(1000, 5, time_in_years=2)

將發(fā)生以下錯(cuò)誤:

--------------------------------------------------------------------------- TypeError                                 Traceback (most recent call last) <ipython-input-36-42e7ec842cd5> in <module> ----> 1 calculate_compound_interest(principal=1000, rate=5, time_in_years=2) TypeError: calculate_compound_interest() got an unexpected keyword argument 'principal' --------------------------------------------------------------------------- TypeError                                 Traceback (most recent call last) <ipython-input-37-1bc57c40980f> in <module> ----> 1 calculate_compound_interest(1000, 5, time_in_years=2) TypeError: calculate_compound_interest() got an unexpected keyword argument 'time_in_years'

因?yàn)槲覀儧](méi)有考慮調(diào)用方顯式地使用位置參數(shù),所以代碼中斷。

python3.8中引入了一個(gè)解決方案,我們可以使用/參數(shù)重新定義函數(shù),該參數(shù)指示僅位置參數(shù)的結(jié)束位置。代碼如下:

# 復(fù)利計(jì)算器年/月復(fù)利 def calculate_compound_interest(p, r, t_in_y, /, *,  # 改變                                 compounded_monthly=False, to_string=False):

現(xiàn)在這樣調(diào)用函數(shù)就會(huì)產(chǎn)生正確的結(jié)果:

calculate_compound_interest(100, 5, 2, compounded_monthly=True) # 10.49413355583269  calculate_compound_interest(100, 5, 2, to_string=True) # '$10.25'

但是,如果我們這樣調(diào)用:

calculate_compound_interest(p=1000, r=5, t_in_y=2)

也會(huì)顯示相應(yīng)的錯(cuò)誤:

---------------------------------------------------------------------------  TypeError                                 Traceback (most recent call last)  <ipython-input-21-883e876a7e8b> in <module>  ----> 1 calculate_compound_interest(p=1000, r=5, t_in_y=2)        2  TypeError: calculate_compound_interest() got some positional-only arguments passed as keyword arguments: 'p, r, t_in_y'

到此,關(guān)于“Python常見的反模式是什么”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識(shí),請(qǐng)繼續(xù)關(guān)注億速云網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)?lái)更多實(shí)用的文章!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI