
淺談使用Python變量時要避免的3個錯誤
ython編程中經(jīng)常遇到一些莫名其妙的錯誤, 其實這不是語言本身的問題, 而是我們忽略了語言本身的一些特性導(dǎo)致的,今天就來看下使用Python變量時導(dǎo)致的3個不可思議的錯誤, 以后在編程中要多多注意。
1、 可變數(shù)據(jù)類型作為函數(shù)定義中的默認(rèn)參數(shù)
這似乎是對的?你寫了一個小函數(shù),比如,搜索當(dāng)前頁面上的鏈接,并可選將其附加到另一個提供的列表中。
從表面看,這像是十分正常的 Python 代碼,事實上它也是,而且是可以運行的。但是,這里有個問題。如果我們給 add_to 參數(shù)提供了一個列表,它將按照我們預(yù)期的那樣工作。但是,如果我們讓它使用默認(rèn)值,就會出現(xiàn)一些神奇的事情。
試試下面的代碼:
def fn(var1, var2=[]):
var2.append(var1)
print(var2)
fn(3)
fn(4)
fn(5)
可能你認(rèn)為我們將看到:
[3]
[4]
[5]
但實際上,我們看到的卻是:
[3]
[3,4]
[3,4,5]
為什么呢?如你所見,每次都使用的是同一個列表,輸出為什么會是這樣?在 Python 中,當(dāng)我們編寫這樣的函數(shù)時,這個列表被實例化為函數(shù)定義的一部分。當(dāng)函數(shù)運行時,它并不是每次都被實例化。這意味著,這個函數(shù)會一直使用完全一樣的列表對象,除非我們提供一個新的對象:
fn(3,[4])
[4,3]
答案正如我們所想的那樣。要想得到這種結(jié)果,正確的方法是:
def fn(var1, var2=None):
ifnot var2:
var2 =[]
var2.append(var1)
或是在第一個例子中:
def search_for_links(page, add_to=None):
ifnot add_to:
add_to =[]
new_links = page.search_for_links()
add_to.extend(new_links)
return add_to
這將在模塊加載的時候移走實例化的內(nèi)容,以便每次運行函數(shù)時都會發(fā)生列表實例化。請注意,對于不可變數(shù)據(jù)類型,比如元組、字符串、整型,是不需要考慮這種情況的。這意味著,像下面這樣的代碼是非??尚械模?nbsp;
def func(message="my message"):
print(message)
2、 可變數(shù)據(jù)類型作為類變量
這和上面提到的最后一個錯誤很相像。思考以下代碼:
class URLCatcher(object):
urls =[]
def add_url(self, url):
self.urls.append(url)
這段代碼看起來非常正常。我們有一個儲存 URL 的對象。當(dāng)我們調(diào)用 add_url 方法時,它會添加一個給定的 URL 到存儲中??雌饋矸浅U_吧?讓我們看看實際是怎樣的:
a =URLCatcher()
a.add_url('http://www.google.com')
b =URLCatcher()
b.add_url('http://www.pythontab.com')
print(b.urls)
print(a.urls)
結(jié)果:
['http://www.google.com','http://www.pythontab.com']
['http://www.google.com','http://www.pythontab.com']
等等,怎么回事?!我們想的不是這樣啊。我們實例化了兩個單獨的對象 a 和 b。把一個 URL 給了 a,另一個給了 b。這兩個對象怎么會都有這兩個 URL 呢?
這和第一個錯例是同樣的問題。創(chuàng)建類定義時,URL 列表將被實例化。該類所有的實例使用相同的列表。在有些時候這種情況是有用的,但大多數(shù)時候你并不想這樣做。你希望每個對象有一個單獨的儲存。為此,我們修改代碼為:
class URLCatcher(object):
def __init__(self):
self.urls =[]
def add_url(self, url):
self.urls.append(url)
現(xiàn)在,當(dāng)創(chuàng)建對象時,URL 列表被實例化。當(dāng)我們實例化兩個單獨的對象時,它們將分別使用兩個單獨的列表。
3、 可變的分配錯誤
這個問題困擾了我一段時間。讓我們做出一些改變,并使用另一種可變數(shù)據(jù)類型 - 字典。
a ={'1':"one",'2':'two'}
現(xiàn)在,假設(shè)我們想把這個字典用在別的地方,且保持它的初始數(shù)據(jù)完整。
b = a
b['3']='three'
簡單吧?
現(xiàn)在,讓我們看看原來那個我們不想改變的字典 a:
{'1':"one",'2':'two','3':'three'}
哇等一下,我們再看看 b?
{'1':"one",'2':'two','3':'three'}
等等,什么?有點亂……讓我們回想一下,看看其它不可變類型在這種情況下會發(fā)生什么,例如一個元組:
c =(2,3)
d = c
d =(4,5)
現(xiàn)在 c 是 (2, 3),而 d 是 (4, 5)。
這個函數(shù)結(jié)果如我們所料。那么,在之前的例子中到底發(fā)生了什么?當(dāng)使用可變類型時,其行為有點像 C 語言的一個指針。在上面的代碼中,我們令 b = a,我們真正表達(dá)的意思是:b 成為 a 的一個引用。它們都指向 Python 內(nèi)存中的同一個對象。聽起來有些熟悉?那是因為這個問題與先前的相似。
列表也會發(fā)生同樣的事嗎?是的。那么我們?nèi)绾谓鉀Q呢?這必須非常小心。如果我們真的需要復(fù)制一個列表進(jìn)行處理,我們可以這樣做:
這將遍歷并復(fù)制列表中的每個對象的引用,并且把它放在一個新的列表中。但是要注意:如果列表中的每個對象都是可變的,我們將再次獲得它們的引用,而不是完整的副本。
假設(shè)在一張紙上列清單。在原來的例子中相當(dāng)于,A 某和 B 某正在看著同一張紙。如果有個人修改了這個清單,兩個人都將看到相同的變化。當(dāng)我們復(fù)制引用時,每個人現(xiàn)在有了他們自己的清單。但是,我們假設(shè)這個清單包括尋找食物的地方。如果“冰箱”是列表中的第一個,即使它被復(fù)制,兩個列表中的條目也都指向同一個冰箱。所以,如果冰箱被 A 修改,吃掉了里面的大蛋糕,B 也將看到這個蛋糕的消失。這里沒有簡單的方法解決它。只要你記住它,并編寫代碼的時候,使用不會造成這個問題的方式。
字典以相同的方式工作,并且你可以通過以下方式創(chuàng)建一個昂貴副本:
再次說明,這只會創(chuàng)建一個新的字典,指向原來存在的相同的條目。因此,如果我們有兩個相同的列表,并且我們修改字典 a 的一個鍵指向的可變對象,那么在字典 b 中也將看到這些變化。
可變數(shù)據(jù)類型的麻煩也是它們強(qiáng)大的地方。以上都不是實際中的問題;它們是一些要注意防止出現(xiàn)的問題。在第三個項目中使用昂貴復(fù)制操作作為解決方案在 99% 的時候是沒有必要的。
總結(jié)
以上就是本文關(guān)于淺談使用Python變量時要避免的3個錯誤的全部內(nèi)容,希望對大家有所幫助。
數(shù)據(jù)分析咨詢請掃描二維碼
若不方便掃碼,搜微信號:CDAshujufenxi
LSTM 模型輸入長度選擇技巧:提升序列建模效能的關(guān)鍵? 在循環(huán)神經(jīng)網(wǎng)絡(luò)(RNN)家族中,長短期記憶網(wǎng)絡(luò)(LSTM)憑借其解決長序列 ...
2025-07-11CDA 數(shù)據(jù)分析師報考條件詳解與準(zhǔn)備指南? ? 在數(shù)據(jù)驅(qū)動決策的時代浪潮下,CDA 數(shù)據(jù)分析師認(rèn)證愈發(fā)受到矚目,成為眾多有志投身數(shù) ...
2025-07-11數(shù)據(jù)透視表中兩列相乘合計的實用指南? 在數(shù)據(jù)分析的日常工作中,數(shù)據(jù)透視表憑借其強(qiáng)大的數(shù)據(jù)匯總和分析功能,成為了 Excel 用戶 ...
2025-07-11尊敬的考生: 您好! 我們誠摯通知您,CDA Level I和 Level II考試大綱將于 2025年7月25日 實施重大更新。 此次更新旨在確保認(rèn) ...
2025-07-10BI 大數(shù)據(jù)分析師:連接數(shù)據(jù)與業(yè)務(wù)的價值轉(zhuǎn)化者? ? 在大數(shù)據(jù)與商業(yè)智能(Business Intelligence,簡稱 BI)深度融合的時代,BI ...
2025-07-10SQL 在預(yù)測分析中的應(yīng)用:從數(shù)據(jù)查詢到趨勢預(yù)判? ? 在數(shù)據(jù)驅(qū)動決策的時代,預(yù)測分析作為挖掘數(shù)據(jù)潛在價值的核心手段,正被廣泛 ...
2025-07-10數(shù)據(jù)查詢結(jié)束后:分析師的收尾工作與價值深化? ? 在數(shù)據(jù)分析的全流程中,“query end”(查詢結(jié)束)并非工作的終點,而是將數(shù) ...
2025-07-10CDA 數(shù)據(jù)分析師考試:從報考到取證的全攻略? 在數(shù)字經(jīng)濟(jì)蓬勃發(fā)展的今天,數(shù)據(jù)分析師已成為各行業(yè)爭搶的核心人才,而 CDA(Certi ...
2025-07-09【CDA干貨】單樣本趨勢性檢驗:捕捉數(shù)據(jù)背后的時間軌跡? 在數(shù)據(jù)分析的版圖中,單樣本趨勢性檢驗如同一位耐心的偵探,專注于從單 ...
2025-07-09year_month數(shù)據(jù)類型:時間維度的精準(zhǔn)切片? ? 在數(shù)據(jù)的世界里,時間是最不可或缺的維度之一,而year_month數(shù)據(jù)類型就像一把精準(zhǔn) ...
2025-07-09CDA 備考干貨:Python 在數(shù)據(jù)分析中的核心應(yīng)用與實戰(zhàn)技巧? ? 在 CDA 數(shù)據(jù)分析師認(rèn)證考試中,Python 作為數(shù)據(jù)處理與分析的核心 ...
2025-07-08SPSS 中的 Mann-Kendall 檢驗:數(shù)據(jù)趨勢與突變分析的有力工具? ? ? 在數(shù)據(jù)分析的廣袤領(lǐng)域中,準(zhǔn)確捕捉數(shù)據(jù)的趨勢變化以及識別 ...
2025-07-08備戰(zhàn) CDA 數(shù)據(jù)分析師考試:需要多久?如何規(guī)劃? CDA(Certified Data Analyst)數(shù)據(jù)分析師認(rèn)證作為國內(nèi)權(quán)威的數(shù)據(jù)分析能力認(rèn)證 ...
2025-07-08LSTM 輸出不確定的成因、影響與應(yīng)對策略? 長短期記憶網(wǎng)絡(luò)(LSTM)作為循環(huán)神經(jīng)網(wǎng)絡(luò)(RNN)的一種變體,憑借獨特的門控機(jī)制,在 ...
2025-07-07統(tǒng)計學(xué)方法在市場調(diào)研數(shù)據(jù)中的深度應(yīng)用? 市場調(diào)研是企業(yè)洞察市場動態(tài)、了解消費者需求的重要途徑,而統(tǒng)計學(xué)方法則是市場調(diào)研數(shù) ...
2025-07-07CDA數(shù)據(jù)分析師證書考試全攻略? 在數(shù)字化浪潮席卷全球的當(dāng)下,數(shù)據(jù)已成為企業(yè)決策、行業(yè)發(fā)展的核心驅(qū)動力,數(shù)據(jù)分析師也因此成為 ...
2025-07-07剖析 CDA 數(shù)據(jù)分析師考試題型:解鎖高效備考與答題策略? CDA(Certified Data Analyst)數(shù)據(jù)分析師考試作為衡量數(shù)據(jù)專業(yè)能力的 ...
2025-07-04SQL Server 字符串截取轉(zhuǎn)日期:解鎖數(shù)據(jù)處理的關(guān)鍵技能? 在數(shù)據(jù)處理與分析工作中,數(shù)據(jù)格式的規(guī)范性是保證后續(xù)分析準(zhǔn)確性的基礎(chǔ) ...
2025-07-04CDA 數(shù)據(jù)分析師視角:從數(shù)據(jù)迷霧中探尋商業(yè)真相? 在數(shù)字化浪潮席卷全球的今天,數(shù)據(jù)已成為企業(yè)決策的核心驅(qū)動力,CDA(Certifie ...
2025-07-04CDA 數(shù)據(jù)分析師:開啟數(shù)據(jù)職業(yè)發(fā)展新征程? ? 在數(shù)據(jù)成為核心生產(chǎn)要素的今天,數(shù)據(jù)分析師的職業(yè)價值愈發(fā)凸顯。CDA(Certified D ...
2025-07-03