字典

字典

字典是一種KEW-VALUE結構,簡稱K_V對。python

In [1]: d = {}

In [2]: type(d)
Out[2]: dict

In [3]: d = {'a' : 1, 'b' : 2}

In [4]: d
Out[4]: {'a': 1, 'b': 2}

In [5]: type(d)
Out[5]: dict

In [6]: d = dict({'a': 1, 'b': 2})

In [7]: d
Out[7]: {'a': 1, 'b': 2}


In [9]: d = dict.fromkeys(range(5))    # 傳入的可迭代對象元素是key,值爲None

In [10]: d
Out[10]: {0: None, 1: None, 2: None, 3: None, 4: None}

In [11]: d = dict.fromkeys(range(5), 'abc')

In [12]: d
Out[12]: {0: 'abc', 1: 'abc', 2: 'abc', 3: 'abc', 4: 'abc'}

In [13]: d = {'a': 1}

In [14]: d
Out[14]: {'a': 1}

In [15]: d['a']
Out[15]: 1

In [16]: d['b']

1、字典的操做

一、增長

In [18]: d = {'a': 1, 'b': 2}

In [19]: d
Out[19]: {'a': 1, 'b': 2}

In [20]: d['c'] = 3    # 直接使用key 做爲下標,對某個不存在的下標賦值,會增長一個 k-v 對

In [21]: d
Out[21]: {'a': 1, 'b': 2, 'c': 3}


In [23]: d.update([('d', 4), ('p', 0)])     # 傳入的是一個可迭代對象

In [24]: d
Out[24]: {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'p': 0}

In [25]: d.update({'r': 1})

In [26]: d
Out[26]: {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'p': 0, 'r': 1}

In [27]: d.update({'d': 5})       # 若存在就會修改字典

In [28]: d
Out[28]: {'a': 1, 'b': 2, 'c': 3, 'd': 5, 'p': 0, 'r': 1}

In [29]:

二、修改

In [31]: d
Out[31]: {'a': 11, 'b': 2, 'c': 3, 'd': 5, 'p': 0, 'r': 1}

In [32]: d.update({'a': 111})

In [33]: d
Out[33]: {'a': 111, 'b': 2, 'c': 3, 'd': 5, 'p': 0, 'r': 1}

In [34]:

三、刪除

    1) d.pop()

In [34]: help(d.pop)

Help on built-in function pop:

pop(...) method of builtins.dict instance
    D.pop(k[,d]) -> v, remove specified key and return the corresponding value.
    If key is not found, d is returned if given, otherwise KeyError is raised

~
(END)
In [35]: d
Out[35]: {'a': 111, 'b': 2, 'c': 3, 'd': 5, 'p': 0, 'r': 1}

In [36]: d.pop('a')      # 刪除一個 key-value 對, 而且返回其value值
Out[36]: 111

In [37]: d
Out[37]: {'b': 2, 'c': 3, 'd': 5, 'p': 0, 'r': 1}

In [38]: d.pop('a')
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-38-858744f94692> in <module>()
----> 1 d.pop('a')

KeyError: 'a'

In [39]: d.pop('a', 'default')      # 若key 不存在,則返回default 的值
Out[39]: 'default'

In [40]: d.pop('b', 'default')      # 若值存在,default 不會取到 
Out[40]: 2

In [41]: d.pop('b', 'default')
Out[41]: 'default'

In [42]:

    2) d.popitem()

In [42]: help(d.popitem)
Help on built-in function popitem:

popitem(...) method of builtins.dict instance
    D.popitem() -> (k, v), remove and return some (key, value) pair as a
    2-tuple; but raise KeyError if D is empty.
~
[END]
In [43]: d
Out[43]: {'c': 3, 'd': 5, 'p': 0, 'r': 1}

In [44]: d.popitem() # 隨機刪除一對 k-v對,而且返回這對 k-v對;若k-v 對 不存在,則拋出KeyError 
Out[44]: ('r', 1)

In [45]: d
Out[45]: {'c': 3, 'd': 5, 'p': 0}

In [46]: d.clear()

In [47]: d
Out[47]: {}

In [48]: d.popitem()
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-48-83c64cff336b> in <module>()
----> 1 d.popitem()

KeyError: 'popitem(): dictionary is empty'

In [49]:

    3)del d['key']

In [50]: d = {'a': 111, 'b': 2, 'c': 3, 'd': 5, 'p': 0, 'r': 1}

In [51]: d
Out[51]: {'a': 111, 'b': 2, 'c': 3, 'd': 5, 'p': 0, 'r': 1}

In [52]: del d['a']

In [53]: d
Out[53]: {'b': 2, 'c': 3, 'd': 5, 'p': 0, 'r': 1}

In [54]: del d['a']  # del 關鍵字,刪除一個引用,儘可能不用del,能用pop 就用pop
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-54-52407f9056e8> in <module>()
----> 1 del d['a']

KeyError: 'a'

In [55]:

若須要修改字典中的key,只能經過 先刪再增長json

四、訪問

In [5]: d = {'b': 2, 'c': 3, 'd': 5, 'p': 0, 'r': 1}

In [6]: d
Out[6]: {'b': 2, 'c': 3, 'd': 5, 'p': 0, 'r': 1}

In [7]: d['d']
Out[7]: 5

In [8]: d['q']       # 當 key 不存在時,會拋出 KeyError
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-8-240eb3314f25> in <module>()
----> 1 d['q']

KeyError: 'q'

In [9]: 

In [9]: 

In [9]: d.get('q') # get 方法 當key 不存在時,返回None,事實上,返回的是一個默認值,只不過這個默認值 默認爲None  

In [10]: d.get('q', '123456789')
Out[10]: '123456789'

In [11]: j = {'city': 'shanghai', 'uname': 'miracle', 'uage': 18}  # request.json

In [12]: j.get('addr', '楊浦')
Out[12]: '楊浦'
In [17]: d.clear()

In [18]: d
Out[18]: {}

In [19]: d.setdefault('c', 'default')  # 實際上是 調用了 get方法,而後賦值
Out[19]: 'default'

In [20]: d
Out[20]: {'c': 'default'}

In [21]: d.setdefault('c', 'cc')       # setdefault 方法,若存在,則不更新,若不存在則更新
Out[21]: 'default'

In [22]: d
Out[22]: {'c': 'default'}

In [23]: help(d.setdefault)


Help on built-in function setdefault:

setdefault(...) method of builtins.dict instance
    D.setdefault(k[,d]) -> D.get(k,d), also set D[k]=d if k not in D
~
(END)
In [24]: def _setdefault(d, k, default):
    ...:     value = d.get(k, default)
    ...:     d[k] = value
    ...:     return value
    ...: 

In [25]: _setdefault(d, 'asdas', '3333')
Out[25]: '3333'

In [26]: d
Out[26]: {'asdas': '3333', 'c': 'default'}

In [27]:

字典訪問單個元素,要麼用下標;要麼用get。推薦使用getbash

五、字典的遍歷

In [29]: for x in d:
    ...:     print(x, d[x])
    ...:     
c default
asdas 3333

In [30]: d.values()   # values 方法返回一個可迭代對象,元素是字典裏的全部value
Out[30]: dict_values(['default', '3333'])

In [31]: for v in d.values():
    ...:     print(v)
    ...:     
default
3333

 

In [32]: d.items()   # 獲取 全部鍵值對
Out[32]: dict_items([('c', 'default'), ('asdas', '3333')])

In [33]: for x in d.items():  # 解構用法
    ...:     print(x)
    ...:     
('c', 'default')
('asdas', '3333')

In [34]: for _, v in d.items():
    ...:     print(_, v)
    ...:     
c default
asdas 3333

In [35]:

 

In [35]: d.keys()    # 返回全部的 key,做爲一個list
Out[35]: dict_keys(['c', 'asdas'])

In [36]: type(d.keys())
Out[36]: dict_keys

In [37]:

六、字典的限制

  • 字典的key  不能重複
  • 字典的key  須要可hash
In [4]: d = {}

In [5]: d[[1, 2, 3]] = 3
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-5-a9743e739b16> in <module>()
----> 1 d[[1, 2, 3]] = 3

TypeError: unhashable type: 'list'

In [6]: d[(1, 2, 3)] = 3

In [7]: d[(1, 2, 3)]
Out[7]: 3

In [8]: d[0] = [1, 2, 3]         # int 類型 能夠做爲key, 但不推薦

In [9]: d[0]
Out[9]: [1, 2, 3]

In [10]:

七、字典的變體

默認字典app

In [10]: from collections import defaultdict

In [11]: d1 = {}

In [12]: d2 = defaultdict()

In [13]: d1
Out[13]: {}

In [14]: d2
Out[14]: defaultdict(None, {})

In [15]: help(defaultdict)
Help on class defaultdict in module collections:

class defaultdict(builtins.dict)
 |  defaultdict(default_factory[, ...]) --> dict with default factory
 |  
 |  The default factory is called without arguments to produce
 |  a new value when a key is not present, in __getitem__ only.
 |  A defaultdict compares equal to a dict with the same items.
 |  All remaining arguments are treated the same as if they were
 |  passed to the dict constructor, including keyword arguments.
 |  
 |  Method resolution order:
 |      defaultdict
 |      builtins.dict
 |      builtins.object
 |  
 |  Methods defined here:
 |  
 |  __copy__(...)
 |      D.copy() -> a shallow copy of D.
 |  
 |  __getattribute__(self, name, /)
 |      Return getattr(self, name).
 |  
 |  __init__(self, /, *args, **kwargs)
 |      Initialize self.  See help(type(self)) for accurate signature.
 |  
 |  __missing__(...)
 |      __missing__(key) # Called by __getitem__ for missing key; pseudo-code:
 |      if self.default_factory is None: raise KeyError((key,))
 |      self[key] = value = self.default_factory()
 |      return value
 |  
 |  __reduce__(...)
 |      Return state information for pickling.
 |  
 |  __repr__(self, /)
 |      Return repr(self).
 |  
 |  copy(...)
 |      D.copy() -> a shallow copy of D.
 |  
 |  ----------------------------------------------------------------------
 |  Data descriptors defined here:
 |  
 |  default_factory
 |      Factory for default value called by __missing__().
 |  
 |  ----------------------------------------------------------------------
 |  Methods inherited from builtins.dict:
 |  
 |  __contains__(self, key, /)
 |      True if D has a key k, else False.
 |  
 |  __delitem__(self, key, /)
 |      Delete self[key].
 |  
 |  __eq__(self, value, /)
 |      Return self==value.
 |  
 |  __ge__(self, value, /)
 |      Return self>=value.
 |  
 |  __getitem__(...)
 |      x.__getitem__(y) <==> x[y]
 |  
 |  __gt__(self, value, /)
 |      Return self>value.
 |  
 |  __iter__(self, /)
 |      Implement iter(self).
 |  
 |  __le__(self, value, /)
 |      Return self<=value.
 |  
 |  __len__(self, /)
 |      Return len(self).
 |  
 |  __lt__(self, value, /)
 |      Return self<value.
 |  
 |  __ne__(self, value, /)
 |      Return self!=value.
 |  
 |  __new__(*args, **kwargs) from builtins.type
 |      Create and return a new object.  See help(type) for accurate signature.
 |  
 |  __setitem__(self, key, value, /)
 |      Set self[key] to value.
 |  
 |  __sizeof__(...)
 |      D.__sizeof__() -> size of D in memory, in bytes
 |  
 |  clear(...)
 |      D.clear() -> None.  Remove all items from D.
 |  
 |  fromkeys(iterable, value=None, /) from builtins.type
 |      Returns a new dict with keys from iterable and values equal to value.
 |  
 |  get(...)
 |      D.get(k[,d]) -> D[k] if k in D, else d.  d defaults to None.
 |  
 |  items(...)
 |      D.items() -> a set-like object providing a view on D's items
 |  
 |  keys(...)
 |      D.keys() -> a set-like object providing a view on D's keys
 |  
 |  pop(...)
 |      D.pop(k[,d]) -> v, remove specified key and return the corresponding value.
 |      If key is not found, d is returned if given, otherwise KeyError is raised
 |  
 |  popitem(...)
 |      D.popitem() -> (k, v), remove and return some (key, value) pair as a
 |      2-tuple; but raise KeyError if D is empty.
 |  
 |  setdefault(...)
 |      D.setdefault(k[,d]) -> D.get(k,d), also set D[k]=d if k not in D
 |  
 |  update(...)
 |      D.update([E, ]**F) -> None.  Update D from dict/iterable E and F.
 |      If E is present and has a .keys() method, then does:  for k in E: D[k] = E[k]
 |      If E is present and lacks a .keys() method, then does:  for k, v in E: D[k] = v
 |      In either case, this is followed by: for k in F:  D[k] = F[k]
 |  
 |  values(...)
 |      D.values() -> an object providing a view on D's values
 |  
 |  ----------------------------------------------------------------------
 |  Data and other attributes inherited from builtins.dict:
 |  
 |  __hash__ = None
~
(END)
In [16]: lst = [1, 2]

In [17]: d = defaultdict(list, {})    # 工廠函數,定義一個字典,當key 不存在時,返回一個空list 做爲默認value


In [18]: d
Out[18]: defaultdict(list, {})        

In [19]: d['a'] = 1

In [20]: d
Out[20]: defaultdict(list, {'a': 1})

In [22]: d['b'] = [1, 2]

In [23]: d
Out[23]: defaultdict(list, {'a': 1, 'b': [1, 2]})

In [24]: for k, v in d.items():
    ...:     print(k, v)
    ...:     
a 1
b [1, 2]

In [25]:
In [26]: d = defaultdict(str)

In [27]: d['a']
Out[27]: ''

In [28]: d = defaultdict(int)

In [29]: d
Out[29]: defaultdict(int, {})

In [30]: d['a']      # 0 表明的是 bool值的False
Out[30]: 0

In [31]: bool(1)
Out[31]: True

In [32]: bool(0)
Out[32]: False

In [33]: if not d['a']:
    ...:     print('0')
    ...:     
0
In [34]: d = {}

In [35]: for k in range(10):
    ...:     for v in range(10):
    ...:         if k not in d.keys():
    ...:             d[k] = []
    ...:         d[k].append(v)
    ...:             

In [36]: d
Out[36]: 
{0: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
 1: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
 2: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
 3: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
 4: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
 5: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
 6: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
 7: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
 8: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
 9: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]}
In [37]: d = defaultdict(list)

In [38]: for k in range(10):
    ...:     for v in range(10):
    ...:         d[k].append(v)
    ...:         

In [39]: d
Out[39]: 
defaultdict(list,
            {0: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
             1: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
             2: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
             3: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
             4: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
             5: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
             6: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
             7: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
             8: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
             9: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]})

In [40]:
# 高階函數
In [56]: def f():
    ...:     print('f is called')
    ...:     return 'a'
    ...: 

In [57]: d = defaultdict(f)

In [58]: d['xxx']
f is called
Out[58]: 'a'

In [59]:

八、有序字典

In [59]: d = {}

In [60]: d['jim'] = (1, 35)

In [61]: d['Leo'] = (2, 37)

In [62]: d['Bob'] = (3, 40)

In [63]: d
Out[63]: {'Bob': (3, 40), 'Leo': (2, 37), 'jim': (1, 35)}

In [64]: from collections import OrderedDict

In [66]: d = OrderedDict()

In [67]: d['jim'] = (1, 35)

In [68]: d['Leo'] = (2, 37)

In [69]: d['Bob'] = (3, 40)

In [70]: d
Out[70]: OrderedDict([('jim', (1, 35)), ('Leo', (2, 37)), ('Bob', (3, 40))])

In [71]:

2、字典的實現

  • 拉鍊法
  • 開地址法

實現過程:函數

  • 傳入一個key
  • 就能經過這個key (索引)獲得這個值,那麼複雜度就是O(1)

 

  • 初始化一個列表,全部位置都是None
  • 全部的key 都是可hash的, 咱們對裏面的值求 hash
  • 假設這個列表有32個槽位, 就是32位, 比32位大怎麼辦? 求模就能夠了
  • 那麼這個就能夠放入列表中了
i = hash(key) % slots      #slots  槽位數

重複的槽位, 咱們稱之爲 hash衝突ui

經過1.拉鍊法;2.開地址法解決this

 

一、拉鍊法

字典攻擊:黑客經過精心設計 key的hash值,讓全部的值 所有落在一個slot 上。 Redis/MEMCACHEDspa

拉鍊法的實現:設計

  1. 函數方法
    # 列表
    slots = []
    # 槽位數
    slots_num = 32
    
    for _ in range(slots_num):
        slots.append([])
    
    def put(slots, key, value):
        i = hash(key) % slots_num
        
        
        for p, (k, v) in enumerate(slots[i]):
            if k == key:
                slots[i][p] = (key, value)
                break
        else:
            slots[i].append((key, value))
            return
    
            
        
    def get(slots, key):
        i = hash(key) % slots_num
        for k, v in slots[i]:
            if k == key:
                return v
        raise KeyError(k)
    In [12]: put(slots, 'r', 2)
    
    In [13]: put(slots, 'd', 2)
    
    In [14]: slots
    Out[14]: 
    [[],
     [],
     [],
     [],
     [],
     [],
     [],
     [],
     [],
     [],
     [],
     [],
     [('d', 2)],
     [],
     [],
     [],
     [],
     [],
     [],
     [('r', 2)],
     [],
     [],
     [],
     [],
     [],
     [],
     [],
     [],
     [],
     [],
     [],
     []]
    
    In [15]: get(slots, 'r')
    Out[15]: 2
    
    In [16]: put(slots, 'r', 3)
    
    In [17]: slots
    Out[17]: 
    [[],
     [],
     [],
     [],
     [],
     [],
     [],
     [],
     [],
     [],
     [],
     [],
     [('d', 2)],
     [],
     [],
     [],
     [],
     [],
     [],
     [['r', 3]],
     [],
     [],
     [],
     [],
     [],
     [],
     [],
     [],
     [],
     [],
     [],
     []]

     

  2. 類方法
class _Dict:
    def __init__(self, num):
        self.__slots__ = []
        self.num = num
        
        for _ in range(self.num):
            self.__slots__.append([])

    def put(self, key, value):
        i = hash(key) % self.num

        for p, (k, v) in enumerate(self.__slots__[i]):
            if k == key:
                self.__slots__[i][p] = (key, value)
                break
        else:
            self.__slots__[i].append((key, value))
            return



    def get(self, key):
        i = hash(key) % self.num
        for k, v in self.__slots__[i]:
            if k == key:
                return v
        raise KeyError(k)
        
    def keys(self):
        ret = []
        for slot in self.__slots__:
            for k, _ in slot:
                ret.append(k)
        return ret

 

In [37]: d = _Dict(32)

In [38]: d.put('r', 2)

In [39]: d.put('d', 3)

In [40]: d.get('r')
Out[40]: 2

In [41]: d.get('d')
Out[41]: 3

In [42]: d.put('r', 4)

In [43]: d.get('r')
Out[43]: 4

In [44]: d.keys()
Out[44]: ['d', 'r']


In [46]: d.__slots__
Out[46]: 
[[],
 [],
 [],
 [],
 [],
 [],
 [],
 [],
 [],
 [],
 [],
 [],
 [('d', 3)],
 [],
 [],
 [],
 [],
 [],
 [],
 [('r', 4)],
 [],
 [],
 [],
 [],
 [],
 [],
 [],
 [],
 [],
 [],
 [],
 []]

In [47]:

二、開地址法

相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息