MIT6.0001 筆記,LECTURE 5:Tuples, List (aliasing, mutability, cloning詳解)

這一篇博客主要來解釋list的高級特性,主要包括aliasing,mutability,和cloning。這三個特性在賦值時需要特別注意。本篇筆記和代碼都來自於MIT的公開課,第五課。《Introduction to Computer Science and Programming in Python》

aliasing

對於簡單的數據類型,比如int,使用 b = a 賦值之後,b只是得到了a的地址。如果修改b的值,則b的地址同時改變。

a = 1
b = a
print('id(a) is ',id(a))
print('id(b) is ',id(b))
print('a is',a)
print('b is',b)
id(a) is  1865706560
id(b) is  1865706560
a is 1
b is 1
b = 3
print('id(a) is ',id(a))
print('id(b) is ',id(b))
print('a is',a)
print('b is',b)
id(a) is  1865706560
id(b) is  1865706624
a is 1
b is 3

對於複雜的數據結構,比如list,使用 hot = warm賦值之後,hot 是warm的一個aliasing,改變其中的hot的成員將會改變warm。示例解釋了append()的副作用。從下面的例子中可以看到warm和hot擁有同樣的內存地址。

warm = ['red', 'yellow', 'orange']
hot = warm
hot.append('pink')
print('id(warm) is',id(warm))
print('id(hot) is',id(hot))
print('warm is',warm)
print('hot is',hot)
id(warm) is 2533068903048
id(hot) is 2533068903048
warm is ['red', 'yellow', 'orange', 'pink']
hot is ['red', 'yellow', 'orange', 'pink']

cloning

如果我們需要新建一個list,然後得到一份拷貝,也叫cloning。需要使用語句chill = cool[:]。需要注意的是,此時的拷貝是一種淺拷貝,淺拷貝只會拷貝一層。如果list的成員是int,str這些簡單數據結構是沒關係的。但是,如果一個list的成員是複雜數據結構,比如list,淺拷貝只會拷貝外層的list,得到一個新的地址,而成員list的地址不會改變。如果需要得到一個完整的拷貝,需要用到深拷貝

示例如下

cool = ['blue', 'green', 'grey']
chill = cool[:]
chill.append('black')
print(chill)
print(cool)
['blue', 'green', 'grey', 'black']
['blue', 'green', 'grey']

淺拷貝和深拷貝

import copy
list1 = [[1,2],[2,3],[3,4],[4,5]]
list2 = list1.copy()
print('after copy')
print('id list1 is ', id(list1))
print('id list2 is ', id(list2))
print('id list1[0] is ', id(list1[0]))
print('id list2[0] is ', id(list2[0]))
list1[0][0] = 0
print('modify list1[0][0]')
print('list1 = ', list1)
print('list2 = ',list2)
print('id list1[0] is ', id(list1[0]))
print('id list2[0] is ', id(list2[0]))
list1[0] = [0,1]
print('modify list1[0]')
print('list1 = ', list1)
print('list2 = ', list2)
print('id list1[0] is ', id(list1[0]))
print('id list2[0] is ', id(list2[0]))
list2 = copy.deepcopy(list1)
list1[0][0]= 1
print('after deepcopy')
print('modify list1[0][0]')
print('id list1 is ', id(list1))
print('id list2 is ', id(list2))
print('id list1[0] is ', id(list1[0]))
print('id list2[0] is ', id(list2[0]))
print('list1 = ', list1)
print('list2 = ', list2)
after copy,淺拷貝,list1和list2的地址不一樣,但是共享了一片內存空間,list1[0]和list2[0]地址是一樣的
id list1 is  1839475337736
id list2 is  1839475372680
id list1[0] is  1839475372168
id list2[0] is  1839475372168
modify list1[0][0]
list1 =  [[0, 2], [2, 3], [3, 4], [4, 5]]
list2 =  [[0, 2], [2, 3], [3, 4], [4, 5]]
id list1[0] is  1839475372168
id list2[0] is  1839475372168
modify list1[0]
list1 =  [[0, 1], [2, 3], [3, 4], [4, 5]]
list2 =  [[0, 2], [2, 3], [3, 4], [4, 5]]
id list1[0] is  1839463834568
id list2[0] is  1839475372168
after deepcopy,深拷貝,list1和list2的地址不一樣,且指向了不同的內存空間,任何修改都不會相互影響。
modify list1[0][0]
id list1 is  1839475337736
id list2 is  1839475375048
id list1[0] is  1839463834568
id list2[0] is  1839475336584
list1 =  [[1, 1], [2, 3], [3, 4], [4, 5]]
list2 =  [[0, 1], [2, 3], [3, 4], [4, 5]]

sort() 和 sorted的使用

當需要對list類型的數據進行排序時,會用到.sort()方法和sorted。
.sort()是沒有返回值的,會改變list的內容。
sorted() 必須把結果賦值給另外的list變量,且並不會改變輸入list變量。

#########################
## EXAMPLE: sorting with/without mutation
#########################
warm = ['red', 'yellow', 'orange']
sortedwarm = warm.sort()
print(warm)
print(sortedwarm)

cool = ['grey', 'green', 'blue']
sortedcool = sorted(cool)
print(cool)
print(sortedcool)

['orange', 'red', 'yellow']
None
['grey', 'green', 'blue']
['blue', 'green', 'grey']

list的成員是list的情況

當list 的成員是list的時候,這個成員list僅僅保存了一個地址在整個list中。
此時使用append,傳遞的是一個成員list的地址。改變成員list的值,會影響到整體list的值。

#########################
## EXAMPLE: lists of lists of lists...
#########################
warm = ['yellow', 'orange']
hot = ['red']
brightcolors = [warm]
brightcolors.append(hot)
print(brightcolors)
hot.append('pink')
print(hot)
print(brightcolors)
[['yellow', 'orange'], ['red']]
['red', 'pink']
[['yellow', 'orange'], ['red', 'pink']]

循環過程中修改list的情況

###############################
## EXAMPLE: mutating a list while iterating over it
###############################
def remove_dups(L1, L2):
    for e in L1:
        if e in L2:
            L1.remove(e)
      
def remove_dups_new(L1, L2):
    L1_copy = L1[:]
    for e in L1_copy:
        if e in L2:
            L1.remove(e)

L1 = [1, 2, 3, 4]
L2 = [1, 2, 5, 6]
remove_dups(L1, L2)
print(L1, L2)

L1 = [1, 2, 3, 4]
L2 = [1, 2, 5, 6]
remove_dups_new(L1, L2)
print(L1, L2)


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