深入python的set和dict


一. collections中的abc

  

和list(Sequence)相似,都繼承於Collection,添加了一些方法

 


二. dict的常見用法

  (setdefault,defaultdict,__missing__方法)

  1.copy():   

   

from collections.abc import MutableMapping
a = {'LYQ1':{'SWPU':'軟件工程'},
     'LYQ2':{'SWPU2':'軟件工程2'}}
#這是淺拷貝,指向的是同一值,修改一個,另一個也會修改
 b=a.copy()
 b['LYQ1']['SWPU']='我是淺拷貝'
 print(b)
 print(a)

 

 

注:copy方法是淺拷貝:深拷貝父對象(一級目錄),子對象(二級目錄)不拷貝,還是引用

 

 

a = {'LYQ1':{'SWPU':'軟件工程'},
     'LYQ2':{'SWPU2':'軟件工程2'}}
import copy
#深拷貝,指向不同的對象
deep_b=copy.deepcopy(a)
deep_b['LYQ1']['SWPU']='我是深拷貝'
print(deep_b)
print(a)

 

   2.fromkeys():

#把一個可迭代對象轉換為dict,{'SWPU':'軟件工程'}為默認值
my_list=['Stu1','Stu2']
my_dict=dict.fromkeys(my_list,{'SWPU':'軟件工程'})
print(my_dict)

 

  3.get():為了預防keyerror

  4.items():循環,返回key,value

  5.setdefault():將值設置進去,並獲取該值返回

my_list=['Stu1','Stu2']
my_dict=dict.fromkeys(my_list,{'SWPU':'軟件工程'})
#將值設置進去,並獲取該值返回
re_value=my_dict.setdefault('Stu3','HAHA')
print(re_value)
print(my_dict)

  6.update():添加鍵值對或更新鍵值對:

a = {'LYQ1':{'SWPU':'軟件工程'},
     'LYQ2':{'SWPU2':'軟件工程2'}}
#添加新鍵值對(即合並兩個字典)
a.update({'LYQ3':'NEW'})
#第二種方式
a.update(LYQ4='NEW2',LYQ5='NEW3')
#第三種方式,list里面放tuple,tuple里面放tuple等(可迭代就行)
a.update([('LYQ6','NEW6')])
print(a)
#修改鍵值對
a.update({'LYQ1':'我修改了'})
print(a)

 

 

三. dict的子類

  defaultdict
  Counter
  不要去繼承內置類型, 有可能會失敗比如update方法

# 不建議繼承list和dict
class MyDict(dict):
    def __setitem__(self, key, value):
        super().__setitem__(key, value * 2)
#未調用自己寫的方法
my_dict=MyDict(one=1)
print(my_dict)
my_dict['one']=1
#調用自己寫的方法
print(my_dict)
#如果要繼承,就繼承Userdict
from collections import UserDict
class MyDict2(UserDict):
    def __setitem__(self, key, value):
        super().__setitem__(key, value * 2)
my_dict2=MyDict2(one=1)
print(my_dict2)

 

 

  

Userdict源碼:當取不到某個key時,就會調用__missing__方法(如果有__missing__)獲取默認值

  2.defaultdict:

from collections import defaultdict
#可以時dict,int,str,list,tuple等等
my_dict=defaultdict(dict)
#找不到key,實際調用的時__missing__方法
print(my_dict['haha'])

 

 

四. set和frozenset

  1.set:無序,不重復(性能很高)

a=set('abcdee')
a.add('f')
print(a)
another_set=set('defgh')
#添加數據
#a.update(another_set)
#print(a)
#集合的差集
re_set=a.difference(another_set)
#減法實現於__ior__魔法函數
re_set2=a-another_set
#集合的交集&
re_set3=a&another_set
#集合的並集|
re_set4=a|another_set
print(re_set)
print(re_set2)
print(re_set3)
print(re_set4)
#也可以用if in判斷(實現於__contains__魔法函數)
if 'a' in re_set:
    print('I am a set')

 

 

  2.frozenset:不可變的集合(無序,不重復)

 

五.dict和set實現原理

  1.測試結論:

    1.1dict查找的性能遠遠高於list;

    1.2在list中隨着list數據的增大,查找時間會增大;

    1.3在dict中查找元素不會隨着dict的增大而增大

  2.dict基於hash表(set也是,所占空間比dict小):

    注:1.dict的key或者set的值,都必須是可以hash的(不可變對象都是可以hash的,如str,frozenset,tuple,自己實現的類【實現__hash__魔法函數】);

      2.dict內存花銷大,但是查詢速度快,自定義的對象或者python內置的對象都是用dict包裝的;

      3.dict的存儲順序與元素添加順序有關;

      4.添加數據有可能改變已有數據的順序;

      5.取數據的時間復雜度為O(1)

   通過hash函數計算key(有很多的算法),這里是通過hash函數計算然后與7進行與運算,在計算過程中有可能沖突,得到同樣的位置(有很多的解決方法),如’abc‘取一位'c'加一位隨機數,如果沖突,就向前多取一位在計算...(還有先聲明一個很小的內存空間,可能存在一些空白,計算空白,如果小於1/3,然后聲明一個更大的空間,拷貝過去,減少沖突)

查找數據,先計算hash值定位,查找是否為空,為空就拋出錯誤,如果不為空查看是否相等,如果被其他占領就不相等,然后又進行沖突解決





免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM