亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

淺談使用Python變量時要避免的3個錯誤

系統 1525 0

Python編程中經常遇到一些莫名其妙的錯誤, 其實這不是語言本身的問題, 而是我們忽略了語言本身的一些特性導致的,今天就來看下使用Python變量時導致的3個不可思議的錯誤, 以后在編程中要多多注意。

關于Python編程運行時新手易犯錯誤,這里暫不作介紹,詳情參見:Python運行的17個時新手常見錯誤小結

1、 可變數據類型作為函數定義中的默認參數

這似乎是對的?你寫了一個小函數,比如,搜索當前頁面上的鏈接,并可選將其附加到另一個提供的列表中。

            
def search_for_links(page, add_to=[]):
  new_links = page.search_for_links()
  add_to.extend(new_links)
  return add_to
          

從表面看,這像是十分正常的 Python 代碼,事實上它也是,而且是可以運行的。但是,這里有個問題。如果我們給 add_to 參數提供了一個列表,它將按照我們預期的那樣工作。但是,如果我們讓它使用默認值,就會出現一些神奇的事情。

試試下面的代碼:

            
def fn(var1, var2=[]):
  var2.append(var1)
  print(var2)
fn(3)
fn(4)
fn(5)
          

可能你認為我們將看到:

            
[3]
[4]
[5]
          

但實際上,我們看到的卻是:

            
[3]
[3,4]
[3,4,5]
          

為什么呢?如你所見,每次都使用的是同一個列表,輸出為什么會是這樣?在 Python 中,當我們編寫這樣的函數時,這個列表被實例化為函數定義的一部分。當函數運行時,它并不是每次都被實例化。這意味著,這個函數會一直使用完全一樣的列表對象,除非我們提供一個新的對象:

            
fn(3,[4])
[4,3]
          

答案正如我們所想的那樣。要想得到這種結果,正確的方法是:

            
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
          

這將在模塊加載的時候移走實例化的內容,以便每次運行函數時都會發生列表實例化。請注意,對于不可變數據類型,比如元組、字符串、整型,是不需要考慮這種情況的。這意味著,像下面這樣的代碼是非常可行的:

            
def func(message="my message"):
  print(message)
          

2、 可變數據類型作為類變量

這和上面提到的最后一個錯誤很相像。思考以下代碼:

            
class URLCatcher(object):
  urls =[]
  def add_url(self, url):
    self.urls.append(url)
          

這段代碼看起來非常正常。我們有一個儲存 URL 的對象。當我們調用 add_url 方法時,它會添加一個給定的 URL 到存儲中。看起來非常正確吧?讓我們看看實際是怎樣的:

            
a =URLCatcher()
a.add_url('http://www.google.com')
b =URLCatcher()
b.add_url('http://www.pythontab.com')
print(b.urls)
print(a.urls)
          

結果:

            
['http://www.google.com','http://www.pythontab.com']
['http://www.google.com','http://www.pythontab.com']
          

等等,怎么回事?!我們想的不是這樣啊。我們實例化了兩個單獨的對象 a 和 b。把一個 URL 給了 a,另一個給了 b。這兩個對象怎么會都有這兩個 URL 呢?

這和第一個錯例是同樣的問題。創建類定義時,URL 列表將被實例化。該類所有的實例使用相同的列表。在有些時候這種情況是有用的,但大多數時候你并不想這樣做。你希望每個對象有一個單獨的儲存。為此,我們修改代碼為:

            
class URLCatcher(object):
  def __init__(self):
    self.urls =[]
  def add_url(self, url):
    self.urls.append(url)
          

現在,當創建對象時,URL 列表被實例化。當我們實例化兩個單獨的對象時,它們將分別使用兩個單獨的列表。

3、 可變的分配錯誤

這個問題困擾了我一段時間。讓我們做出一些改變,并使用另一種可變數據類型 - 字典。

            
a ={'1':"one",'2':'two'}
          

現在,假設我們想把這個字典用在別的地方,且保持它的初始數據完整。

            
b = a
b['3']='three'
          

簡單吧?

現在,讓我們看看原來那個我們不想改變的字典 a:

            
{'1':"one",'2':'two','3':'three'}
          

哇等一下,我們再看看 b?

            
{'1':"one",'2':'two','3':'three'}
          

等等,什么?有點亂……讓我們回想一下,看看其它不可變類型在這種情況下會發生什么,例如一個元組:

            
c =(2,3)
d = c
d =(4,5)
          

現在 c 是 (2, 3),而 d 是 (4, 5)。

這個函數結果如我們所料。那么,在之前的例子中到底發生了什么?當使用可變類型時,其行為有點像 C 語言的一個指針。在上面的代碼中,我們令 b = a,我們真正表達的意思是:b 成為 a 的一個引用。它們都指向 Python 內存中的同一個對象。聽起來有些熟悉?那是因為這個問題與先前的相似。

列表也會發生同樣的事嗎?是的。那么我們如何解決呢?這必須非常小心。如果我們真的需要復制一個列表進行處理,我們可以這樣做:

            
b = a[:]
          

這將遍歷并復制列表中的每個對象的引用,并且把它放在一個新的列表中。但是要注意:如果列表中的每個對象都是可變的,我們將再次獲得它們的引用,而不是完整的副本。

假設在一張紙上列清單。在原來的例子中相當于,A 某和 B 某正在看著同一張紙。如果有個人修改了這個清單,兩個人都將看到相同的變化。當我們復制引用時,每個人現在有了他們自己的清單。但是,我們假設這個清單包括尋找食物的地方。如果“冰箱”是列表中的第一個,即使它被復制,兩個列表中的條目也都指向同一個冰箱。所以,如果冰箱被 A 修改,吃掉了里面的大蛋糕,B 也將看到這個蛋糕的消失。這里沒有簡單的方法解決它。只要你記住它,并編寫代碼的時候,使用不會造成這個問題的方式。

字典以相同的方式工作,并且你可以通過以下方式創建一個昂貴副本:

            
b = a.copy()
          

再次說明,這只會創建一個新的字典,指向原來存在的相同的條目。因此,如果我們有兩個相同的列表,并且我們修改字典 a 的一個鍵指向的可變對象,那么在字典 b 中也將看到這些變化。

可變數據類型的麻煩也是它們強大的地方。以上都不是實際中的問題;它們是一些要注意防止出現的問題。在第三個項目中使用昂貴復制操作作為解決方案在 99% 的時候是沒有必要的。

總結

以上就是本文關于淺談使用Python變量時要避免的3個錯誤的全部內容,希望對大家有所幫助。感興趣的朋友可以繼續參閱本站:python探索之BaseHTTPServer-實現Web服務器介紹、Python探索之SocketServer詳解等,如有不足之處,歡迎留言指出。感謝朋友們對本站的支持!


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 国产香蕉国产精品偷在线观看 | 色综合色狠狠天天综合色 | 免费久久 | 奇米777四色影视在线看 | 9999精品视频| 久久免费99精品久久久久久 | 在线观看国产一区亚洲bd | 欧美一区二区三区视频在线观看 | 一级a性色生活片毛片 | 成人精品国产亚洲 | 国产永久一区二区三区 | 九九99国产精品视频 | 久久精品免费一区二区三区 | 国产成人亚洲综合网站不卡 | 亚洲精品亚洲九十七页 | 精品久久久久中文字幕日本 | 香蕉成人在线 | 日韩久久精品一区二区三区 | 免费观看黄色 | 亚洲精品中文字幕区 | 不卡中文字幕 | 一区二区午夜 | 国产精品福利视频免费观看 | 亚洲图片欧美 | 久久草在线视频 | 羞羞的视频网站 | 日韩经典中文字幕 | 亚洲综合欧美 | 久青草影院在线观看国产 | 伊人色院成人蜜桃视频 | 久久免费福利视频 | 亚洲精品乱码久久久久久中文字幕 | 免费操片 | 2019年国产不卡在线刷新 | 久久爱伊人一区二区三区小说 | 亚洲国产成人久久午夜 | 2021久久伊人精品中文字幕有 | 日日操综合 | 欧美 xx性 在线 | 九九精品免视看国产成人 | 欧美日韩影视 |