你應(yīng)該避免的5個常見 Python 錯誤

點擊下面卡片關(guān)注“AI算法與圖像處理”,選擇加"星標"或“置頂”
重磅干貨,第一時間送達
引言
Python 是一種非常強大的編程語言,它的語法很容易理解,即使你沒有編程基礎(chǔ),也可以自學。在整個學習過程中,由于缺乏對某些概念的理解,你可能會犯很多錯誤。學習如何糾正這些錯誤將進一步增強你對基礎(chǔ)知識以及編程技能的理解。
本文將總結(jié)許多人在開始學習過程中可能遇到的一些常見 Python 錯誤,以及如何修正或避免這些錯誤。
1. 修改后重新加載模塊
你是否曾經(jīng)浪費時間調(diào)試和修復(fù)一個問題,并最終意識到自己沒有在修改后的源代碼上進行調(diào)試?這種情況通常發(fā)生在初學者身上,因為他們沒有意識到整個模塊只在執(zhí)行 import 語句時加載到內(nèi)存中一次。因此,如果你正在單獨的模塊中修改某些代碼并將其導入到當前代碼中,則必須重新加載該模塊以反映最新的更改。
要重新加載一個模塊,你可以使用來自 importlib 模塊的 reload 函數(shù):
from importlib import reload# some module which you have made changesimport externallibreload(externallib)
2. 全局變量和局部變量命名沖突
假設(shè)已經(jīng)定義了一個名為 app_config 的全局變量,并且希望在 init_config 函數(shù)中使用它,如下所示:
app_config = "app.ini"def init_config():app_config = app_config or "default.ini"print(app_config)
你可能希望打印出 “app.ini”,因為它已經(jīng)被全局定義,但是令人驚訝的是,由于變量 app_config 在賦值之前被引用,您會收到 “UnboundLocalError” 異常。如果注釋掉賦值語句并僅打印出變量,將看到正確打印出的值。那么這是怎么回事?
這是由于每當有賦值表達式時,Python 都會嘗試在局部作用域中創(chuàng)建一個變量,而且由于局部變量和全局變量具有相同的名稱,全局變量被隱藏在局部作用域中。因此 Python 會拋出一個錯誤,說在初始化之前使用了局部變量 app_config。
為了解決這個命名沖突,你應(yīng)該為你的全局變量和局部變量使用不同的名字來避免任何混淆,例如:
app_config = "app.ini"def init_config():config = app_config or "default.ini"print(config)
3.檢查虛假值
在 if 或 while 語句中檢查一個變量的真或假有時也會出錯。對于 Python 初學者來說,混合 None 值和其他錯誤值并最終編寫一些錯誤代碼是很常見的。例如: 假設(shè)你想檢查什么時候價格不是0或者低于5,觸發(fā)一些賣出警告:
def selling_alert(price):if price and price < 5:print("selling signal!!!")
一切看起來都很好,但是當你用 price = 0進行測試時,你不會得到任何提醒:
selling_alert(0)# Nothing has been printed out
這是因為 Python 將 None 和0都計算為 False,因此打印語句將被跳過,盡管 price < 5為 true。
在 python 中,空序列對象,如“”(空字符串)、 list、 set、 dict、 tuple 等,都被計算為 False,在任何數(shù)字格式(如0和0.0)中也是零。因此,為了避免這樣的問題,你應(yīng)該非常清楚你的邏輯是否需要區(qū)分 None 和其他 False 值,然后在必要時分割邏輯,例如:
if price is None:print("invalid input")elif price < 5:print("selling signal!!!")
4.默認值和變量綁定
當你希望使函數(shù)參數(shù)可選但仍可靈活更改時,可以使用默認值。假設(shè)你需要實現(xiàn)一個帶有 event_time 參數(shù)的日志記錄函數(shù),希望在未給出時將缺省值作為當前時間戳。你可以像下面這樣寫一些代碼:
from datetime import datetimedef log_event_time(event, event_time=datetime.now()):print(f"log this event - {event} at {event_time}")
如果在 log_event_time 函數(shù)調(diào)用期間沒有提供 event_time,那么在調(diào)用該函數(shù)時,它將用時間戳記記錄事件。但是如果你用下面的方法來測試:
log_event_time("check-in")# log this event - check-in at 2021-02-21 14:00:56.046938log_event_time("check-out")# log this event - check-out at 2021-02-21 14:00:56.046938
您將看到所有事件都以相同的時間戳記錄。那么為什么 event_time 的默認值不起作用呢?
要回答這個問題,你應(yīng)該知道變量綁定發(fā)生在函數(shù)定義期間。對于上面的示例,在最初定義函數(shù)時分配了 event_time 的默認值。每次調(diào)用函數(shù)時都會使用相同的值。
要解決此問題,可以將 None 設(shè)置為默認值,并檢查它是否為 None 時覆蓋函數(shù)調(diào)用中的 event_time 。例如:
def log_event_time(event, event_time=None):event_time = event_time or datetime.now()print(f"log this event - {event} at {event_time}")
5. 可變對象的默認值
Python 初學者容易犯的另一個錯誤是為可變函數(shù)參數(shù)設(shè)置默認值。例如, add_white_list 函數(shù)中的以下參數(shù):
def add_white_list(user, user_list=[]):user_list.append(user)return user_list
你可能希望在未提供 user_list 的情況下創(chuàng)建一個空列表,然后將新用戶添加到該列表中并返回。
my_list = add_white_list('Jack')# ['Jack']my_list = add_white_list('Jill', my_list)#['Jack', 'Jill']
但是當你想再次使用空列表時,你會看到一些意想不到的結(jié)果:
從前面的變量綁定示例中,我們知道 user _ list 的默認值只在函數(shù)定義時創(chuàng)建一次。由于 list 是可變的,對 list 對象所做的更改將由后續(xù)的函數(shù)調(diào)用引用。
def add_white_list(user, user_list=None):if user_list is None:user_list = []user_list.append(user)return user_list
為了解決這個問題,我們將使用 None 作為 user _ list 的默認值,并在調(diào)用期間沒有給出 user _ list 時使用局部變量創(chuàng)建一個新列表。例如:
個人微信(如果沒有備注不拉群!) 請注明:地區(qū)+學校/企業(yè)+研究方向+昵稱
下載1:何愷明頂會分享
在「AI算法與圖像處理」公眾號后臺回復(fù):何愷明,即可下載。總共有6份PDF,涉及 ResNet、Mask RCNN等經(jīng)典工作的總結(jié)分析
下載2:終身受益的編程指南:Google編程風格指南
在「AI算法與圖像處理」公眾號后臺回復(fù):c++,即可下載。歷經(jīng)十年考驗,最權(quán)威的編程規(guī)范!
下載3 CVPR2021 在「AI算法與圖像處理」公眾號后臺回復(fù):CVPR,即可下載1467篇CVPR 2020論文 和 CVPR 2021 最新論文
靚仔,靚妹 點亮在看吧

