list 和 dict 的複製

2021-03-02 Python機器學習算法說書人





我們都知道,Python 中有兩種可變的數據類型:list 和 dict。這兩種數據類型對應的實例也有很多方法可以對自身進行修改,需要注意的是,這裡調用修改相關的方法的時候不是返回修改後的實例,而是就地修改,也就是原地修改。我們有些時候不希望原來的被修改,因此,複製它們的實例就顯得非常重要。




我們都知道,一個 list 乘上一個整數 n 表示重複 list 中的元素 n 次創建一個新 list。這裡需要注意的是 n ≥ 0,如果 n < 0,返回新的空 list(我也不知道為什麼,記就完事了),不相信可以看下面的示例。

>>> [0, 1] * 2[0, 1, 0, 1]>>> [0, 1] * 1[0, 1]>>> [0, 1] * 0[]>>> [0, 1] * -1[]>>> [0, 1] * -2[]

由此可以得出,創建 10 個元素全為 0 的 list 可以這麼做:[0] * 10,我們來看看是不是徹底實現了複製。

>>> a = [0] * 10>>> a[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]>>> a[0] = 1>>> a[1, 0, 0, 0, 0, 0, 0, 0, 0, 0]

果然實現了複製,修改第一個元素的值對其餘的元素沒有影響。然而,事情可能沒有那麼簡單,我們再來看一個例子。

>>> a = [[]] * 10>>> a[[], [], [], [], [], [], [], [], [], []]>>> a[0].append(0)>>> a[[0], [0], [0], [0], [0], [0], [0], [0], [0], [0]]

我們可以發現,結果並不是我們想要的,一改全改。因此,我們發現乘法有些時候不能進行複製。與此同時,我們希望大 list 裡面的小 list 也實現複製,而不是指向同一個,怎麼做?很簡單,使用列表推導式就可以了,還是這個例子。

>>> a = [[] for _ in range(10)]>>> a[[], [], [], [], [], [], [], [], [], []]>>> a[0].append(0)>>> a[[0], [], [], [], [], [], [], [], [], []]

這下應該沒有問題了,針對 list 的元素複製到此結束。如果進行元素複製怕遇到這樣的麻煩就全部使用列表推導式。但是,乘法也要會,因為有些模塊或者是項目的源碼可能會使用乘法!



講完了元素複製,我們來看一下整體複製。因為整體複製針對 list 和 dict 都可以使用,所以我分成兩部分進行講解,先看 list 的整體複製,再看 dict 的整體複製。



我們假設有一個 list 的實例 a,要把它複製給 b,我們能不能直接寫 b = a 呢?其實是不行的,不信的話可以看一下下面的示例。

>>> a = [1, 2, 1]>>> b = a>>> b[2] = 3>>> a[1, 2, 3]

我們可以發現,修改 b 的時候,a 也跟著改了,因此我們可以看出 a 和 b 是同一個 list,如何讓 a 和 b 只是值相等,但它們是不同的 list 呢?

最容易想到的方法就是使用 list 的方法 copy,還是這個例子。

>>> a = [1, 2, 1]>>> b = a.copy()>>> b[2] = 3>>> a[1, 2, 1]

我們可以發現修改 b 對 a 沒有任何影響,因此完成了複製。

完成複製的操作其核心代碼就是第二行,我們還可以使用下面幾種方法來完成複製。

>>> b = a[:]>>> b = list(a)>>> b = [_ for _ in a]>>> b = a + []  >>> b = a * 1  

其中後面兩種可能不是那麼容易能夠想得到的,這些方法都能完成複製,大家可以自己進行驗證,我就不做演示了。

但是,這幾種複製的方法都存在一個問題,我拿使用 copy 方法進行複製來演示一下這個問題。

>>> a = [[], []]>>> b = a.copy()>>> b[0].append(0)>>> a[[0], []]

我們可以發現複製並沒有那麼徹底,我們把這種不徹底的複製稱之為淺複製。那麼,如何不讓它進行所謂的淺複製?我們後面再說,先繼續看 dict 的整體複製。


我們假設有一個 dict 的實例 a,要把它複製給 b,我們能不能直接寫 b = a 呢?其實是不行的,不信的話可以看一下下面的示例。

>>> a = {'1': 1, '2': 2}>>> b = a>>> b['1'] = 0>>> a{'1': 0, '2': 2}

我們可以發現,當 b 修改對應鍵的值時,a 也跟著修改,因此我們可以看出 a 和 b 是同一個 dict,如何讓 a 和 b 只是值相等,但它們是不同的 dict 呢?

最容易想到的方法就是使用 dict 的方法 copy,還是這個例子。

>>> a = {'1': 1, '2': 2}>>> b = a.copy()>>> b['1'] = 0>>> a{'1': 1, '2': 2}

我們可以發現修改 b 對 a 沒有任何影響,因此完成了複製。

完成複製的操作其核心代碼就是第二行,我們還可以使用下面幾種方法來完成複製。

>>> b = dict(a)>>> b = {k: a[k] for k in a}

但是,這幾種複製的方法都存在一個問題,我拿使用 copy 方法進行複製來演示一下這個問題。

>>> a = {'1': [1], '2': [2]}>>> b = a.copy()>>> b['1'].append(1)>>> a{'1': [1, 1], '2': [2]}

我們可以發現這樣的複製都是淺複製,如何不進行淺複製呢?答案很簡單,進行深複製即可。



我首先來講一下什麼是深複製。深複製,即同時複製值及其包含的所有值,等等。大家看了這麼專業的解釋可能會覺得雲裡霧裡,不過不用擔心,我可以讓大家徹底理解深複製,只要記住一句話就行:「深複製是徹底的複製!

深複製我們沒有必要自己實現,Python 有模塊已經給你實現好了,開箱即用就完事了。還是使用上面的例子進行演示。

>>> a = {'1': [1], '2': [2]}>>> from copy import deepcopy>>> b = deepcopy(a)>>> b['1'].append(1)>>> a{'1': [1], '2': [2]}

同樣的,對於 list 套 list 的情況也必須使用深複製。

當然,我從今年開始已經入駐 B 站了!下面給出 B 站帳號:新時代的運籌帷幄,喜歡的可以關注一下,看完視頻不要忘記一鍵三連啊!

今天的文章有不懂的可以後臺回復「加群」,備註:Python 機器學習算法說書人,不備註可是會被拒絕的哦~!



相關焦點

  • 【掘金使用技巧4】list[dict]類型數據的提取與儲存
    在掘金終端的使用過程中,一些數據的提取和儲存不太方便。小編針對數據的提取和儲存問題,提供一些解決方法和使用範例,歡迎大家一起學習討論。list[dict]類型數據,以tick裡面的quotes為例tick數據是一類比較特殊的數據,返回欄位中的quotes代表五檔行情,是一個list[dict]的結構。
  • Python——dict字典和set集合
    Python內置了字典:dict的支持,dict全稱dictionary,在其他語言中也稱為map,使用鍵-值(key-value)存儲,具有極快的查找速度。舉個例子,假設要根據同學的名字查找對應的成績,如果用list實現,需要兩個list:names = ['張三', '李四', '王五']scores = [95, 75, 85]給定一個名字,要查找對應的成績,就先要在names中找到對應的位置,再從scores取出對應的成績,list越長,耗時越長。
  • 盤點Python編程中dict和set常用用法
    和list比較,dict有以下幾個特點:查找和插入的速度極快,不會隨著key的增加而增加;需要佔用大量的內存,內存浪費多。而list相反:查找和插入的時間隨著元素的增加而增加;佔用空間小,浪費內存很少。所以,dict是用空間來換取時間的一種方法。
  • Python dict字典詳解
    相對地,列表(list)和元組(tuple)都是有序的序列,它們的元素在底層是挨著存放的。字典類型是 Python 中唯一的映射類型。「映射」是數學中的術語,簡單理解,它指的是元素之間相互對應的關係,即通過一個元素,可以唯一找到另一個元素。如圖 1 所示。
  • 理解Python中__dict__是怎樣一種體驗
    答案是__dict__,Python中的所有內建(build-in)數據類型(type)都有屬性__dcit__,當然自定義的類(class)也有,因為自定義的類也是一種數據類型嘛。在a.age=10前後分別加上一行print a.
  • Python數據類型之字典dict
    # 字典是一種可變容器類型,可存儲任意類型對象# 字典以鍵值對存儲數據,key-value形式,鍵值之間使用冒號:分隔,每個鍵值中間用逗號,分隔# 字典包含在大括號,花括號{}中# python中鍵必須是不可變的,但值可取任何數據類型# 元組可以作為 dict 的 key,但列表不能作為元組的 key,dict 要求
  • python中字典dict的操作技巧匯總
    字典通過大括號或者dict函數來創建,用法如下>>> a = {'one':1, 'tow':2, 'three':3}>>> a{'one': 1, 'tow': 2, 'three': 3}>>> type(a)<class 'dict'>key和value
  • Python中的基礎數據類型(List,Tuple,Dict)及其常用用法簡析
    列表排序,最大(小)值li = [8, 2, 6, 8, 5]li.sort() print(li)li = ['b', '5', 'z', 'y', 'r', 'l']li.sort()print(li)print(max(li))print(min(li))
  • Pandas 基本使用(二) — DataFrame.to_dict() 函數使用
    {column(列名) : value(值)}};備註:1,上面中 value 代表數據表中的值,column表示列名,index 表示行名,如下圖所示:Snipaste_2020-03-09_00-16-58.jpg2,{ }表示字典數據類型,字典中的數據是以 {key : value} 的形式顯示,是鍵名和鍵值一一對應形成的
  • Redis 內部數據結構詳解(1):dict
    比如:stringlisthashsetsorted set這一層面也是Redis暴露給外部的調用接口。第二個層面,是從內部實現的角度,屬於更底層的實現。比如:dictsdsziplistquicklistskiplist第一個層面的「數據結構」,Redis的官方文檔(http://redis.io/topics/data-types-intro)有詳細的介紹。
  • Python基礎知識儲備,字典dict的用法,花個幾分鐘時間學習它吧
    = {20190101: "王一", 20190102: "王二", 20190103: "王三", 20190101: "王四"}print(dict01)如:dict01中有兩個學號為20190101的學生,最後print列印僅顯示最後一個元素。
  • Python dict字典方法完全攻略(全)
    我們知道,Python 字典的數據類型為 dict,我們可使用 dir(dict) 來查看該類型包含哪些方法,例如:>>
  • Python中字典(dict)的基本講解
    一:字典(dict)字典和前面講的列表與元組不太一樣,列表和元組都是一個有序的序列,但是字典是一個無序的可變的序列,並且字典中的元素以「鍵值對」的形式存在,可以方便快捷的進行查找元素。字典中鍵(key)和值(value)的關係可以參考數學中映射的概念,我們可以通過鍵(key)來快速找到對應的值(value),也就是說鍵(key)是各個元素對應的索引,值(value)是各個鍵對應的元素,鍵(key)和其關聯的值(value)稱之為鍵值對。
  • Python:Pandas的DataFrame如何按指定list排序
    >df指定list元素多的情況:若指定的list所包含元素比Dataframe中需要排序的列的元素多,怎麼辦?list_custom_new = ['d', 'c', 'b','a','e']dict_new = {'e':1, 'b':2, 'c':3}df_new = pd.DataFrame(list(dict_new.items()), columns=['words', 'value'])print(list_custom_new)
  • Python筆記:List相關操作
    List相關操作小例子獲取list的下標和值
  • 構建簡單數據管道,為什麼tf.data要比feed_dict更好?
    在大多數面向初學者的TensorFlow教程裡,作者通常會建議讀者在會話中用feed_dict為模型導入數據——feed_dict是一個字典,能為佔位符饋送數據
  • 英文單詞記憶法:詞根dict的用法
    新東方網>英語>英語學習>語法詞彙>詞彙指導>正文英文單詞記憶法:詞根dict的用法 2016-01-15 15:51 來源:北京新東方 作者:林莉涵
  • python之[] 與 list()分析
    # 使用一對中括號list_a = []# 使用內置函數list_b = list()    SO.這兩種方法有什麼不一樣呢?哪個會快一點呢?    而對於 list(),「list」只是一個普通的名稱,並不是字面量,也就是說解釋器一開始並不認識它。因此,解釋器的第一步是要找到這個名稱(對應LOAD_NAME)。它會按照一定的順序,在各個作用域中逐一查找(局部作用域--全局作用域--內置作用域),直到找到為止,找不到則拋出NameError異常。
  • 雲計算開發學習筆記:Python3字典鍵特性和字典內置函數
    str(dict) 輸出字典,以可列印的字符串表示。 type(variable) 返回輸入的變量類型,如果變量是字典就返回字典類型。 Python字典包含了以下內置方法:函數描述 radiansdict.clear() 刪除字典內所有元素。
  • Python 3.9.0 beta4 發布 在內置的dict 函數加入 Union 運算符
    Beta 版本預覽旨在為廣大社區提供測試新功能和錯誤修復以及準備其項目以支持新功能版本的機會。  · Python 3.9 部分主要新功能和變更:  · PEP 584, 在內置的 dict 函數加入 Union 運算符  · PEP 585, 類型標註中內置通用類型  · PEP 593, 靈活的函數和變量註解  · PEP 602, Python 採用穩定的年度發布節奏  · PEP 615, 支持標準庫中的