基本數據類型補充 set集合 深淺拷貝

 

 

1、基本數據類型補充python

1,關於int和str在以前的學習中已經介紹了80%以上了,如今再補充一個字符串的基本操做:app

複製代碼
    li = ['李嘉誠','何炅','海峯','劉嘉玲']
    s = "_".join(li)
    print(s)  # 結果爲:李嘉誠_何炅_海峯_劉嘉玲

    li = '黃花大閨女'
    s = "_".join(li)
    print(s)  # 結果爲:黃_花_大_閨_女
複製代碼

2,列表相關:學習

  循環刪除列表中的每個元素,有以下代碼,注意結果並分析緣由:spa

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

  分析緣由:for的運行過程當中,會有一個指針來記錄當前循環的元素是哪個,一開始這個指針指向第0個,而後獲取到第0個元素,緊接着刪除第0個,這個時候,原來第一個元素會自動的變成第0 個元素,而後指針向後移動一次,指向1元素,這時原來的1變成了0,也就不會被刪除了。指針

       用range()刪除試試看,以下代碼:code

複製代碼
    li = [11,22,33,44]
    for i in range(0,len(li)):
        del li[i]
    print(li)
    # 結果:報錯,IndexError: list assignment index out of range
    # i = 0,1,2,3,刪除的時候,li[0]被刪除以後,後一個就變成了第0個,以此類推
    # 當i = 2的時候,list中還有兩個元素,可是這個時候刪除的是第3個,因此會報錯
複製代碼

  經分析發現,循環刪除都不行,不論用del仍是remove,都不能實現,那麼用pop呢?具體以下:對象

    li = [11,22,33,44]
    for el in li:
        li.pop()
    print(li)  # 結果爲:[11, 22],因此pop也不能徹底刪除

因此下面這樣是能夠的:blog

    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)
複製代碼

注意:因爲刪除元素會致使元素的索引改變,因此容易出現問題,所以儘可能不要在循環中直接去刪除元素,能夠把要刪除的元素添加到另外一個列表中而後再批量刪除。內存

3,字典(dict)中的fromkeys()能夠幫咱們經過list來建立一個dict, 須要注意的是fromkeys直接使用類名(dict)進行訪問,具體代碼以下:

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

  能夠看出,前面的列表中的每一項都會做爲key,後面列表中的內容做爲value,生產dict。

如今請看下面一段代碼:

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

  能夠看出,代碼中只是更改了jay那個列表,可是因爲jay和JJ用的是同一個列表,因此,前面那個改了,後面那個也會跟着改。

4,字典(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)
複製代碼

5,類型轉換

       元組 = > 列表  list(tuple)

       列表 = > 元組  tuple(list)

       list  = >  str   str.join(list)

       str  = >  list   str.split()

       能轉換成False的數據:0,’’,None,[],(),{},set() =>False

2、集合

       set(集合)是python的一個基本數據類型,通常不是很經常使用,set中的元素是不重複的,無序的,裏面的元素必須是可hash的(int,tuple,bool),咱們能夠這樣來記,set就是dict類型的數據可是不保存value,只保存key,set也用{}表示。

       注意:set集合中的元素必須是可hash的,可是set自己是不可hash,set是可變的。

    set1 = {'1','alex',2,True,[1,2,3]} # 報錯
    set2 = {'1','alex',2,True,{1:2}} # 報錯
    set3 = {'1','alex',2,True,(1,2,[2,3,4])} # 報錯,set的可哈希元素中也必須是可哈希的

set中的元素是不可重複的,且無序的,以下代碼:

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

使用這個特性,咱們可使用set來去掉重複,以下代碼:

    # 給list去重複
    lst = [45 , 5 , "哈哈", 45 , '哈哈', 50]
    lst = list(set(lst))  # 把list轉換成set, 而後再轉換回list
    print(lst)

如何建立一個空字典和一個空集合:

    d = {}   #建立一個空字典
    s = set()   #建立一個空集合

1,增長

       集合的增長操做有:add,update(迭代更新),具體代碼以下示例:

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

2,刪除

       集合的刪除操做有:pop,remove,clear,具體代碼以下示例:

複製代碼
    s = {"劉嘉玲", '關之琳', "王祖賢","張曼玉", "李若彤"}
    item = s.pop() # 隨機彈出⼀個.返回所彈出的元素
    print(s)
    print(item)

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

    s.clear() 
    # 清空set集合.須要注意的是set集合若是是空的. 打印出來是set() 由於要和dict區分的.
    print(s) # 結果爲:set()
複製代碼

3,修改

       集合中的數據沒有索引. 也沒有辦法去定位一個元素. 因此沒有辦法進行直接修改,咱們能夠採用先刪除後添加的方式來完成修改操做,具體以下示例:

    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集合自己是能夠發生改變的,是不可hash的,咱們可使用frozenset來保存數據。

frozenset是不可變的,也就是一個可哈希的數據類型。具體以下代碼示例:

    s = frozenset(["趙本山", "劉能", "皮長山", "長貴"])
    dic = {s:'123'} # 能夠正常使用了
    print(dic) # 結果爲:{frozenset({'長貴', '劉能', '皮長山', '趙本山'}): '123'}

  這個不是很經常使用,瞭解一下就能夠了。

3、深淺拷貝

3.1 分析以下代碼的運行結果:

複製代碼
    lst1 = ["金毛獅王", "紫衫龍王", "白眉鷹王", "青翼蝠王"]
    lst2 = lst1
    print(lst1 is lst2)  # 結果爲:True,lst1和lst2指向同一個列表
    lst1.append("楊逍")
    print(lst1)  #結果爲:['金毛獅王', '紫衫龍王', '白眉鷹王', '青翼蝠王']
    print(lst2)   #結果爲:['金毛獅王', '紫衫龍王', '白眉鷹王', '青翼蝠王']

    dic1 = {"id": 123, "name": "謝遜"}
    dic2 = dic1
    print(dic1 is dic2)  #結果爲:True,dic1和dic2指向同一個字典
    dic1['name'] = "範瑤"
    print(dic1)   #結果爲:{'id': 123, 'name': '範瑤'}
    print(dic2)   #結果爲:{'id': 123, 'name': '範瑤'}
複製代碼

  對於list,dict,set來講,直接賦值,實際上是把內存地址交給變量,並非複製一分內容,因此lst1的內存指向和lst2是同樣的,lst1改變了,lst2也發生了改變。

3.2 淺拷貝:淺拷貝只是拷貝第一層,第二層的內容不會拷貝,因此被稱爲淺拷貝。具體示例以下:

複製代碼
    lst1 = ["何炅", "杜海濤","周渝民"]
    lst2 = lst1.copy() #或者能夠用lst2 = lst1[:],列表切片產生新列表
    lst1.append("李嘉誠")
    print(lst1)  #結果爲:['何炅', '杜海濤', '周渝民', '李嘉誠']
    print(lst2)   #結果爲:['何炅', '杜海濤', '周渝民']
    print(id(lst1) is id(lst2))  #False
    # 結果:兩個lst徹底不⼀樣. 內存地址和內容也不同. 發現實現了內存的拷貝
    lst1 = ["何炅", "杜海濤","周渝民", ["麻花藤", "馬芸", "周筆暢"]]
    lst2 = lst1.copy()
    lst1[3].append("無敵是多磨寂寞")
    print(lst1)  #結果爲:['何炅', '杜海濤', '周渝民', ['麻花藤', '馬芸', '周筆暢', '無敵是多磨寂寞']]
    print(lst2)   #結果爲:['何炅', '杜海濤', '周渝民', ['麻花藤', '馬芸', '周筆暢', '無敵是多磨寂寞']]
    print(id(lst1[3]) , id(lst2[3]))   #40938504 40938504  
    print(id(lst1[3]) is id(lst2[3]))  # False 此處不明白爲何返回False(可能還比較了父級內存地址,而父級也就是lst1和lst2的內存地址是不同的)
複製代碼

3.3 深拷貝:深拷貝是把元素內部的元素徹底進行拷貝複製,不會產生一個改變另外一個跟着改變的問題。以下:

複製代碼
    import copy   # 引入模塊
    lst1 = ["何炅", "杜海濤","周渝民", ["麻花藤", "馬芸", "周筆暢"]]
    lst2 = copy.deepcopy(lst1)
    lst1[3].append("無敵是多磨寂寞")
    print(lst1)  
    #結果爲:['何炅', '杜海濤', '周渝民', ['麻花藤', '馬芸', '周筆暢', '無敵是多磨寂寞']]
    print(lst2)  
    #結果爲:['何炅', '杜海濤', '周渝民', ['麻花藤', '馬芸', '周筆暢']]
    print(id(lst1[3]),id(lst2[3]))  # 43643784 43645384,內存地址不同
複製代碼
相關文章
相關標籤/搜索