1. 程式人生 > >python學習筆記:第7天 深淺拷貝

python學習筆記:第7天 深淺拷貝

我們 spl 交集 再次 ipy section 結束 技術分享 dict

目錄

  • 1. 基礎數據類型補充
  • 2. set集合
  • 3. 深淺拷貝

1. 基礎數據類型補充

(1)join方法

join方法是把一個列表中的數據進行拼接,拼接成字符串(與split方法相反,split方法是把一個字符串切割成列表)

In [1]: l1 = [‘a‘, ‘b‘, ‘c‘]

In [2]: s1 = ‘‘

In [3]: for i in l1:            # 如果不使用join方法需要自己使用循環拼接成字符串
   ...:     s1 += i + ‘-‘

In [4]: s1.strip(‘-‘)
Out[4]: ‘a-b-c‘

In [5]: l1
Out[5]: [‘a‘, ‘b‘, ‘c‘]

In [6]: s2 = ‘-‘.join(l1)       # 使用join方法可以直接把字符串拼接

In [7]: s2
Out[7]: ‘a-b-c‘

(2)列表和字典的刪除及類型轉換

對於列表和字典的刪除,有一個需要註意的地方,我們先來看個例子:

In [10]: l2 = [ ‘a‘, ‘b‘, ‘c‘, ‘e‘, ‘f‘ ]

In [11]: for i in l2:
    ...:     l2.remove(i)

In [12]: l2
Out[12]: [‘b‘, ‘e‘]

In [13]:

上面的例子中是遍歷列表l2並循環刪除列表中的元素,但是最後打印時還存在2個元素‘b’和‘e’,為什麽這兩個元素沒有被刪除,分析如下:

  • 首次遍歷列表時,i的值為‘a’,然後在列表中把元素刪除後,列表中後面的索引位置都往前移動了一位,此時索引為0的位置的值為‘b’
  • 第二次次遍歷時,取到索引為1的元素是‘c’,也就是在列表中把‘c’刪除了,然後後面的索引又往前移動了
  • 第三次循環時i的值為‘f’,把元素‘f’刪除後,循環結束,於是最後還剩下了2個元素

從上面的分析來看,我們可以得出:在循環遍歷列表時,不應該去刪除列表的元素,否則後續的程序可能出現意料之外的錯誤;如果需要刪除多個元素可以使用下面這種方法:

In [19]: l2 = [ ‘a‘, ‘b‘, ‘c‘, ‘e‘, ‘f‘ ]

In [20]: del_l2 = []

In [21]: for i in l2:           # 遍歷列表,把要刪除的元素添加到另一個列表中,然後再對列表進行刪除
    ...:     del_l2.append(i)

In [22]: for i in del_l2:
    ...:     l2.remove(i)

In [23]: l2
Out[23]: []

In [24]:

然後我們再來看下字典遍歷時的問題:

In [24]: d1 = {‘a‘:1, ‘b‘:2}

In [25]: for k in d1:
    ...:     del d1[k]
---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
<ipython-input-25-a77d5961c011> in <module>
----> 1 for k in d1:
      2     del d1[k]

RuntimeError: dictionary changed size during iteration

In [26]:

從上面的結果可以看出,字典在遍歷的時候不允許做刪除操作(RuntimeError: dictionary changed size during iteration),要刪除時跟列表一樣,把要刪除的元素的key保存在列表中,循環結束後再刪除。

(3)字典的fromkey方法及數據類型轉換

fromkey方法

dict中的fromkey(),可以幫我們通過list來創建?個dict:

In [26]: dict.fromkeys(‘abc‘, 100)
Out[26]: {‘a‘: 100, ‘b‘: 100, ‘c‘: 100}

In [27]: dict.fromkeys(‘abc‘, [100, 200, 300])
Out[27]: {‘a‘: [100, 200, 300], ‘b‘: [100, 200, 300], ‘c‘: [100, 200, 300]}

In [28]: d2 = dict.fromkeys(‘abc‘, 100)

In [29]: d2
Out[29]: {‘a‘: 100, ‘b‘: 100, ‘c‘: 100}

In [30]: d3 = dict.fromkeys(‘abc‘, [100, 200, 300])

In [31]: d3
Out[31]: {‘a‘: [100, 200, 300], ‘b‘: [100, 200, 300], ‘c‘: [100, 200, 300]}

fromkey方法接收兩個參數,第一個是一個可叠代的數據,叠代出的每個元素作為字典的key,第二個參數作為字典value,但是這裏要註意的是,如果第二個參數是一個可變的數據類型,只要修改其中一個值那麽其他的值也會被修改:

In [32]: d3[‘a‘].pop()
Out[32]: 300

In [33]: d3
Out[33]: {‘a‘: [100, 200], ‘b‘: [100, 200], ‘c‘: [100, 200]}

數據類型的轉換

  • 元組 => 列表 list(tuple)
  • 列表 => 元組 tuple(list)
  • list=>str str.join(list)
  • str=>list str.split()
  • 轉換成False的數據:
    • 0,‘‘,None,[],(),{},set() ==> False
    • 不為空 ===> True

2. set集合

set中的元素是不重復的.?序的,??的元素必須是可hash的(int, str, tuple,bool), 我們可以這樣來記:set就是dict類型的數據但
是不保存value, 只保存key,set也?{}表?。

set中的元素是不重復的, 且?序的:

In [34]: s1 = {‘a‘, ‘a‘, ‘b‘, ‘b‘, ‘c‘}

In [35]: s1
Out[35]: {‘a‘, ‘b‘, ‘c‘}

In [36]: s2 = {1, 2, [11, 22]}              # set集合中的元素必須是可hash的,但是set本身是不可hash的
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-36-e5e6f226f8af> in <module>
----> 1 s2 = {1, 2, [11, 22]}

TypeError: unhashable type: ‘list‘

In [37]:

使用元素唯一性的這個特性,可以對對數據去重處理:

In [39]: l1 = [1, 2, 3, 2, 2, 3]

In [40]: l1
Out[40]: [1, 2, 3, 2, 2, 3]

In [41]: set(l1)
Out[41]: {1, 2, 3}

In [42]:

字典的方法

  • add 添加一個元素
  • clear 清空元素
  • pop 隨機刪除
  • remove 刪除指定元素
  • update 對集合進行更新
  • union 並集運算
  • difference 差集運算
  • intersection 交集運算
  • symmetric_difference 反交集運算
  • issubset 子集
  • issuperset 超集

3. 深淺拷貝

(1)賦值操作

In [44]: a = [1, 2, 3, 4]

In [45]: b = a

In [46]: a.append(10)

In [47]: a, b
Out[47]: ([1, 2, 3, 4, 10], [1, 2, 3, 4, 10])

In [48]: c = {‘a‘:1, ‘b‘:2}

In [49]: d = c

In [50]: d[‘c‘] = 5

In [51]: d
Out[51]: {‘a‘: 1, ‘b‘: 2, ‘c‘: 5}

In [52]: c
Out[52]: {‘a‘: 1, ‘b‘: 2, ‘c‘: 5}

In [53]:

對於list, set, dict來說, 直接賦值. 其實是把內存地址交給變量. 並不是復制?份內容. 所以當列表a變了後列表b也跟著變了,字典也是一樣。

(2)淺拷貝

In [53]: l1
Out[53]: [1, 2, 3, 2, 2, 3]

In [54]: l2 = l1.copy()

In [55]: l2
Out[55]: [1, 2, 3, 2, 2, 3]

In [56]: l1.append(‘SEL‘)

In [57]: print(l1, l2)
[1, 2, 3, 2, 2, 3, ‘SEL‘] [1, 2, 3, 2, 2, 3]

In [58]:

從上面的例子可以看出,淺復制(使用copy方法)會把列表l1的內容賦值一份給l2,此時修改l1的內容並不會影響列表l2的內容,下面的圖可以看出變量存放再內存的情況:

技術分享圖片

In [61]: l3 = l2.copy()

In [62]: l3
Out[62]: [1, 2, [3, ‘SEL‘]]

In [63]: l2[2].append(‘hello‘)

In [64]: l2
Out[64]: [1, 2, [3, ‘SEL‘, ‘hello‘]]

In [65]: l3
Out[65]: [1, 2, [3, ‘SEL‘, ‘hello‘]]

In [66]:

但是此時我們可以看到,使用淺拷貝雖然會復制列表裏面的內容,但僅僅是包含第一層,如果列表裏面嵌套了列表,內層的列表的內容變話的話,被復制的列表也會變化,如上所示,把l2的值拷貝給l3之後,修改了l2中嵌套的列表,l3中的也會改變,如下圖所示:

技術分享圖片

(3)深拷貝

In [66]: import copy            # 需要導入copy模塊

In [67]: l5 = [1, 2, [‘a‘, ‘b‘, [‘aa‘, ‘bb‘], 3]]

In [68]: l6 = copy.deepcopy(l5)

In [69]: l5
Out[69]: [1, 2, [‘a‘, ‘b‘, [‘aa‘, ‘bb‘], 3]]

In [70]: l6
Out[70]: [1, 2, [‘a‘, ‘b‘, [‘aa‘, ‘bb‘], 3]]

In [71]: l5[2][2].append(‘cc‘)

In [72]: l5
Out[72]: [1, 2, [‘a‘, ‘b‘, [‘aa‘, ‘bb‘, ‘cc‘], 3]]

In [73]: l6
Out[73]: [1, 2, [‘a‘, ‘b‘, [‘aa‘, ‘bb‘], 3]]

In [74]:

深度拷貝會完全復制整個列表裏的內容,再次修改之前的列表時,新列表並不會受影響:

技術分享圖片

python學習筆記:第7天 深淺拷貝