Python使用collections模塊實(shí)現(xiàn)擴(kuò)展數(shù)據(jù)類
楔子
Python 標(biāo)準(zhǔn)庫提供了一個(gè) collections 模塊,里面提供了很多的數(shù)據(jù)類,在工作中使用這些類能夠簡化我們的開發(fā)。
下面就來看看這個(gè)模塊能夠幫助我們做哪些事情?
搜索多個(gè)字典
假設(shè)當(dāng)前有 3 個(gè)字典:dct1、dct2、dct3,現(xiàn)在要通過 key 查找對應(yīng)的 value。如果 key 在 dct1 里面存在,那么直接返回,否則從 dct2 里面找。dct2 里面如果不存在,那么從 dct3 里面找。
這個(gè)需求該怎么實(shí)現(xiàn)呢?
dct1?=?{"a":?1,?"b":?2,?"c":?3}
dct2?=?{"d":?4,?"e":?5,?"f":?6}
dct3?=?{"e":?7,?"f":?8,?"g":?9}
def?get_value_by_key(key):
????if?key?in?dct1:
????????return?dct1[key]
????elif?key?in?dct2:
????????return?dct2[key]
????elif?key?in?dct3:
????????return?dct3[key]
????else:
????????raise?KeyError
print(get_value_by_key("b"))??#?2
print(get_value_by_key("d"))??#?4
print(get_value_by_key("f"))??#?6實(shí)現(xiàn)起來非常簡單,但通過 ChainMap 對象可以更方便地做到這一點(diǎn)。
from?collections?import?ChainMap
dct1?=?{"a":?1,?"b":?2,?"c":?3}
dct2?=?{"b":?4,?"c":?5,?"d":?6}
#?將多個(gè)字典傳進(jìn)去,
dct?=?ChainMap(dct1,?dct2)
#?如果多個(gè)字典存在相同的?key,那么返回第一次出現(xiàn)的?key?對應(yīng)的?value
print(dct["b"],?dct["d"])
"""
2?6
"""
#?字典的?API?都可以使用
print(dct.items())
"""
ItemsView(ChainMap({'a':?1,?'b':?2,?'c':?3},?{'b':?4,?'c':?5,?'d':?6}))
"""
#?也可以使用?get,如果?key?在所有的字典中都不存在
#?則返回默認(rèn)值
print(dct.get("k",?333))
"""
333
"""
#?ChainMap?對象有一個(gè)?maps?屬性,存儲(chǔ)了要搜索的映射列表
#?這個(gè)列表是可變的,所以可以直接增加新映射,或者改變元素的順序以控制查找和更新行為。
print(dct.maps)
"""
[{'a':?1,?'b':?2,?'c':?3},?{'b':?4,?'c':?5,?'d':?6}]
"""
#?dct.maps?保存了原始的字典,修改?dct.maps?會(huì)影響原字典
print(dct1)
"""
{'a':?1,?'b':?2,?'c':?3}
"""
dct.maps[0]["a"]?=?11111111
print(dct1)
"""
{'a':?11111111,?'b':?2,?'c':?3}
"""
#?同理修改原字典,也會(huì)影響?dct.maps以上就是 ChainMap 對象的用法,當(dāng)你需要從多個(gè)字典中進(jìn)行搜索的話,它會(huì)很有用。
統(tǒng)計(jì)可散列的對象
我們經(jīng)常會(huì)遇到數(shù)量統(tǒng)計(jì)相關(guān)的問題,比如有一個(gè)序列,計(jì)算里面每個(gè)元素出現(xiàn)了多少次。一般情況下,我們會(huì)這么做。
words?=?["hello",?"world",
?????????"hello",?"beautiful",?"world",
?????????"hello",?"cruel",?"world"]
counter?=?{}
for?word?in?words:
????if?word?in?counter:
????????counter[word]?+=?1
????else:
????????counter[word]?=?1
print(counter)
"""
{'hello':?3,?'world':?3,?'beautiful':?1,?'cruel':?1}
"""實(shí)現(xiàn)方法沒有任何問題,但通過 Counter 會(huì)更方便,并且還提供了更多功能。
from?collections?import?Counter
words?=?["hello",?"world",
?????????"hello",?"beautiful",?"world",
?????????"hello",?"cruel",?"world"]
#?將序列傳進(jìn)去即可
counter?=?Counter(words)
print(counter)
"""
Counter({'hello':?3,?'world':?3,?'beautiful':?1,?'cruel':?1})
"""
#?Counter?繼承?dict,所以字典的?API?它也是都支持的
counter?=?Counter(hello=3,?world=3,?beautiful=1,?cruel=1)
print(counter)
"""
Counter({'hello':?3,?'world':?3,?'beautiful':?1,?'cruel':?1})
"""Counter 對象還支持動(dòng)態(tài)更新操作,舉個(gè)例子:
from?collections?import?Counter
#?Counter?需要接收一個(gè)可迭代對象,然后會(huì)遍歷它
#?所以結(jié)果就是?a?出現(xiàn)了三次,b?出現(xiàn)了兩次,c?出現(xiàn)了一次
counter?=?Counter("aaabbc")
print(counter)
"""
Counter({'a':?3,?'b':?2,?'c':?1})
"""
#?也可以動(dòng)態(tài)更新,比如又來了一個(gè)序列
#?需要和當(dāng)前的?counter?組合起來進(jìn)行統(tǒng)計(jì)
counter.update("bcd")
print(counter)
"""
Counter({'a':?3,?'b':?3,?'c':?2,?'d':?1})
"""
#?可以看到?b?和?c?的值都增加了?1,并且出現(xiàn)了?d
#?需要注意的是:update 方法同樣接收一個(gè)可迭代對象,然后進(jìn)行遍歷
#?如果我希望添加一個(gè)?key?叫?"bcd"?的話,那么要這么做
counter.update(["bcd"])
print(counter)
"""
Counter({'a':?3,?'b':?3,?'c':?2,?'d':?1,?'bcd':?1})
"""
#?訪問計(jì)數(shù),Counter?對象可以像字典一樣訪問
print(counter["a"])??
"""
3
"""
#?如果訪問一個(gè)不存在的?key,不會(huì)引發(fā)?KeyError
#?而是會(huì)返回?0,表示對象中沒有這個(gè)?key
print(counter["mmp"])??
"""
0
"""
#?還可以計(jì)算出現(xiàn)最多的元素,這是用的最頻繁的一個(gè)功能
#?統(tǒng)計(jì)?string?中前三個(gè)出現(xiàn)次數(shù)最多的元素
string?=?"sasaxzsdsadfscxzcasdscxzdfscxsasadszczxczxcsds"
counter?=?Counter(string)
print(counter)
"""
Counter({'s':?13,?'c':?7,?'a':?6,?'x':?6,?'z':?6,?'d':?6,?'f':?2})
"""
print(counter.most_common(3))
"""
[('s',?13),?('c',?7),?('a',?6)]
"""Counter 對象還有一個(gè)強(qiáng)大的功能,就是它支持算數(shù)操作以及位運(yùn)算。
from?collections?import?Counter
counter1?=?Counter("aabbccc")
counter2?=?Counter("bbbccdd")
print(counter1)??
print(counter2)??
"""
Counter({'a':?2,?'b':?2,?'c':?3})
Counter({'b':?3,?'c':?2,?'d':?2})
"""
#?如果?counter1?的元素出現(xiàn)在了?counter2?中
#?就把該元素減去,記住:減的是次數(shù)
print(counter1?-?counter2)??
"""
Counter({'a':?2,?'c':?1})
"""
#?a?在?counter1?中出現(xiàn)了?2?次,在?counter2?中沒有出現(xiàn),所以是?a:?2
#?b?在?counter1?中出現(xiàn)了?2?次,在?counter2?中出現(xiàn)?3?次,所以一減就沒有了
#?c?在?counter1?中出現(xiàn)了?3?次,在?counter2?中出現(xiàn)?2?次,所以相減還剩下一次
#?至于?counter1?中沒有的元素就不用管了
#?相加就很好理解了
print(counter1?+?counter2)?
"""
Counter({'b':?5,?'c':?5,?'a':?2,?'d':?2})?
"""
#?相交的話,查找公共的元素,并且取次數(shù)出現(xiàn)較小的那個(gè)
print(counter1?&?counter2)??
"""
Counter({'b':?2,?'c':?2})
"""
#?并集的話,取較大的,記住不是相加
#?所以?b?和?c?出現(xiàn)的次數(shù)不會(huì)增加,只是取較大的那個(gè)
print(counter1?|?counter2)??
"""
Counter({'b':?3,?'c':?3,?'a':?2,?'d':?2})
"""以上就是 Counter 的用法,更多的還是統(tǒng)計(jì)次數(shù),求 topK。
缺少的鍵返回默認(rèn)值
很明顯,這是針對于字典的。首先字典也支持這種操作,通過 setdefault 和 get 兩個(gè)方法,可以用來獲取 key 對應(yīng)的 value,并且還能在 key 不存在的時(shí)候給一個(gè)默認(rèn)值。
如果 key 存在,兩者會(huì)獲取 key 對應(yīng)的 value;但如果 key 不存在,setdefault 會(huì)先將 key 和指定的默認(rèn)值設(shè)置進(jìn)去,然后再將設(shè)置的值返回,而 get 則只會(huì)返回默認(rèn)值,不會(huì)進(jìn)行設(shè)置。
d?=?{"a":?1}
#?如果?key?存在,直接返回?value
print(d.get("a",?0))??#?1
print(d.setdefault("a",?0))??#?1
#?原字典不受影響
print(d)??#?{"a":?1}
#?key?不存在,則返回指定的默認(rèn)值
print(d.get("b",?0))??#?0
#?原字典不受影響
print(d)??#?{"a":?1}
#?key?不存在的話,會(huì)將?key?和默認(rèn)值組成鍵值對,設(shè)置在字典中
print(d.setdefault("b",?0))??#?0
print(d)??#?{"a":?1,?"b":?0}指的一提的是,setdefault 是一個(gè)非常實(shí)用且簡潔的方法,但用的卻不多。我們舉一個(gè)例子:
data?=?[
????("banana",?15),?("banana",?17),?("banana",?22),
????("apple",?31),?("apple",?30),?("apple",?33),
????("orange",?45),?("orange",?47),?("orange",?44),
]
#?如果我希望將 data 轉(zhuǎn)成以下格式,該怎么辦呢?
"""
{'banana':?[15,?17,?22],?
?'apple':?[31,?30,?33],?
?'orange':?[45,?47,?44]}
"""
def?change_data1():
????result?=?{}
????for?product,?count?in?data:
????????if?product?not?in?result:
????????????result[product]?=?[count]
????????else:
????????????result[product].append(count)
????return?result
print(change_data1())
"""
{'banana':?[15,?17,?22],?
?'apple':?[31,?30,?33],?
?'orange':?[45,?47,?44]}
"""
#?結(jié)果沒問題,但如果用?setdefault?的話會(huì)更方便
def?change_data2():
????result?=?{}
????for?product,?count?in?data:
????????result.setdefault(product,?[]).append(count)
????return?result
print(change_data2())
"""
{'banana':?[15,?17,?22],?
?'apple':?[31,?30,?33],?
?'orange':?[45,?47,?44]}
"""但這個(gè)功能也可以通過 defaultdict 完成,該類要求調(diào)用者傳遞一個(gè)類型,當(dāng) key 不存在時(shí)會(huì)返回對應(yīng)類型的零值。
from?collections?import?defaultdict
d?=?defaultdict(int)
print(d)??#?defaultdict(<class?'int'>,?{})
print(d["a"])??#?0
print(d)??#?defaultdict(<class?'int'>,?{'a':?0})
d?=?defaultdict(tuple)
print(d)??#?defaultdict(<class?'tuple'>,?{})
print(d["a"])??#?()
print(d)??#?defaultdict(<class?'tuple'>,?{'a':?()})
#?之前的例子就可以這么做
data?=?[
????("banana",?15),?("banana",?17),?("banana",?22),
????("apple",?31),?("apple",?30),?("apple",?33),
????("orange",?45),?("orange",?47),?("orange",?44),
]
result?=?defaultdict(list)
for?product,?count?in?data:
????result[product].append(count)
#?defaultdict?繼承?dict,支持字典的?API
print(dict(result))
"""
{'banana':?[15,?17,?22],?
?'apple':?[31,?30,?33],?
?'orange':?[45,?47,?44]}
"""
#?整個(gè)過程就是,key?如果存在,那么獲取?value
#?key?不存在,那么將指定類型的零值作為?value(這里是空列表)
#?并且返回之前,會(huì)先將?key、value?添加到鍵值對中
#?再比如之前的詞頻統(tǒng)計(jì)
string?=?"aabbccdddddee"
counter?=?defaultdict(int)
for?c?in?string:
????counter[c]?+=?1
print(dict(counter))
"""
{'a':?2,?'b':?2,?'c':?2,?'d':?5,?'e':?2}
"""怎么樣,是不是很方便呢?在實(shí)例化 defaultdict 的時(shí)候,指定一個(gè)類型即可,獲取一個(gè)不存在的 key 的時(shí)候,會(huì)返回指定的類型的零值,并且還會(huì)將 key 和零值添加到字典中。
此外 defaultdict 還可以自定義返回值,只需要指定一個(gè)不需要參數(shù)的函數(shù)即可。
from?collections?import?defaultdict #?此時(shí)的默認(rèn)值就是?default d?=?defaultdict(lambda:?"default") print(d["aa"])??#?default #?此外還可以添加參數(shù),因?yàn)閱为?dú)指定了?aa,所以打印的時(shí)候以指定的為準(zhǔn) #?如果沒有指定,那么才會(huì)得到默認(rèn)值 d4?=?defaultdict(lambda:?"default",?aa="bar") print(d4["aa"])??#?bar print(d4["bb"])??#?default
那么估計(jì)會(huì)有人好奇,這是如何實(shí)現(xiàn)的呢?其實(shí)主要是實(shí)現(xiàn)了一個(gè)叫做 __missing__ 的魔法方法。字典在查找元素的時(shí)候,會(huì)調(diào)用 __getitem__,然后在找不到的時(shí)候會(huì)去調(diào)用 __missing__。但是注意:dict 這個(gè)類本身并沒有實(shí)現(xiàn) __missing__,所以我們需要繼承自 dict,然后在子類中實(shí)現(xiàn)。
class?MyDict(dict):
????def?__getitem__(self,?item):
????????#?執(zhí)行父類的?__getitem__?方法
????????#?如果?key?不存在,會(huì)去執(zhí)行?__missing__?方法
????????value?=?super().__getitem__(item)
????????#?所以這里的?value?就是?__missing__?方法的返回值
????????return?value
????def?__missing__(self,?key):
????????self[key]?=?"搞事情?(′ー`?)搞事情"
????????return?self[key]
d?=?MyDict([("a",?3),?("b",?4)])
print(d)??#?{'a':?3,?'b':?4}
print(d["mmm"])??#?搞事情?(′ー`?)搞事情
print(d)??#?{'a':?3,?'b':?4,?'mmm':?'搞事情?(′ー`?)搞事情'}都是一些基礎(chǔ)的內(nèi)容了,突然想到了,就提一遍。
雙端隊(duì)列
如果你需要維護(hù)一個(gè)序列,并根據(jù)需求動(dòng)態(tài)地往序列的尾部添加元素和彈出元素,那么你會(huì)選擇什么序列呢?很明顯,如果只在尾部操作,那么列表一定是最合適的選擇。
但如果我們操作的不止是尾部,還有頭部呢?比如往序列的頭部添加和彈出元素,此時(shí)雙端隊(duì)列就是一個(gè)不錯(cuò)的選擇。
雙端隊(duì)列支持從任意一端添加和刪除元素,更為常用的兩種數(shù)據(jù)結(jié)構(gòu)(即棧和隊(duì)列)就是雙端隊(duì)列的退化形式,它們的輸入和輸出被限制在某一端。
from?collections?import?deque
#?接收一個(gè)可迭代對象,然后進(jìn)行遍歷
d?=?deque("abcdefg")
print(d)?
"""
deque(['a',?'b',?'c',?'d',?'e',?'f',?'g'])
"""
print(len(d))?
"""
7
"""
print(d[0])?
"""
a
"""
print(d[-1])??
"""
g
"""
#?由于?deque?是一種序列容器,因此同樣支持?list?的操作
#?如:通過索引獲取元素,查看長度,刪除元素,反轉(zhuǎn)元素等等
#?list?支持的操作,deque?基本上都支持
d.reverse()
print(d)??#?deque(['g',?'f',?'e',?'d',?'c',?'b',?'a'])
d.remove("c")
print(d)??#?deque(['g',?'f',?'e',?'d',?'b',?'a'])deque 還有很多的 API,比如添加元素。
from?collections?import?deque
d?=?deque("abc")
#?添加元素,可以從兩端添加
d.append("Hello")??#?從尾部添加
d.appendleft("World")??#?也可以從頭部添加
print(d)
"""
deque(['World',?'a',?'b',?'c',?'Hello'])
"""
#?還可以使用?insert,?如果范圍越界,自動(dòng)添加在兩端
d.insert(100,?"古明地覺")
print(d)
"""
deque(['World',?'a',?'b',?'c',?'Hello',?'古明地覺'])
"""
#?也可以通過extend,extendleft?一次添加多個(gè)元素
d?=?deque([1,?2,?3])
d.extend([4,?5,?6])
print(d)
"""
deque([1,?2,?3,?4,?5,?6])
"""
d.extendleft([7,?8,?9])
print(d)
"""
deque([9,?8,?7,?1,?2,?3,?4,?5,?6])
"""
#?注意添加的順序,我們是從左邊開始添加的
#?先添加?7,然后?8?會(huì)跑到?7?的左邊,所以是結(jié)果是倒過來的再來看看刪除元素:
from?collections?import?deque d?=?deque(range(1,?7)) print(d) """ deque([1,?2,?3,?4,?5,?6]) """ #?調(diào)用?pop?方法可以從尾部彈出一個(gè)元素 print(d.pop())??#?6 print(d.pop())??#?5 print(d.pop())??#?4 #?pop?是從右端刪除一個(gè)元素,popleft?是從左端開始刪除一個(gè)元素 #?但如果想?pop?掉指定索引的元素,則只能用?pop?函數(shù),傳入索引值即可 print(d.popleft())??#?1 print(d) """ deque([2,?3]) """ #?注意:deque 和 queue一樣,是線程安全的 #?它們均受?GIL?這把超級大鎖保護(hù),可以不同的線程中進(jìn)行消費(fèi) #?如果想清空里面的元素,可以像?list、dict?一樣,使用?clear?方法 d.clear() print(d)?? """ deque([]) """
最后 deque 還有一個(gè)非常有意思的方法,叫 rotate,它是做什么的呢?來看一下。
from?collections?import?deque #?按任意一個(gè)方向進(jìn)行旋轉(zhuǎn),從而跳過某些元素。 # d.rotate(n):n 大于0,從右邊開始取 n 個(gè)元素放到左邊 #?n?小于?0,從左邊取?n?個(gè)元素放到右邊 d?=?deque(range(10)) print(d)?? """ deque([0,?1,?2,?3,?4,?5,?6,?7,?8,?9]) """ #?從右邊取?2?個(gè)元素放到左邊,所以?8?和?9?被放到了左邊 d.rotate(2) print(d)?? """ deque([8,?9,?0,?1,?2,?3,?4,?5,?6,?7]) """ d.rotate(-3) #?從左邊取?3?個(gè)元素放到右邊,所以?8、9、0?被放到了右邊 print(d)?? """ deque([1,?2,?3,?4,?5,?6,?7,?8,?9,?0]) """
當(dāng)然雙端隊(duì)列默認(rèn)是容量無限的,但很多時(shí)候我們需要給隊(duì)列加上容量限制,如何加呢?
from?collections?import?deque
#?限制隊(duì)列的大小
#?我們在初始化一個(gè)雙端隊(duì)列的時(shí)候,還可以限制它的大小
d?=?deque("abcdefg",?maxlen=5)
#?我們初始化?7?個(gè)元素,但是指定最大長度只有?5
#?所以前面兩個(gè)元素("a"?和?"b")就被擠出去了
print(d)
"""
deque(['c',?'d',?'e',?'f',?'g'],?maxlen=5)
"""
#?當(dāng)我往前面添加元素的時(shí)候,后面的就被擠出去了
#?因?yàn)殛?duì)列最多只能容納?5?個(gè)元素
d.appendleft("Hello")
print(d)??
"""
deque(['Hello',?'c',?'d',?'e',?'f'],?maxlen=5)
"""當(dāng)你要維護(hù)一個(gè)從首尾兩端添加、刪除元素的序列時(shí),使用 deque 是一個(gè)非常正確的選擇。
比如 asyncio 的鎖 Lock,當(dāng)獲取鎖時(shí),就會(huì)創(chuàng)建一個(gè) Future 對象,并保存在雙端隊(duì)列中。
帶有名字的元組
元組的話,我們都是通過索引來獲取元素,但通過索引的話,如果你不手動(dòng)數(shù)一數(shù),你是不知道該索引會(huì)對應(yīng)哪一個(gè)元素的。所以問題來了,可不可以給里面的元素一個(gè)字段名呢?我們通過字段名來獲取對應(yīng)的值不就行啦,沒錯(cuò),這就是 namedtuple。
from?collections?import?namedtuple
#?傳入名字,和字段
Person?=?namedtuple("Person",?["name",?"age",?"gender"])
person1?=?Person(name="satori",?age=16,?gender="f")
print(person1)
"""
Person(name='satori',?age=16,?gender='f')
"""
print(person1.name,?person1.age,?person1.gender)
"""
satori?16?f
"""
print(person1[0])
"""
satori
"""
#?不僅可以像普通的?tuple?一樣使用索引訪問
#?還可以像類一樣通過?.?字段名訪問
person2?=?Person("satori",?16,?"f")
#?注意:這個(gè)和普通的元組一樣,是不可以修改的
try:
????person2.name?=?"xxx"
except?AttributeError?as?e:
????print(e)??#?can't?set?attribute
#?非法字段名,不能使用?Python?的關(guān)鍵字
try:
????namedtuple("keywords",?["for",?"in"])
except?ValueError?as?e:
????print(e)
????"""
????Type?names?and?field?names?cannot?be?a?keyword:?'for'
????"""
#?如果字段名重復(fù)了,會(huì)報(bào)錯(cuò)
try:
????namedtuple("Person",?["name",?"age",?"age"])
except?ValueError?as?e:
????print(e)
????"""
????Encountered?duplicate?field?name:?'age'
????"""
#?如果非要加上重名字段,可以設(shè)置一個(gè)參數(shù)
Person?=?namedtuple("Person",?["name",?"age",?"age"],
????????????????????rename=True)
print(Person)??
"""
<class?'__main__.Person'>
"""
person3?=?Person("koishi",?15,?15)
#?可以看到重復(fù)的字段名會(huì)按照索引的值,在前面加上一個(gè)下劃線
#?比如第二個(gè)?age?重復(fù),它的索引是多少呢?是?2,所以默認(rèn)幫我們把字段名修改為?_2
print(person3)??
"""
Person(name='koishi',?age=15,?_2=15)
"""
#?此外我們所有的字段名都保存在?_fields?屬性中
print(person3._fields)??
"""
('name',?'age',?'_2')
"""但 namedtuple 還有一個(gè)不完美的地方,就是它無法指定字段的類型,所以我們更推薦使用 typing 模塊里的 NamedTuple。
from?typing?import?NamedTuple
class?Person(NamedTuple):
????name:?str
????age:?int
????gender:?str
p?=?Person("satori",?16,?"f")
print(p)
"""
Person(name='satori',?age=16,?gender='f')
"""
#?同樣能夠基于索引和字段名來獲取值
print(p[0],?p.name)
"""
satori?satori
"""
#?創(chuàng)建類的話,還可以這么創(chuàng)建
Person?=?NamedTuple('Person',?name=str,?age=int,?gender=str)
Person?=?NamedTuple(
????'Person',?[("name",?str),?("age",?int),?("gender",?str)]
)更建議使用 NamedTuple。
記住鍵值對順序的字典
從 Python3.6 開始,字典遍歷默認(rèn)是有序的,但我們不應(yīng)該依賴這個(gè)特性。如果希望字典有序,應(yīng)該使用 OrderDict 字典子類。
from?collections?import?OrderedDict
d?=?OrderedDict()
d["a"]?=?"A"
d["b"]?=?"B"
d["c"]?=?"C"
for?k,?v?in?d.items():
????print(k,?v)
"""
a?A
b?B
c?C
"""
#?此外也可以在初始化的時(shí)候,添加元素
print(OrderedDict({"a":?1}))??
"""
OrderedDict([('a',?1)])
"""
#?相等性,對于常規(guī)字典來說,只要里面元素一樣便是相等的,不考慮順序
#?但是對于OrderDict來說,除了元素,順序也要一樣,否則就不相等
d1?=?{"a":?1,?"b":?2}
d2?=?{"b":?2,?"a":?1}
print(d1?==?d2)??
"""
True
"""
d1?=?OrderedDict({"a":?1,?"b":?2})
d2?=?OrderedDict({"b":?2,?"a":?1})
print(d1?==?d2)??
"""
False
"""
#?重排,在?OrderDict?中可以使用?move_to_end?方法
#?將某個(gè)鍵移動(dòng)到序列的起始位置或末尾位置來改變順序
d3?=?OrderedDict({"a":?1,?"b":?2,?"c":?3,?"d":?4})
#?表示將?key="c"?的鍵值對移動(dòng)到末尾
d3.move_to_end("c")??
print(d3)??
"""
OrderedDict([('a',?1),?('b',?2),?('d',?4),?('c',?3)])
"""
#?表示將?key="c"?的這個(gè)鍵值對移動(dòng)到行首
d3.move_to_end("c",?last=False)??
print(d3)??
"""
OrderedDict([('c',?3),?('a',?1),?('b',?2),?('d',?4)])
"""
#?從尾部彈出一個(gè)元素
print(d3.popitem())
"""
('d',?4)
"""
#?從頭部彈出一個(gè)元素
print(d3.popitem(last=False))
"""
('c',?3)
"""使用 OrderDict 要比 dict 更加耗費(fèi)內(nèi)存,因此在存儲(chǔ)大量鍵值對的時(shí)候,思考一下,是否需要保證鍵值對有序。
但在實(shí)現(xiàn) LRU 緩存的時(shí)候,OrderDict 非常常用,比如某個(gè)鍵被訪問了,通過 move_to_end 移到頭部。當(dāng)緩存滿了的時(shí)候,通過 popitem 彈出尾部元素。
以上就是Python使用collections模塊實(shí)現(xiàn)擴(kuò)展數(shù)據(jù)類的詳細(xì)內(nèi)容,更多關(guān)于Python collections的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Python Dask庫處理大規(guī)模數(shù)據(jù)集的強(qiáng)大功能實(shí)戰(zhàn)
Dask是一個(gè)靈活、開源的Python庫,專為處理大規(guī)模數(shù)據(jù)集而設(shè)計(jì),與傳統(tǒng)的單機(jī)計(jì)算相比,Dask能夠在分布式系統(tǒng)上運(yùn)行,有效利用集群的計(jì)算資源,本文將深入介紹Dask的核心概念、功能和實(shí)際應(yīng)用,通過豐富的示例代碼展示其在大數(shù)據(jù)處理領(lǐng)域的強(qiáng)大能力2023-12-12
關(guān)于Pytorch MaxUnpool2d中size操作方式
今天小編就為大家分享一篇關(guān)于Pytorch MaxUnpool2d中size操作方式,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-01-01
python實(shí)現(xiàn)簡易五子棋游戲(控制臺(tái)版)
這篇文章主要為大家詳細(xì)介紹了python實(shí)現(xiàn)簡易五子棋游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-05-05
Python內(nèi)置函數(shù)——__import__ 的使用方法
本篇文章主要介紹了Python內(nèi)置函數(shù)——__import__ 的使用方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-11-11
如何使用matplotlib讓你的數(shù)據(jù)更加生動(dòng)
數(shù)據(jù)可視化用于以更直接的表示方式顯示數(shù)據(jù),并且更易于理解,下面這篇文章主要給大家介紹了關(guān)于如何使用matplotlib讓你的數(shù)據(jù)更加生動(dòng)的相關(guān)資料,需要的朋友可以參考下2021-11-11
Python機(jī)器學(xué)習(xí)NLP自然語言處理基本操作之命名實(shí)例提取
自然語言處理(?Natural?Language?Processing,?NLP)是計(jì)算機(jī)科學(xué)領(lǐng)域與人工智能領(lǐng)域中的一個(gè)重要方向。它研究能實(shí)現(xiàn)人與計(jì)算機(jī)之間用自然語言進(jìn)行有效通信的各種理論和方法2021-11-11
Python創(chuàng)建文件和追加文件內(nèi)容實(shí)例
這篇文章主要介紹了Python創(chuàng)建文件和追加文件內(nèi)容實(shí)例,本文同時(shí)給出了把標(biāo)準(zhǔn)輸出定向到文件實(shí)例,需要的朋友可以參考下2014-10-10

