1. 程式人生 > >python學習打卡 day07 set集合,深淺拷⻉貝以及部分知識點補充

python學習打卡 day07 set集合,深淺拷⻉貝以及部分知識點補充

本節的主要內容:

  1. 基礎資料型別補充
  2. set集合
  3. 深淺拷貝

主要內容:

一.基礎資料型別補充

字串:

li = ["李嘉誠", "麻花藤", "⻩海峰", "劉嘉玲"] 
s = "_".join(li) print(s) 
# 李嘉誠_麻花藤_黃海峰_劉嘉玲

可以看出 join() 的作用是把列表中的字串拼接起來,正好和 split() 相反

字串轉化成列表: split()

列表轉化成字串:join()x->y型別 y(x)表示False的資料型別: False, 0, "", [], tuple(), dict(), set(), None.

列表:

   迴圈刪除列表中的每一個元素.

li = [11, 22, 33, 44] 
for e in li:    
    li.remove(e) 
print(li) 
#結果: [22, 44]

原因分析:

for的運行過程. 會有一個指標來記錄當前迴圈的元素是哪一個, 一開始這個指標指向第0 個. 然後獲取到第0個元素. 緊接著刪除第0個.

這個時候. 原來是第一個的元素會自動的變成第0個. 然後指標向後移動一次, 指向1元素.  這時原來的1已經變成了0, 也就不會被刪除了. 

用del 和pop試試看:

li = [11, 22, 33, 44] 
for i in range(0, len(li)):    
    
del li[i] print(li) 結果: 報錯 # i= 0, 1, 2 刪除的時候li[0] 被刪除之後.後面一個就變成了第0個. # 以此類推. 當i = 2的時候. list中只有一個元素. 但是這個時候刪除的是第2個 肯定報錯啊

經過測試分析發現,迴圈刪除都不行,不論是用del還remove,都不能實現

for el in li:    
    li.pop()    # pop也不行 
print(li) 
#結果: [11, 22]

經過測試發現pop也不能實現迴圈刪除

所以要執行迴圈刪除只有這樣才行:

for i in range(0, len(li)):    #
迴圈len(li)次, 然後從後往前刪除 li.pop() print(li)

或者用另一個列表來記錄你要刪除的內容.然後迴圈刪除

li = [11, 22, 33, 44] 
del_li = [] 
for e in li:    
    del_li.append(e) 
for e in del_li:    
    li.remove(e)   
print(li)

注意:由於刪除元素會導致元素的索引改變,所以容易出現問題.儘量不要在迴圈中直接去刪除元素,可以把要刪除的元素新增到另一個集合中然後再批量刪除.

dic中的fromkeys(),可以幫我們通過list來建立一個dict

dic = dict.fromkeys(["jay", "JJ"], ["周杰倫", "麻花藤"]) 
print(dic) 
結果: {'jay': ['周杰倫', '麻花藤'], 'JJ': ['周杰倫', '麻花藤']

前面列表中的每一項都會作為key,後面列表中的內容作為value,生成dict

但是,要注意:

dic = dict.fromkeys(["jay", "JJ"], ["周杰倫", "麻花藤"]) 
print(dic) 
dic.get("jay").append("胡⼤大") 
print(dic) 
結果: {'jay': ['周杰倫', '麻花藤', '胡⼤大'], 'JJ': ['周杰倫', '麻花藤', '胡⼤大']}

程式碼中只是更改了jay那個列表.但是由於jay和JJ用的是同一個列表,所以前面那個改了後面這個也會跟著改

dict中的元素在迭代過程中是不允許進行刪除的

dic = {'k1': 'alex', 'k2': 'wusir', 's1': '金老板'} 
# 刪除key中帶有'k'的元素 
for k in dic:    if 'k' in k:        
del dic[k]      # dictionary changed size during iteration, 在迴圈迭代的時候不允許進行刪除操作 
print(dic)

要進行刪除操作,可以把要刪除的元素暫時先儲存在一個list中,然後迴圈list,再刪除:

dic = {'k1': 'alex', 'k2': 'wusir', 's1': '金老板'} 
dic_del_list = [] 
# 刪除key中帶有'k'的元素 
for k in dic:    
    if 'k' in k:        
    dic_del_list.append(k) 
for el in dic_del_list:    
    del dic[el] 
print(dic)

 二.set集合

set集合是python的一個基本資料型別.一般不是很常用,set中的元素是不重複的.無序的.裡面的元素必須是可雜湊的(int,str,tuple,bool),我們可以

這樣來理解:set就是dict型別的資料,但是是不儲存value,只儲存key.set也用{}表示

注意: set集合中的元素必須是可hash的,但set本身是不可hash的,set是可變的

set中的元素是不可重複的,且無序的.我們可利用這個特性用它來去掉重複的元素:

s = {"周杰倫", "周杰倫", "周星星"} 
print(s) 
#結果: {'周星星', '周杰倫'}

set的增刪改查

1.增加

s = {"劉嘉玲", '關之琳', "王祖賢"} 
s.add("鄭裕玲") 
print(s) 
s.add("鄭裕玲")    # 重複的內容不會被新增到set集合中 
print(s) s = {"劉嘉玲", '關之琳', "王祖賢"} 
s.update("麻花藤")    # 迭代更新 
print(s) 
s.update(["張曼玉", "李若彤","李若彤"]) 
print(s)

2.刪除

s = {"劉嘉玲", '關之琳', "王祖賢","張曼玉", "李若彤"} 
item = s.pop()  # 隨機彈出⼀一個. 
print(s) 
print(item) 

s.remove("關之琳") # 直接刪除元素 
# s.remove("馬虎疼") # 不存在這個元素. 刪除會報錯 
print(s) 

s.clear()    # 清空set集合.需要注意的是set集合如果是空的. 打印出來是set() 因為要和 dict區分的.
print(s)    # set()

3.修改

# set集合中的資料沒有索引. 也沒有辦法去定位一個元素. 所以沒有辦法進行直接修改. 
# 我們可以採用先刪除後新增的方式來完成修改操作 
s = {"劉嘉玲", '關之琳', "王祖賢","張曼玉", "李若彤"} 
# 把劉嘉玲改成趙本山 
s.remove("劉嘉玲") 
s.add("趙本山") 
print(s)

4.查詢

# set是一個可迭代物件. 所以可以進行for迴圈 
for el in s:    
print(el)

5.常用操作

s1 = {"劉能", "趙四", "皮長山"}
s2 = {"劉科長", "馮鄉長", 皮長山"} 
# 交集 
# 兩個集合中的共有元素 
print(s1 & s2)  # {'皮長山'} 
print(s1.intersection(s2))  # {'皮長山'} 

# 並集
print(s1 | s2)  # {'劉科長', '馮鄉長', '趙四', '皮長山', '劉能'} print(s1.union(s2))     # {'劉科長', '馮鄉長', '趙四', '皮長山', '劉能'} 

# 差集 
print(s1 - s2)  # {'趙四', '劉能'} 得到第⼀箇中單獨存在的 print(s1.difference(s2))     # {'趙四', '劉能'} 

# 反交集 
print(s1 ^ s2)  # 兩個集合中單獨存在的資料 {'馮鄉長', '劉能', '劉科長', '趙四'} 
print(s1.symmetric_difference(s2)) # {'馮鄉長', '劉能', '劉科長', '趙四'}

s1 = {"劉能", "趙四"} 
s2 = {"劉能", "趙四", "皮長山"} 

# 子集 
print(s1 < s2)  # set1是set2的子集嗎? True 
print(s1.issubset(s2)) 

# 超集 
print(s1 > s2) # set1是set2的超集嗎? False print(s1.issuperset(s2))

set集合本身是可以發生改變的,是不可雜湊的,我們可使用frozenset來儲存資料.

frozenset是不可變的,也就是一個可雜湊的資料型別

s = frozenset(["趙本山", "劉能", "皮長山", "長跪"]) 
dic = {s:'123'} # 可以正常使用了 
print(dic) 

 set集合這塊的知識不是很常用,瞭解就可以了

三.深淺拷貝

 lst1 = ["孫悟空", "貝吉塔", "卡卡羅特"]
 lst2 = lst1 # 賦值

 lst1.append("短笛")

 print(lst1)
 print(lst2)

 print(id(lst1), id(lst2))

 對於list,set,dict來說,直接賦值其實是把記憶體地址交給變數,並不是複製一份內容.所以lst1的記憶體指向和lst2是一樣的,lst1改變了,lst2也發生改變

淺拷貝

lst1 = ["孫悟空", "貝吉塔", "卡卡羅特"]
lst2 = lst1[:] # [:] 在原來的資料中獲取到所有的資料組成新的列表
lst2 = lst1.copy() #  拷貝會幫我們建立新物件

lst1.append("短笛")

print(lst1)
print(lst2)

print(id(lst1), id(lst2))
lst1 = ["孫悟空", "貝吉塔", "卡卡羅特",["七龍珠","戰鬥陀螺"]]
lst2 = lst1.copy() # 淺拷貝

lst1[3].append("巴啦啦小魔仙")
print(lst1)
print(lst2)
print(id(lst1), id(lst2))

通過上面的兩個例子,可知,淺拷貝只會拷貝第一層的內容,第二層的內容不會拷貝.所以被稱為淺拷貝

深拷貝

import copy # 引入拷貝模組
lst1 = ["孫悟空", "貝吉塔", "卡卡羅特",["七龍珠","戰鬥陀螺"]]
lst2 = copy.deepcopy(lst1) # 會把這個物件相關的內部資訊全部複製一份

lst1[3].append("巴啦啦小魔仙")
print(lst1)
print(lst2)

print(id(lst1), id(lst2))

經過深拷貝,lst1裡面就算第二層的內容發生改變,lst2的內容也不會跟著改變

深度拷貝:把元素內部的元素完全拷貝複製,不會產生一個改變,另一個跟著改變的問題

淺拷貝的優點是:省記憶體;缺點是:容易出現同一個物件唄多個變數所引用.

深拷貝的優點是:完全拷貝出一份兩個物件之間除了資料相同,沒有任何關係的物件,缺點是:佔記憶體

共同優點:快速建立物件->原型模式(設計模式)

補充一個知識點:

a = [1, 2] 
a[1] = a 
print(a[1])
#結果是 [1,[...]]

原因: a與a[1]相互賦值陷入了死迴圈,使得後面的內容計算不出來