字典是一種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']
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]:
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]:
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]:
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]:
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]:
實現過程:函數
i = hash(key) % slots #slots 槽位數
重複的槽位, 咱們稱之爲 hash衝突ui
經過1.拉鍊法;2.開地址法解決this
字典攻擊:黑客經過精心設計 key的hash值,讓全部的值 所有落在一個slot 上。 Redis/MEMCACHEDspa
拉鍊法的實現:設計
# 列表 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]], [], [], [], [], [], [], [], [], [], [], [], []]
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]: