語法:Python中的引用和副本

實踐纔是最好的老師,對於程序員來說可能更爲重要。

首先列出在編碼中遇到的問題,給出一個列表nums=[1,2,3,3,3,4],要求將這個列表中值爲3的元素刪除,計算剩下列表的長度。

題目並不難,一個思想就是遍歷list元素,一旦該元素屬於這個列表,從該鏈表中刪除,因爲鏈表是可覆蓋對象,遍歷完成後計算鏈表的長度即可。

但是我在編碼中發現了一個問題。

nums=[1,2,3,3,3,4]
for i in nums:
    if i ==3:
        nums.remove(i)
print(len(nums))

看上去程序沒有什麼問題,但是結果並不是預期中的3,而是4。想過採用下面這種方式,就會得到正確答案。

nums=[1,2,3,3,3,4]
for i in nums[:]:
    if i ==3:
        nums.remove(i)
print(len(nums))

nums和nums[:]之間的區別,其實就是引用和副本之間的區別,針對可覆蓋變量,如果兩個變量引用相同的內存,指向同一個對象,修改一個變量的值就會連帶的對另一個變量造成影響。這爲某些程序的實現提供了方便,同時也容易產生不易發現的BUG。通過創建對應的副本,可以避免這樣的影響。

在第一個代碼塊中,由於nums是可覆蓋變量,當遇到nums中的第一個值爲3的元素是,這時候i遍歷到了nums中的第3個位置,由於符合刪除條件,nums執行移除remove操作,這時候nums變成了[1,2,3,3,4],接下來i應該查找nums中的第四個位置,這時候就會忽略在nums裏的第一個3,直接跳到了第二個3,完成了remove操作,造成最終結果nums變成[1,2,3,4],所以長度爲4。使用nums的副本很好的避免了這個問題。

下面這個程序可以更好的說明問題。

nums=[1,2,[3,3,3],4]
for i in nums:
    if type(i) is list:
        print(i[:])
        for j in i[:]:
            i[:].remove(j)
        print(i[:])
print(nums)

輸出結果:
這裏寫圖片描述

也不知道我接受的清不清楚,有問題大家一起交流哦。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章