Python集合:專業(yè)數(shù)據(jù)類型的自定義(Python是什么意思)

      網(wǎng)友投稿 1035 2025-04-02

      目錄

      Python 集合入門

      提高代碼可讀性:namedtuple()

      構(gòu)建高效的隊(duì)列和堆棧:deque

      處理丟失的鍵:defaultdict

      保持字典有序:OrderedDict

      一次計(jì)數(shù)對(duì)象:計(jì)數(shù)器

      將字典鏈接在一起:ChainMap

      自定義內(nèi)置函數(shù):UserString、UserList 和 UserDict

      結(jié)論

      Python 的collections模塊提供了一組豐富的專用容器數(shù)據(jù)類型,這些數(shù)據(jù)類型經(jīng)過(guò)精心設(shè)計(jì),以 Pythonic 和高效的方式解決特定的編程問題。該模塊還提供包裝類,使之更安全創(chuàng)建,其行為類似于內(nèi)建類型的自定義類dict,list和str。

      了解 中的數(shù)據(jù)類型和類collections將使您能夠使用一組有價(jià)值的可靠和高效的工具來(lái)擴(kuò)展您的編程工具包。

      在本教程中,您將學(xué)習(xí)如何:

      編寫可讀且顯式的代碼namedtuple

      建立高效的隊(duì)列,棧與deque

      快速計(jì)數(shù)對(duì)象Counter

      處理缺少字典鍵與defaultdict

      保證鍵的插入順序OrderedDict

      將多個(gè)字典作為一個(gè)單元管理ChainMap

      為了更好地理解 中的數(shù)據(jù)類型和類collections,您應(yīng)該了解使用 Python 內(nèi)置數(shù)據(jù)類型(例如列表、元組和字典)的基礎(chǔ)知識(shí)。此外,本文的最后一部分需要有關(guān)Python 中面向?qū)ο缶幊痰囊恍┗局R(shí)。

      Python 入門?collections

      早在Python 2.4中,雷蒙德赫廷杰貢獻(xiàn)了一個(gè)所謂的新模塊collections的標(biāo)準(zhǔn)庫(kù)。目標(biāo)是提供各種專門的集合數(shù)據(jù)類型來(lái)解決特定的編程問題。

      當(dāng)時(shí)collections只包含了一個(gè)數(shù)據(jù)結(jié)構(gòu) ,deque專門設(shè)計(jì)成一個(gè)雙端隊(duì)列,支持在序列的任一端進(jìn)行高效的append和pop操作。從那時(shí)起,標(biāo)準(zhǔn)庫(kù)中的幾個(gè)模塊利用deque來(lái)提高它們的類和結(jié)構(gòu)的性能。一些突出的例子是queue和threading。

      隨著時(shí)間的推移,一些專門的容器數(shù)據(jù)類型填充了模塊:

      除了這些專門的數(shù)據(jù)類型之外,collections還提供了三個(gè)基類來(lái)促進(jìn)自定義列表、字典和字符串的創(chuàng)建:

      將相應(yīng)的標(biāo)準(zhǔn)內(nèi)置數(shù)據(jù)類型進(jìn)行子類化的能力使對(duì)這些包裝器類的需求部分黯然失色。但是,有時(shí)使用這些類比使用標(biāo)準(zhǔn)數(shù)據(jù)類型更安全且不易出錯(cuò)。

      通過(guò)collections對(duì)本模塊中的數(shù)據(jù)結(jié)構(gòu)和類可以解決的具體用例的簡(jiǎn)要介紹,是時(shí)候仔細(xì)研究它們了。在此之前,重要的是要指出本教程是collections一個(gè)整體的介紹。在以下大部分內(nèi)容中,您會(huì)找到一個(gè)藍(lán)色警告框,它會(huì)引導(dǎo)您閱讀有關(guān)當(dāng)前類或函數(shù)的專門文章。

      提高代碼可讀性:?namedtuple()

      Pythonnamedtuple()是一個(gè)工廠函數(shù),它允許您創(chuàng)建tuple具有命名字段的子類。這些字段使您可以使用點(diǎn)表示法直接訪問給定命名元組中的值,例如 in?obj.attr。

      之所以需要此功能,是因?yàn)槭褂盟饕L問常規(guī)元組中的值很煩人、難以閱讀且容易出錯(cuò)。如果您正在使用的元組有多個(gè)項(xiàng)目并且在遠(yuǎn)離您使用它的地方構(gòu)建,則尤其如此。

      注意:查看使用 namedtuple 編寫 Pythonic 和 Clean Code 以更深入地了解如何namedtuple在 Python 中使用。

      開發(fā)人員可以使用點(diǎn)表示法訪問具有命名字段的元組子類,這在 Python 2.6 中似乎是一個(gè)理想的功能。這就是namedtuple().?如果將它們與常規(guī)元組進(jìn)行比較,您可以使用此函數(shù)構(gòu)建的元組子類在代碼可讀性方面是一個(gè)巨大的勝利。

      為了正確看待代碼可讀性問題,請(qǐng)考慮divmod().?這個(gè)內(nèi)置函數(shù)接受兩個(gè)(非復(fù)數(shù))數(shù)字并返回一個(gè)元組,其中包含由輸入值的整數(shù)除法產(chǎn)生的商和余數(shù):

      >>> divmod(12, 5) (2, 2)

      它工作得很好。但是,這個(gè)結(jié)果可讀嗎?你能說(shuō)出輸出中每個(gè)數(shù)字的含義嗎?幸運(yùn)的是,Python 提供了一種改進(jìn)方法。您可以使用以下代碼對(duì)divmod()具有顯式結(jié)果的自定義版本進(jìn)行編碼namedtuple:

      >>>

      >>> from collections import namedtuple >>> def custom_divmod(x, y): ... DivMod = namedtuple("DivMod", "quotient remainder") ... return DivMod(*divmod(x, y)) ... >>> result = custom_divmod(12, 5) >>> result DivMod(quotient=2, remainder=2) >>> result.quotient 2 >>> result.remainder 2

      現(xiàn)在您知道結(jié)果中每個(gè)值的含義了。您還可以使用點(diǎn)表示法和描述性字段名稱訪問每個(gè)獨(dú)立值。

      要使用 創(chuàng)建新的元組子類namedtuple(),您需要兩個(gè)必需的參數(shù):

      typename是您正在創(chuàng)建的類的名稱。它必須是具有有效 Python 標(biāo)識(shí)符的字符串。

      field_names是您將用于訪問生成的元組中的項(xiàng)目的字段名稱列表。有可能:

      一個(gè)可迭代的字符串,例如["field1", "field2", ..., "fieldN"]

      具有以空格分隔的字段名稱的字符串,例如?"field1 field2 ... fieldN"

      具有逗號(hào)分隔字段名稱的字符串,例如?"field1, field2, ..., fieldN"

      例如,以下是使用以下方法創(chuàng)建Point具有兩個(gè)坐標(biāo) (x和y)的示例 2D 的不同方法namedtuple():

      >>> from collections import namedtuple >>> # Use a list of strings as field names >>> Point = namedtuple("Point", ["x", "y"]) >>> point = Point(2, 4) >>> point Point(x=2, y=4) >>> # Access the coordinates >>> point.x 2 >>> point.y 4 >>> point[0] 2 >>> # Use a generator expression as field names >>> Point = namedtuple("Point", (field for field in "xy")) >>> Point(2, 4) Point(x=2, y=4) >>> # Use a string with comma-separated field names >>> Point = namedtuple("Point", "x, y") >>> Point(2, 4) Point(x=2, y=4) >>> # Use a string with space-separated field names >>> Point = namedtuple("Point", "x y") >>> Point(2, 4) Point(x=2, y=4)

      在這些示例中,您首先Point使用list字段名稱創(chuàng)建。然后實(shí)例化Point以創(chuàng)建一個(gè)point對(duì)象。請(qǐng)注意,您可以通過(guò)字段名稱和索引訪問x和y。

      其余示例展示了如何使用逗號(hào)分隔的字段名稱字符串、生成器表達(dá)式和空格分隔的字段名稱字符串創(chuàng)建等效的命名元組。

      命名元組還提供了一系列很酷的功能,允許您為字段定義默認(rèn)值、從給定的命名元組創(chuàng)建字典、替換給定字段的值等等:

      >>> from collections import namedtuple >>> # Define default values for fields >>> Person = namedtuple("Person", "name job", defaults=["Python Developer"]) >>> person = Person("Jane") >>> person Person(name='Jane', job='Python Developer') >>> # Create a dictionary from a named tuple >>> person._asdict() {'name': 'Jane', 'job': 'Python Developer'} >>> # Replace the value of a field >>> person = person._replace(job="Web Developer") >>> person Person(name='Jane', job='Web Developer')

      在這里,您首先Person使用namedtuple().?這一次,您使用一個(gè)名為的可選參數(shù)defaults,該參數(shù)接受元組字段的一系列默認(rèn)值。請(qǐng)注意,namedtuple()將默認(rèn)值應(yīng)用于最右側(cè)的字段。

      在第二個(gè)示例中,您使用._asdict().?此方法返回一個(gè)使用字段名稱作為鍵的新字典。

      最后,您使用._replace()替換 的原始值job。此方法不會(huì)就地更新元組,而是返回一個(gè)新命名的元組,新值存儲(chǔ)在相應(yīng)的字段中。你知道為什么要._replace()返回一個(gè)新命名的元組嗎?

      構(gòu)建高效的隊(duì)列和堆棧:?deque

      Pythondeque是collections.?這種類似序列的數(shù)據(jù)類型是堆棧和隊(duì)列的泛化,旨在支持?jǐn)?shù)據(jù)結(jié)構(gòu)兩端的高效內(nèi)存和快速追加和彈出操作。

      注:這個(gè)詞deque的發(fā)音是“甲板”和代表d?ouble-?é?nded闕UE。

      在 Python 中,list對(duì)象開頭或左側(cè)的 append 和 pop 操作效率低下,時(shí)間復(fù)雜度為O?(?n?)。如果您使用大型列表,這些操作尤其昂貴,因?yàn)?Python 必須將所有項(xiàng)目向右移動(dòng)才能在列表的開頭插入新項(xiàng)目。

      另一方面,列表右側(cè)的 append 和 pop 操作通常是有效的(O?(1)),除了 Python 需要重新分配內(nèi)存以增長(zhǎng)底層列表以接受新項(xiàng)目的情況。

      Pythondeque就是為了解決這個(gè)問題而創(chuàng)建的。deque對(duì)象兩側(cè)的追加和彈出操作是穩(wěn)定且同樣高效的,因?yàn)殡p端隊(duì)列是作為雙向鏈表實(shí)現(xiàn)的。這就是為什么雙端隊(duì)列對(duì)于創(chuàng)建堆棧和隊(duì)列特別有用。

      以隊(duì)列為例。它以先進(jìn)/先出(?FIFO?) 方式管理項(xiàng)目。它用作管道,您可以在管道的一端插入新項(xiàng)目,然后從另一端彈出舊項(xiàng)目。將項(xiàng)目添加到隊(duì)列的末尾稱為入隊(duì)操作。從隊(duì)列的前面或開頭刪除項(xiàng)目稱為dequeue。

      現(xiàn)在假設(shè)您正在模擬排隊(duì)等候購(gòu)買電影票的人。您可以使用deque.?每次有新人到達(dá)時(shí),您都會(huì)將他們排入隊(duì)列。當(dāng)隊(duì)列前面的人拿到他們的票時(shí),你就讓他們出隊(duì)。

      以下是使用deque對(duì)象模擬該過(guò)程的方法:

      >>> from collections import deque >>> ticket_queue = deque() >>> ticket_queue deque([]) >>> # People arrive to the queue >>> ticket_queue.append("Jane") >>> ticket_queue.append("John") >>> ticket_queue.append("Linda") >>> ticket_queue deque(['Jane', 'John', 'Linda']) >>> # People bought their tickets >>> ticket_queue.popleft() 'Jane' >>> ticket_queue.popleft() 'John' >>> ticket_queue.popleft() 'Linda' >>> # No people on the queue >>> ticket_queue.popleft() Traceback (most recent call last): File "", line 1, in IndexError: pop from an empty deque

      在這里,您首先創(chuàng)建一個(gè)空deque對(duì)象來(lái)表示人員隊(duì)列。要使一個(gè)人入隊(duì),您可以使用.append(),它將項(xiàng)目添加到雙端隊(duì)列的右端。要使一個(gè)人出隊(duì),您可以使用.popleft(),它刪除并返回雙端隊(duì)列左端的項(xiàng)目。

      注意:在 Python 標(biāo)準(zhǔn)庫(kù)中,您會(huì)發(fā)現(xiàn)queue.?該模塊實(shí)現(xiàn)了多生產(chǎn)者、多消費(fèi)者隊(duì)列,可用于安全地在多個(gè)線程之間交換信息。

      在deque初始化有兩個(gè)可選參數(shù):

      iterable?持有一個(gè)用作初始化程序的可迭代對(duì)象。

      maxlen保存一個(gè)整數(shù),用于指定 的最大長(zhǎng)度deque。

      如果您不提供iterable,則會(huì)得到一個(gè)空的雙端隊(duì)列。如果您為 提供值maxlen,那么您的雙端隊(duì)列將最多存儲(chǔ)maxlen項(xiàng)目。

      擁有 amaxlen是一個(gè)方便的功能。例如,假設(shè)您需要在您的一個(gè)應(yīng)用程序中實(shí)現(xiàn)最近文件列表。在這種情況下,您可以執(zhí)行以下操作:

      >>> from collections import deque >>> recent_files = deque(["core.py", "README.md", "__init__.py"], maxlen=3) >>> recent_files.appendleft("database.py") >>> recent_files deque(['database.py', 'core.py', 'README.md'], maxlen=3) >>> recent_files.appendleft("requirements.txt") >>> recent_files deque(['requirements.txt', 'database.py', 'core.py'], maxlen=3)

      一旦雙端隊(duì)列達(dá)到其最大大小(在本例中為三個(gè)文件),在雙端隊(duì)列的末尾添加一個(gè)新文件會(huì)自動(dòng)丟棄另一端的文件。如果您不向 提供值maxlen,則雙端隊(duì)列可以增長(zhǎng)到任意數(shù)量的項(xiàng)目。

      到目前為止,您已經(jīng)學(xué)習(xí)了雙端隊(duì)列的基礎(chǔ)知識(shí),包括如何創(chuàng)建它們以及如何從給定雙端隊(duì)列的兩端追加和彈出項(xiàng)目。Deques 提供了一些具有類似列表界面的附加功能。這里是其中的一些:

      >>> from collections import deque >>> # Use different iterables to create deques >>> deque((1, 2, 3, 4)) deque([1, 2, 3, 4]) >>> deque([1, 2, 3, 4]) deque([1, 2, 3, 4]) >>> deque("abcd") deque(['a', 'b', 'c', 'd']) >>> # Unlike lists, deque doesn't support .pop() with arbitrary indices >>> deque("abcd").pop(2) Traceback (most recent call last): File "", line 1, in TypeError: pop() takes no arguments (1 given) >>> # Extend an existing deque >>> numbers = deque([1, 2]) >>> numbers.extend([3, 4, 5]) >>> numbers deque([1, 2, 3, 4, 5]) >>> numbers.extendleft([-1, -2, -3, -4, -5]) >>> numbers deque([-5, -4, -3, -2, -1, 1, 2, 3, 4, 5]) >>> # Insert an item at a given position >>> numbers.insert(5, 0) >>> numbers deque([-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5])

      在這些示例中,您首先使用不同類型的可迭代對(duì)象創(chuàng)建雙端隊(duì)列來(lái)初始化它們。deque和之間的一個(gè)區(qū)別list是deque.pop()不支持在給定索引處彈出項(xiàng)目。

      請(qǐng)注意,deque為、 和提供了姐妹方法.append(),后綴表示它們?cè)诘讓与p端隊(duì)列的左端執(zhí)行相應(yīng)的操作。.pop().extend()left

      Deques 還支持序列操作:

      雙端隊(duì)列的另一個(gè)有趣功能是能夠使用.rotate()以下方法旋轉(zhuǎn)其元素:

      >>> from collections import deque >>> ordinals = deque(["first", "second", "third"]) >>> ordinals.rotate() >>> ordinals deque(['third', 'first', 'second']) >>> ordinals.rotate(2) >>> ordinals deque(['first', 'second', 'third']) >>> ordinals.rotate(-2) >>> ordinals deque(['third', 'first', 'second']) >>> ordinals.rotate(-1) >>> ordinals deque(['first', 'second', 'third'])

      此方法將雙端隊(duì)列n向右旋轉(zhuǎn)。默認(rèn)值n是1。如果為 提供負(fù)值n,則向左旋轉(zhuǎn)。

      最后,您可以使用索引訪問雙端隊(duì)列中的元素,但不能對(duì)雙端隊(duì)列進(jìn)行切片:

      Python 的集合:專業(yè)數(shù)據(jù)類型的自定義(python是什么意思)

      >>>

      >>> from collections import deque >>> ordinals = deque(["first", "second", "third"]) >>> ordinals[1] 'second' >>> ordinals[0:2] Traceback (most recent call last): File "", line 1, in TypeError: sequence index must be integer, not 'slice'

      雙端隊(duì)列支持索引,但有趣的是,它們不支持切片。當(dāng)您嘗試從現(xiàn)有雙端隊(duì)列中檢索切片時(shí),您會(huì)得到一個(gè)TypeError.?這是因?yàn)閷?duì)鏈表執(zhí)行切片操作效率低下,因此該操作不可用。

      處理丟失的鍵:?defaultdict

      當(dāng)您在 Python 中使用字典時(shí),您將面臨的一個(gè)常見問題是如何處理丟失的鍵。如果您嘗試訪問給定字典中不存在的鍵,則會(huì)得到KeyError:

      >>>

      >>> favorites = {"pet": "dog", "color": "blue", "language": "Python"} >>> favorites["fruit"] Traceback (most recent call last): File "", line 1, in KeyError: 'fruit'

      有幾種方法可以解決此問題。例如,您可以使用.setdefault().?此方法將鍵作為參數(shù)。如果鍵存在于字典中,則返回相應(yīng)的值。否則,該方法插入鍵,為其分配一個(gè)默認(rèn)值,并返回該值:

      >>> favorites = {"pet": "dog", "color": "blue", "language": "Python"} >>> favorites.setdefault("fruit", "apple") 'apple' >>> favorites {'pet': 'dog', 'color': 'blue', 'language': 'Python', 'fruit': 'apple'} >>> favorites.setdefault("pet", "cat") 'dog' >>> favorites {'pet': 'dog', 'color': 'blue', 'language': 'Python', 'fruit': 'apple'}

      在此示例中,您使用.setdefault()為 生成默認(rèn)值fruit。由于該鍵在 中不存在favorites,請(qǐng).setdefault()創(chuàng)建它并為其分配 值apple。如果您.setdefault()使用現(xiàn)有鍵調(diào)用,則調(diào)用不會(huì)影響字典,并且您的鍵將保存原始值而不是默認(rèn)值。

      .get()如果缺少給定的鍵,您還可以使用返回合適的默認(rèn)值:

      >>> favorites = {"pet": "dog", "color": "blue", "language": "Python"} >>> favorites.get("fruit", "apple") 'apple' >>> favorites {'pet': 'dog', 'color': 'blue', 'language': 'Python'}

      在這里,.get()返回apple是因?yàn)榈讓幼值渲腥鄙冁I。但是,.get()不會(huì)為您創(chuàng)建新密鑰。

      由于處理字典中缺失的鍵是一個(gè)常見的需求,Pythoncollections也為此提供了一個(gè)工具。該defaultdict類型是dict旨在幫助您解決丟失鍵的子類。

      注意:查看使用 Python defaultdict 類型處理丟失的鍵以深入了解如何使用 Python 的defaultdict.

      的構(gòu)造defaultdict函數(shù)接受一個(gè)函數(shù)對(duì)象作為它的第一個(gè)參數(shù)。當(dāng)您訪問一個(gè)不存在的鍵時(shí),defaultdict自動(dòng)調(diào)用該函數(shù)而不帶參數(shù)來(lái)為手頭的鍵創(chuàng)建合適的默認(rèn)值。

      您可以使用任何可調(diào)用defaultdict對(duì)象來(lái)初始化您的對(duì)象。例如,int()您可以創(chuàng)建一個(gè)合適的計(jì)數(shù)器來(lái)計(jì)算不同的對(duì)象:

      >>>

      >>> from collections import defaultdict >>> counter = defaultdict(int) >>> counter defaultdict(, {}) >>> counter["dogs"] 0 >>> counter defaultdict(, {'dogs': 0}) >>> counter["dogs"] += 1 >>> counter["dogs"] += 1 >>> counter["dogs"] += 1 >>> counter["cats"] += 1 >>> counter["cats"] += 1 >>> counter defaultdict(, {'dogs': 3, 'cats': 2})

      在這個(gè)例子中,你創(chuàng)建一個(gè)空defaultdict與int()作為第一個(gè)參數(shù)。當(dāng)您訪問一個(gè)不存在的鍵時(shí),字典會(huì)自動(dòng)調(diào)用int(),它將0作為手頭鍵的默認(rèn)值返回。defaultdict在 Python 中計(jì)算事物時(shí),這種對(duì)象非常有用。

      的另一個(gè)常見用例defaultdict是對(duì)事物進(jìn)行分組。在這種情況下,方便的工廠函數(shù)是list():

      >>>

      >>> from collections import defaultdict >>> pets = [ ... ("dog", "Affenpinscher"), ... ("dog", "Terrier"), ... ("dog", "Boxer"), ... ("cat", "Abyssinian"), ... ("cat", "Birman"), ... ] >>> group_pets = defaultdict(list) >>> for pet, breed in pets: ... group_pets[pet].append(breed) ... >>> for pet, breeds in group_pets.items(): ... print(pet, "->", breeds) ... dog -> ['Affenpinscher', 'Terrier', 'Boxer'] cat -> ['Abyssinian', 'Birman']

      在此示例中,您有關(guān)于寵物及其品種的原始數(shù)據(jù),您需要按寵物對(duì)它們進(jìn)行分組。為此,請(qǐng)?jiān)趧?chuàng)建實(shí)例時(shí)使用list()as?。這使您的字典能夠自動(dòng)創(chuàng)建一個(gè)空列表 (?) 作為您訪問的每個(gè)缺失鍵的默認(rèn)值。然后您使用該列表來(lái)存儲(chǔ)您的寵物的品種。.default_factorydefaultdict[]

      最后,您應(yīng)該注意,由于defaultdict是 的子類dict,因此它提供了相同的接口。這意味著您可以defaultdict像使用常規(guī)字典一樣使用您的對(duì)象。

      保持字典有序:?OrderedDict

      有時(shí)您需要字典來(lái)記住插入鍵值對(duì)的順序。多年來(lái),Python 的常規(guī)詞典都是無(wú)序的?數(shù)據(jù)結(jié)構(gòu)。因此,早在 2008 年,PEP 372 就引入了向collections.

      新類將根據(jù)插入鍵的時(shí)刻記住項(xiàng)目的順序。那就是OrderedDict.

      OrderedDict在Python 3.1中引入。它的應(yīng)用程序編程接口 (API) 與dict.?但是,OrderedDict以相同的順序?qū)︽I和值進(jìn)行迭代,鍵首先被插入到字典中。如果為現(xiàn)有鍵分配新值,則鍵值對(duì)的順序保持不變。如果一個(gè)條目被刪除并重新插入,那么它將被移動(dòng)到字典的末尾。

      注意:查看Python 中的 OrderedDict 與 dict:工作的正確工具,以更深入地了解 PythonOrderedDict以及您應(yīng)該考慮使用它的原因。

      有幾種方法可以創(chuàng)建OrderedDict對(duì)象。它們中的大多數(shù)與您創(chuàng)建常規(guī)字典的方式相同。例如,您可以通過(guò)實(shí)例化不帶參數(shù)的類來(lái)創(chuàng)建一個(gè)空的有序字典,然后根據(jù)需要插入鍵值對(duì):

      >>> from collections import OrderedDict >>> life_stages = OrderedDict() >>> life_stages["childhood"] = "0-9" >>> life_stages["adolescence"] = "9-18" >>> life_stages["adulthood"] = "18-65" >>> life_stages["old"] = "+65" >>> for stage, years in life_stages.items(): ... print(stage, "->", years) ... childhood -> 0-9 adolescence -> 9-18 adulthood -> 18-65 old -> +65

      在這個(gè)例子中,你通過(guò)OrderedDict不帶參數(shù)的實(shí)例化來(lái)創(chuàng)建一個(gè)空的有序字典。接下來(lái),像使用常規(guī)字典一樣將鍵值對(duì)添加到字典中。

      當(dāng)您遍歷字典, 時(shí)life_stages,您會(huì)按照將它們插入字典中的相同順序獲得鍵值對(duì)。保證物品的順序是主要解決的問題OrderedDict。

      Python的3.6引入了一個(gè)新的實(shí)現(xiàn)dict。這個(gè)實(shí)現(xiàn)提供了一個(gè)意想不到的新功能:現(xiàn)在常規(guī)詞典將它們的項(xiàng)目按照它們第一次插入的順序保存。

      最初,該功能被認(rèn)為是一個(gè)實(shí)現(xiàn)細(xì)節(jié),文檔建議不要依賴它。但是,從Python 3.7 開始,該功能正式成為語(yǔ)言規(guī)范的一部分。那么,使用的意義OrderedDict何在?

      有一些特點(diǎn)OrderedDict仍然使它有價(jià)值:

      意圖通信:使用OrderedDict,您的代碼將清楚地表明字典中項(xiàng)目的順序很重要。您清楚地傳達(dá)了您的代碼需要或依賴于底層字典中項(xiàng)目的順序。

      控制項(xiàng)目的順序:使用OrderedDict,您可以訪問.move_to_end(),這是一種允許您操縱字典中項(xiàng)目順序的方法。您還將擁有一個(gè)增強(qiáng)的變體,.popitem()它允許從底層字典的任一端刪除項(xiàng)目。

      相等測(cè)試行為:使用OrderedDict,字典之間的相等測(cè)試會(huì)考慮項(xiàng)目的順序。因此,如果您有兩個(gè)具有相同項(xiàng)目組但順序不同的有序字典,那么您的字典將被視為不相等。

      至少還有一個(gè)使用的理由OrderedDict:向后兼容。在dict運(yùn)行 Python 3.6 之前版本的環(huán)境中,依靠常規(guī)對(duì)象來(lái)保留項(xiàng)目的順序會(huì)破壞您的代碼。

      好的,現(xiàn)在是時(shí)候看看這些很酷的功能了OrderedDict:

      >>> from collections import OrderedDict >>> letters = OrderedDict(b=2, d=4, a=1, c=3) >>> letters OrderedDict([('b', 2), ('d', 4), ('a', 1), ('c', 3)]) >>> # Move b to the right end >>> letters.move_to_end("b") >>> letters OrderedDict([('d', 4), ('a', 1), ('c', 3), ('b', 2)]) >>> # Move b to the left end >>> letters.move_to_end("b", last=False) >>> letters OrderedDict([('b', 2), ('d', 4), ('a', 1), ('c', 3)]) >>> # Sort letters by key >>> for key in sorted(letters): ... letters.move_to_end(key) ... >>> letters OrderedDict([('a', 1), ('b', 2), ('c', 3), ('d', 4)])

      在這些示例中,您使用.move_to_end()來(lái)移動(dòng)項(xiàng)目和重新排序letters。請(qǐng)注意,.move_to_end()接受一個(gè)名為的可選參數(shù)last,該參數(shù)允許您控制要將項(xiàng)目移動(dòng)到字典的哪一端。當(dāng)您需要對(duì)字典中的項(xiàng)目進(jìn)行排序或需要以任何方式操縱它們的順序時(shí),此方法非常方便。

      OrderedDict和普通字典之間的另一個(gè)重要區(qū)別是它們?nèi)绾伪容^相等性:

      >>> from collections import OrderedDict >>> # Regular dictionaries compare the content only >>> letters_0 = dict(a=1, b=2, c=3, d=4) >>> letters_1 = dict(b=2, a=1, d=4, c=3) >>> letters_0 == letters_1 True >>> # Ordered dictionaries compare content and order >>> letters_0 = OrderedDict(a=1, b=2, c=3, d=4) >>> letters_1 = OrderedDict(b=2, a=1, d=4, c=3) >>> letters_0 == letters_1 False >>> letters_2 = OrderedDict(a=1, b=2, c=3, d=4) >>> letters_0 == letters_2 True

      在這里,letters_1具有與 不同的項(xiàng)目順序letters_0。當(dāng)您使用常規(guī)詞典時(shí),這種差異無(wú)關(guān)緊要,兩個(gè)詞典比較相等。另一方面,當(dāng)您使用有序字典時(shí),letters_0和letters_1不相等。這是因?yàn)橛行蜃值渲g的相等性測(cè)試考慮內(nèi)容和項(xiàng)目的順序。

      一次計(jì)數(shù)對(duì)象:?Counter

      計(jì)數(shù)對(duì)象是編程中的常見操作。假設(shè)您需要計(jì)算給定項(xiàng)目出現(xiàn)在列表或可迭代對(duì)象中的次數(shù)。如果您的清單很短,那么計(jì)算其項(xiàng)目可能會(huì)簡(jiǎn)單快捷。如果您有一個(gè)很長(zhǎng)的清單,那么計(jì)算項(xiàng)目將更具挑戰(zhàn)性。

      要對(duì)對(duì)象進(jìn)行計(jì)數(shù),通常使用counter或初始值為 0的整數(shù)變量。然后增加計(jì)數(shù)器以反映給定對(duì)象出現(xiàn)的次數(shù)。

      在 Python 中,您可以使用字典一次計(jì)算多個(gè)不同的對(duì)象。在這種情況下,鍵將存儲(chǔ)單個(gè)對(duì)象,值將保存給定對(duì)象的重復(fù)次數(shù)或?qū)ο蟮挠?jì)數(shù)。

      這是一個(gè)"mississippi"使用常規(guī)字典和for循環(huán)計(jì)算單詞中字母的示例:

      >>> word = "mississippi" >>> counter = {} >>> for letter in word: ... if letter not in counter: ... counter[letter] = 0 ... counter[letter] += 1 ... >>> counter {'m': 1, 'i': 4, 's': 4, 'p': 2}

      循環(huán)遍歷 中的字母word。該條件語(yǔ)句檢查,如果字母是不是已經(jīng)在字典中并初始化字母的數(shù)量相應(yīng)為零。最后一步是隨著循環(huán)的進(jìn)行增加字母的計(jì)數(shù)。

      正如您已經(jīng)知道的那樣,defaultdict對(duì)象在計(jì)算事物時(shí)很方便,因?yàn)槟恍枰獧z查鍵是否存在。字典保證任何缺失的鍵都有適當(dāng)?shù)哪J(rèn)值:

      >>>

      >>> from collections import defaultdict >>> counter = defaultdict(int) >>> for letter in "mississippi": ... counter[letter] += 1 ... >>> counter defaultdict(, {'m': 1, 'i': 4, 's': 4, 'p': 2})

      在此示例中,您創(chuàng)建一個(gè)defaultdict對(duì)象并使用 對(duì)其進(jìn)行初始化int()。隨著int()作為工廠的功能,基本默認(rèn)的字典會(huì)自動(dòng)創(chuàng)建丟失的鑰匙,方便他們初始化為零。然后增加當(dāng)前鍵的值以計(jì)算 中字母的最終計(jì)數(shù)"mississippi"。

      就像其他常見的編程問題一樣,Python 也有一個(gè)解決計(jì)數(shù)問題的有效工具。在 中collections,您會(huì)發(fā)現(xiàn)Counter,這是一個(gè)dict專為計(jì)算對(duì)象而設(shè)計(jì)的子類。

      以下是如何"mississippi"使用Counter以下方法編寫示例:

      >>>

      >>> from collections import Counter >>> Counter("mississippi") Counter({'i': 4, 's': 4, 'p': 2, 'm': 1})

      哇!那很快!一行代碼就完成了。在這個(gè)例子中,Counter迭代"mississippi",生成一個(gè)以字母為鍵、頻率為值的字典。

      注意:查看Python 的計(jì)數(shù)器:計(jì)算對(duì)象的 Pythonic 方法以深入了解Counter以及如何使用它來(lái)有效地計(jì)算對(duì)象。

      有幾種不同的實(shí)例化方法Counter。您可以使用列表、元組或任何具有重復(fù)對(duì)象的可迭代對(duì)象。唯一的限制是您的對(duì)象需要是可散列的:

      >>>

      >>> from collections import Counter >>> Counter([1, 1, 2, 3, 3, 3, 4]) Counter({3: 3, 1: 2, 2: 1, 4: 1}) >>> Counter(([1], [1])) Traceback (most recent call last): ... TypeError: unhashable type: 'list'

      整數(shù)是可散列的,因此Counter可以正常工作。另一方面,列表不可散列,因此Counter失敗并帶有TypeError.

      可散列意味著您的對(duì)象必須具有在其生命周期中永遠(yuǎn)不會(huì)改變的散列值。這是一個(gè)要求,因?yàn)檫@些對(duì)象將用作字典鍵。在 Python 中,不可變對(duì)象也是可散列的。

      注意:在 中Counter,高度優(yōu)化的C 函數(shù)提供計(jì)數(shù)功能。如果此函數(shù)由于某種原因不可用,則該類使用等效但效率較低的Python 函數(shù)。

      由于Counter是 的子類dict,它們的接口大體相同。但是,存在一些細(xì)微的差異。第一個(gè)區(qū)別是Counter沒有實(shí)現(xiàn).fromkeys().?這避免了不一致,例如Counter.fromkeys("abbbc", 2),每個(gè)字母都有一個(gè)初始計(jì)數(shù),2而不管它在輸入迭代中的實(shí)際計(jì)數(shù)如何。

      第二個(gè)區(qū)別是.update()不會(huì)用新的計(jì)數(shù)替換現(xiàn)有對(duì)象(鍵)的計(jì)數(shù)(值)。它將兩個(gè)計(jì)數(shù)加在一起:

      >>> from collections import Counter >>> letters = Counter("mississippi") >>> letters Counter({'i': 4, 's': 4, 'p': 2, 'm': 1}) >>> # Update the counts of m and i >>> letters.update(m=3, i=4) >>> letters Counter({'i': 8, 'm': 4, 's': 4, 'p': 2}) >>> # Add a new key-count pair >>> letters.update({"a": 2}) >>> letters Counter({'i': 8, 'm': 4, 's': 4, 'p': 2, 'a': 2}) >>> # Update with another counter >>> letters.update(Counter(["s", "s", "p"])) >>> letters Counter({'i': 8, 's': 6, 'm': 4, 'p': 3, 'a': 2})

      在這里,您更新計(jì)數(shù)m和i。現(xiàn)在,這些字母包含它們初始計(jì)數(shù)的總和加上您通過(guò) 傳遞給它們的值.update()。如果您使用原始計(jì)數(shù)器中不存在的鍵,則.update()創(chuàng)建具有相應(yīng)值的新鍵。最后,.update()接受可迭代對(duì)象、映射、關(guān)鍵字參數(shù)以及其他計(jì)數(shù)器。

      注意:由于Counter是 的子類dict,因此對(duì)可以存儲(chǔ)在計(jì)數(shù)器的鍵和值中的對(duì)象沒有限制。鍵可以存儲(chǔ)任何可散列的對(duì)象,而值可以存儲(chǔ)任何對(duì)象。但是,要在邏輯上用作計(jì)數(shù)器,值應(yīng)該是表示計(jì)數(shù)的整數(shù)。

      Counterand之間的另一個(gè)區(qū)別dict是訪問丟失的鍵返回0而不是提高 a?KeyError:

      >>>

      >>> from collections import Counter >>> letters = Counter("mississippi") >>> letters["a"] 0

      此行為表示計(jì)數(shù)器中不存在的對(duì)象的計(jì)數(shù)為零。在此示例中,該字母"a"不在原始單詞中,因此其計(jì)數(shù)為0。

      在 Python 中,Counter也可用于模擬multiset或bag。Multisets 類似于set,但它們?cè)试S給定元素的多個(gè)實(shí)例。一個(gè)元素的實(shí)例數(shù)被稱為它的多重性。例如,您可以有一個(gè)像 {1, 1, 2, 3, 3, 3, 4, 4} 這樣的多重集。

      當(dāng)你Counter用來(lái)模擬多重集時(shí),鍵代表元素,值代表它們各自的多重性:

      >>> from collections import Counter >>> multiset = Counter({1, 1, 2, 3, 3, 3, 4, 4}) >>> multiset Counter({1: 1, 2: 1, 3: 1, 4: 1}) >>> multiset.keys() == {1, 2, 3, 4} True

      在這里, 的鍵multiset相當(dāng)于一個(gè) Python 集。這些值包含集合中每個(gè)元素的多重性。

      Python'Counter提供了一些附加功能,可幫助您將它們作為多集使用。例如,您可以使用元素及其多重性的映射來(lái)初始化計(jì)數(shù)器。您還可以對(duì)元素的多重性等執(zhí)行數(shù)學(xué)運(yùn)算。

      假設(shè)您在當(dāng)?shù)氐膶櫸锸杖菟ぷ鳌D阌幸欢〝?shù)量的寵物,你需要記錄每天有多少寵物被領(lǐng)養(yǎng),有多少寵物進(jìn)出收容所。在這種情況下,您可以使用Counter:

      >>> from collections import Counter >>> inventory = Counter(dogs=23, cats=14, pythons=7) >>> adopted = Counter(dogs=2, cats=5, pythons=1) >>> inventory.subtract(adopted) >>> inventory Counter({'dogs': 21, 'cats': 9, 'pythons': 6}) >>> new_pets = {"dogs": 4, "cats": 1} >>> inventory.update(new_pets) >>> inventory Counter({'dogs': 25, 'cats': 10, 'pythons': 6}) >>> inventory = inventory - Counter(dogs=2, cats=3, pythons=1) >>> inventory Counter({'dogs': 23, 'cats': 7, 'pythons': 5}) >>> new_pets = {"dogs": 4, "pythons": 2} >>> inventory += new_pets >>> inventory Counter({'dogs': 27, 'cats': 7, 'pythons': 7})

      那很整齊!現(xiàn)在,您可以使用 來(lái)記錄您的寵物Counter。請(qǐng)注意,您可以使用.subtract()和.update()來(lái)減去和添加計(jì)數(shù)或多重性。您還可以使用加法 (?+) 和減法 (?-) 運(yùn)算符。

      Counter在 Python 中將對(duì)象作為多重集還有很多事情可以做,所以繼續(xù)嘗試吧!

      將字典鏈接在一起:?ChainMap

      Python 將ChainMap多個(gè)字典和其他映射組合在一起以創(chuàng)建一個(gè)與常規(guī)字典非常相似的對(duì)象。換句話說(shuō),它需要多個(gè)映射并使它們?cè)谶壿嬌媳憩F(xiàn)為一個(gè)。

      ChainMap對(duì)象是可更新的視圖,這意味著任何鏈接映射的更改都會(huì)影響整個(gè)ChainMap對(duì)象。這是因?yàn)镃hainMap不會(huì)將輸入映射合并在一起。它保留了一個(gè)映射列表,并在該列表的頂部重新實(shí)現(xiàn)了常見的字典操作。例如,鍵查找會(huì)連續(xù)搜索映射列表,直到找到鍵為止。

      注意:查看Python 的 ChainMap:有效管理多個(gè)上下文以更深入地了解ChainMap在 Python 代碼中的使用。

      當(dāng)您使用ChainMap對(duì)象時(shí),您可以擁有多個(gè)帶有唯一鍵或重復(fù)鍵的字典。

      在任何一種情況下,都ChainMap允許您將所有字典視為一個(gè)。如果您的字典中具有唯一鍵,則可以像使用單個(gè)字典一樣訪問和更新這些鍵。

      如果您的字典中有重復(fù)的鍵,除了將您的字典作為一個(gè)來(lái)管理之外,您還可以利用映射的內(nèi)部列表來(lái)定義某種訪問優(yōu)先級(jí)。由于此功能,ChainMap對(duì)象非常適合處理多個(gè)上下文。

      例如,假設(shè)您正在開發(fā)一個(gè)命令行界面 (CLI)應(yīng)用程序。該應(yīng)用程序允許用戶使用代理服務(wù)連接到 Internet。設(shè)置優(yōu)先級(jí)是:

      命令行選項(xiàng) (?--proxy,?-p)

      用戶主目錄中的本地配置文件

      全局代理配置

      如果用戶在命令行提供代理,則應(yīng)用程序必須使用該代理。否則,應(yīng)用程序應(yīng)使用下一個(gè)配置對(duì)象中提供的代理,依此類推。這是最常見的用例之一ChainMap。在這種情況下,您可以執(zhí)行以下操作:

      >>> from collections import ChainMap >>> cmd_proxy = {} # The user doesn't provide a proxy >>> local_proxy = {"proxy": "proxy.local.com"} >>> global_proxy = {"proxy": "proxy.global.com"} >>> config = ChainMap(cmd_proxy, local_proxy, global_proxy) >>> config["proxy"] 'proxy.local.com'

      ChainMap允許您為應(yīng)用程序的代理配置定義適當(dāng)?shù)膬?yōu)先級(jí)。鍵查找搜索cmd_proxy,然后local_proxy,最后global_proxy,返回手頭鍵的第一個(gè)實(shí)例。在此示例中,用戶未在命令行提供代理,因此您的應(yīng)用程序使用local_proxy.

      通常,ChainMap對(duì)象的行為類似于常規(guī)dict對(duì)象。但是,它們具有一些附加功能。例如,它們有一個(gè).maps保存內(nèi)部映射列表的公共屬性:

      >>> from collections import ChainMap >>> numbers = {"one": 1, "two": 2} >>> letters = {"a": "A", "b": "B"} >>> alpha_nums = ChainMap(numbers, letters) >>> alpha_nums.maps [{'one': 1, 'two': 2}, {'a': 'A', 'b': 'B'}]

      實(shí)例屬性.maps使您可以訪問內(nèi)部映射列表。此列表可更新。您可以手動(dòng)添加和刪除映射、遍歷列表等。

      此外,ChainMap提供了一個(gè).new_child()方法和一個(gè).parents屬性:

      >>> from collections import ChainMap >>> dad = {"name": "John", "age": 35} >>> mom = {"name": "Jane", "age": 31} >>> family = ChainMap(mom, dad) >>> family ChainMap({'name': 'Jane', 'age': 31}, {'name': 'John', 'age': 35}) >>> son = {"name": "Mike", "age": 0} >>> family = family.new_child(son) >>> for person in family.maps: ... print(person) ... {'name': 'Mike', 'age': 0} {'name': 'Jane', 'age': 31} {'name': 'John', 'age': 35} >>> family.parents ChainMap({'name': 'Jane', 'age': 31}, {'name': 'John', 'age': 35})

      使用.new_child(),您可以創(chuàng)建一個(gè)ChainMap包含新地圖 (?son)的新對(duì)象,后跟當(dāng)前實(shí)例中的所有地圖。作為第一個(gè)參數(shù)傳遞的地圖成為地圖列表中的第一個(gè)地圖。如果您不傳遞地圖,則該方法使用空字典。

      該parents屬性返回一個(gè)ChainMap包含當(dāng)前實(shí)例中除第一個(gè)之外的所有地圖的新對(duì)象。當(dāng)您需要在鍵查找中跳過(guò)第一個(gè)映射時(shí),這很有用。

      最后一個(gè)要強(qiáng)調(diào)的功能ChainMap是變異操作,例如更新鍵、添加新鍵、刪除現(xiàn)有鍵、彈出鍵和清除字典,作用于內(nèi)部映射列表中的第一個(gè)映射:

      >>> from collections import ChainMap >>> numbers = {"one": 1, "two": 2} >>> letters = {"a": "A", "b": "B"} >>> alpha_nums = ChainMap(numbers, letters) >>> alpha_nums ChainMap({'one': 1, 'two': 2}, {'a': 'A', 'b': 'B'}) >>> # Add a new key-value pair >>> alpha_nums["c"] = "C" >>> alpha_nums ChainMap({'one': 1, 'two': 2, 'c': 'C'}, {'a': 'A', 'b': 'B'}) >>> # Pop a key that exists in the first dictionary >>> alpha_nums.pop("two") 2 >>> alpha_nums ChainMap({'one': 1, 'c': 'C'}, {'a': 'A', 'b': 'B'}) >>> # Delete keys that don't exist in the first dict but do in others >>> del alpha_nums["a"] Traceback (most recent call last): ... KeyError: "Key not found in the first mapping: 'a'" >>> # Clear the dictionary >>> alpha_nums.clear() >>> alpha_nums ChainMap({}, {'a': 'A', 'b': 'B'})

      這些示例表明對(duì)ChainMap對(duì)象的變異操作僅影響內(nèi)部列表中的第一個(gè)映射。這是您在使用ChainMap.

      棘手的部分是,乍一看,似乎可以改變給定ChainMap.?但是,您只能.maps更改第一個(gè)映射中的鍵值對(duì),除非您使用直接訪問和更改列表中的其他映射。

      定制的內(nèi)置插件:UserString,UserList,和UserDict

      有時(shí)您需要自定義內(nèi)置類型,例如字符串、列表和字典,以添加和修改某些行為。從Python 2.2 開始,您可以通過(guò)直接對(duì)這些類型進(jìn)行子類化來(lái)實(shí)現(xiàn)。但是,您可能會(huì)遇到這種方法的一些問題,稍后您將看到。

      Pythoncollections提供了三個(gè)方便的包裝類來(lái)模擬內(nèi)置數(shù)據(jù)類型的行為:

      UserString

      UserList

      UserDict

      結(jié)合常規(guī)方法和特殊方法,您可以使用這些類來(lái)模仿和自定義字符串、列表和字典的行為。

      如今,開發(fā)人員經(jīng)常問自己是否有理由使用UserString,?UserList, 以及UserDict何時(shí)需要自定義內(nèi)置類型的行為。答案是肯定的。

      內(nèi)置類型的設(shè)計(jì)和實(shí)現(xiàn)考慮到了開閉原則。這意味著它們對(duì)擴(kuò)展開放,但對(duì)修改關(guān)閉。允許修改這些類的核心特性可能會(huì)破壞它們的不變量。因此,Python 核心開發(fā)人員決定保護(hù)它們免受修改。

      例如,假設(shè)您需要一個(gè)在插入鍵時(shí)自動(dòng)將鍵小寫的字典。您可以子類化dict和覆蓋,.__setitem__()以便每次插入鍵時(shí),字典都會(huì)小寫鍵名:

      >>>

      >>> class LowerDict(dict): ... def __setitem__(self, key, value): ... key = key.lower() ... super().__setitem__(key, value) ... >>> ordinals = LowerDict({"FIRST": 1, "SECOND": 2}) >>> ordinals["THIRD"] = 3 >>> ordinals.update({"FOURTH": 4}) >>> ordinals {'FIRST': 1, 'SECOND': 2, 'third': 3, 'FOURTH': 4} >>> isinstance(ordinals, dict) True

      當(dāng)您使用帶有方括號(hào) (?[]) 的字典樣式分配插入新鍵時(shí),此字典可以正常工作。但是,當(dāng)您將初始字典傳遞給類構(gòu)造函數(shù)或使用.update().?這意味著您需要覆蓋.__init__()、.update()和其他一些方法才能使您的自定義字典正常工作。

      現(xiàn)在看看同一個(gè)字典,但UserDict用作基類:

      >>>

      >>> from collections import UserDict >>> class LowerDict(UserDict): ... def __setitem__(self, key, value): ... key = key.lower() ... super().__setitem__(key, value) ... >>> ordinals = LowerDict({"FIRST": 1, "SECOND": 2}) >>> ordinals["THIRD"] = 3 >>> ordinals.update({"FOURTH": 4}) >>> ordinals {'first': 1, 'second': 2, 'third': 3, 'fourth': 4} >>> isinstance(ordinals, dict) False

      有用!您的自定義字典現(xiàn)在會(huì)將所有新鍵轉(zhuǎn)換為小寫字母,然后再將它們插入字典中。請(qǐng)注意,由于您不dict直接繼承自,因此您的類不會(huì)返回dict上面示例中的實(shí)例。

      UserDict將常規(guī)字典存儲(chǔ)在名為 的實(shí)例屬性中.data。然后它圍繞該字典實(shí)現(xiàn)所有方法。UserList并UserString以相同的方式工作,但它們的.data屬性分別包含 alist和一個(gè)str對(duì)象。

      如果您需要自定義這些類中的任何一個(gè),那么您只需要覆蓋適當(dāng)?shù)姆椒ú⒏鶕?jù)需要更改它們的操作。

      通常,當(dāng)您需要一個(gè)與底層包裝的內(nèi)置類幾乎相同的類并且您想要自定義其標(biāo)準(zhǔn)功能的某些部分時(shí),您應(yīng)該使用UserDict,?UserList, 和UserString。

      使用這些類而不是內(nèi)置的等效類的另一個(gè)原因是訪問底層.data屬性以直接操作它。

      從內(nèi)置類型直接在很大程度上取代了使用的能力,繼承UserDict,UserList以及UserString。然而,內(nèi)置類型的內(nèi)部實(shí)現(xiàn)使得在不重寫大量代碼的情況下很難安全地繼承它們。在大多數(shù)情況下,使用來(lái)自collections.?它會(huì)讓你免于幾個(gè)問題和奇怪的行為。

      結(jié)論

      在 Python 的collections模塊中,您有幾種專門的容器數(shù)據(jù)類型,可用于解決常見的編程問題,例如計(jì)數(shù)對(duì)象、創(chuàng)建隊(duì)列和堆棧、處理字典中丟失的鍵等等。

      中的數(shù)據(jù)類型和類collections被設(shè)計(jì)為高效和 Pythonic。它們對(duì)您的 Python 編程之旅非常有幫助,因此學(xué)習(xí)它們非常值得您花時(shí)間和精力。

      在本教程中,您學(xué)習(xí)了如何:

      使用編寫可讀和顯式的代碼namedtuple

      建立高效的隊(duì)列和堆棧使用deque

      使用有效地計(jì)數(shù)對(duì)象Counter

      處理缺少字典鍵與defaultdict

      記住鍵的插入順序OrderedDict

      在一個(gè)視圖中鏈接多個(gè)字典ChainMap

      您還了解了三種簡(jiǎn)便的包裝類:UserDict,UserList,和UserString。這些類是方便當(dāng)你需要?jiǎng)?chuàng)建一個(gè)模仿的行為內(nèi)置類型的自定義類dict,list和str。

      Python 容器 數(shù)據(jù)結(jié)構(gòu)

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請(qǐng)聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請(qǐng)聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。

      上一篇:微軟OneNote客戶預(yù)覽版學(xué)習(xí)工具下載(暫未上線):教學(xué)好幫手
      下一篇:Excel工作表選擇單元格相關(guān)操作技巧(Excel表格單元格選擇)
      相關(guān)文章
      亚洲丰满熟女一区二区v| 国产精品亚洲色婷婷99久久精品| 国产亚洲视频在线观看| 亚洲日韩乱码久久久久久| 在线免费观看亚洲| 日韩亚洲人成在线综合日本| 久久久久亚洲精品男人的天堂| 亚洲国产小视频精品久久久三级| 久久亚洲色WWW成人欧美| 2017亚洲男人天堂一| 亚洲无吗在线视频| 亚洲人成网站日本片| 国产精品亚洲午夜一区二区三区| 亚洲国产精品专区| 亚洲国产视频一区| 精品久久亚洲中文无码| 亚洲av午夜精品无码专区| 日韩亚洲国产高清免费视频| 中文字幕乱码亚洲无线三区| 国产精品亚洲一区二区麻豆| 亚洲综合无码一区二区痴汉| 亚洲色大成网站www永久男同| 亚洲国产欧美国产综合一区| 亚洲αⅴ无码乱码在线观看性色| 亚洲欧好州第一的日产suv| 亚洲AV日韩AV永久无码色欲| 日韩精品亚洲专区在线观看| 亚洲精品A在线观看| 亚洲色大成网站www永久一区| 亚洲AV无码一区二区三区系列| 亚洲国语精品自产拍在线观看| 久久精品国产亚洲AV高清热 | 亚洲最新视频在线观看| 久久精品蜜芽亚洲国产AV| 1区1区3区4区产品亚洲| www.亚洲日本| 理论亚洲区美一区二区三区| 亚洲日韩涩涩成人午夜私人影院| 亚洲乱码中文字幕综合| 亚洲欧洲第一a在线观看| 亚洲一区在线观看视频|