Python Cookbook-5.14 給字典類型增加排名功能

任務

你需要用字典存儲一些鍵和“分數”的映射關系。你經常需要以自然順序(即以分數的升序)訪問鍵和分數值,并能夠根據那個順序檢查一個鍵的排名。對這個問題,用dict 似乎不太合適。

解決方案

我們可以使用 dict 的子類,根據需要增加或者重寫一些方法。在我們使用多繼承、將UserDict.DictMixin 放置在基類 dict、并仔細安排各種方法的委托或重寫之前,我們可以設法獲得一種美妙的平衡,既擁有極好的性能又避免了編寫一些冗余代碼。

我們可以在文檔字符串中加入很多示例,還可以用標準庫的 doctest 模塊來提供單元測試的功能,這也能夠確保我們在文檔字符串中編寫的例子的準確性:

#!/usr/bin/env python
'''一個反映鍵到分數的映射的字典'''
from bisect import bisect_left,insort_left
import UserDict
class Ratings(UserDict.DictMixin,dict):'''Ratings類很像一個字典,但有一些額外特性:每個鍵的對應值都是該鍵的“分數”,所有鍵都根據它們的分數排名。對應值必須是可以比較的,同樣,鍵則必須是可哈希的(即可以“綁”在分數上)所有關于映射的行為都如同預期一樣,比如:>>>r = Ratings({"bob":30,"john":30})>>>len(r)2>>>r.has_key("paul"),"paul" in r(False,False)>>>r["john"] = 20r.update({"paul":20,"tom":10})>>>len(r)4>>>r.has_key("paul"),"paul" in r(True,True)>>>[r[key} for key in ["bob","paul","john","tom"]][30,20,20,10]>>>r.get("nobody"),r.get("nobody",0)(None,0)除了映射的接口,我們還提供了和排名相關的方法。r.rating(key)返回了某個鍵的排名,其中排名為0的是最低的分數(如果兩個鍵的分數相同,則直接比較它們兩者,“打破僵局”,較小的鍵排名更低):>>>[r.rating(key) for key in ["bob","paul","john","tom"]][3,2,1,0]getValueByRating(ranking)和getKeyByRating(ranking)對于給定的排名索引,分別返回分數和鍵:>>>[r.getValueByRating(rating) for rating in range(4)][10,20,20,30]>>>[r.getKeyByRating(rating) for rating in range(4)]['tom','john','paul','bob']一個重要的特性是keys()返回的鍵是以排名的升序排列的,而其他所有返回的相關的列表或迭代器都遵循這個順序:>>> r.keys()['tom','john','paul','bob']>>>[key for key in r]['tom','john','paul','bob']>>> [key for key in r.iterkeys()]['tom','john','paul','bob']>>> r.values()[10,20,20,30]>>>[value for value in r.itervalues()][10,20,20,30]>>> r.items()[('tom',10),('john',20),('paul',20),('bob',30)]>>>[item for item in r.iteritems()][('tom',10),('john',20),('paul',20),('bob',30)]實例可以被修改(添加、改變和刪除鍵-分數對應關系)而且實例的每個方法都反映了實例的當前狀態:>>>r["tom"] = 100>>> r.items()[('john',20),('paul',20),('bob',30),('tom',100)]>>>del r["paul"]>>>r.items()[('john',20),('bob',30),('tom',100)]>>>r["paul"] = 25>>>r.items()[('john',20),('paul',25),('bob',30),('tom',100)]>>>r.clear()>>>r.items()[  ]''''''這個實現小心翼翼地混合了繼承和托管,因此在盡量減少冗余代碼的前提下獲得了不錯的性能,當然,同時也保證了語義的正確性。所有未被實現的映射方法都通過繼承來獲得,大多來自DictMixin,但關鍵的__getitem__來自 dict。'''def init(self,*args,**kwds):'''這個類就像dict一樣被實例化'''dict.__init__(self,*args,**kwds)#self._rating是關鍵的輔助數據結構:一個所有(值,鍵)#的列表,并保有一種“自然的”排序狀態self._rating =[ (v,k) for k,v in dict.iteritems(self)]self._rating.sort()def copy(self):'''提供一個完全相同但獨立的拷貝'''return Ratings(self)def __setitem__(self,k,y):'''除了把主要任務委托給dict,我們還維護self._rating'''if k in self:del self._rating[self.rating(k)]dict.__setitem__(self,k,v)insort_left(self._rating,(v,k))def __delitem__(self,k):'''除了把主要任務委托給dict,我們還維護self._rating'''del self._rating[self.rating(k)]dict.__delitem__(self,k)'''顯式地將某些方法委托給dict的對應方法,以免繼承了DictMixin的較慢的(雖然功能正確)實現'''__len__ = dict.__len____contains__ = dict.__contains__has_key = __contains__'''在self._rating和self.keys()之間的關鍵的語義聯系————DictMixin“免費”給了我們所有其他方法,雖然我們直接實現它們能夠獲得稍好一點的性能。'''def __iter__(self):for v,k in self._rating:yield kiterkeys = __iter__def keys(self):return list(self)'''三個和排名相關的方法'''def rating(self,key):item = self[key],keyi = bisect_left(self._rating,item)if item == self._rating[i]:return iraise LookupError,"item not found in rating"def getValueByRating(self,rating):return self._rating[rating][0]def getKeyByRating(self,rating):return self.rating[rating][1]
def _test():'''我們使用doctest來測試這個模塊,模塊名必須為rating.py,這樣docstring中的示例才會有效'''import doctest,ratingdoctest.testmod(rating)
if __name__ == "__main__":_test()

討論

在很多方面,字典都是很自然地被應用于存儲鍵(比如,競賽中參與者的名字)和“分數”(比如參與者獲得的分數,或者參與者在拍賣中的出價)的對應關系的數據結構。如果我們希望在這些應用中使用字典,我們可能會希望以自然的順序訪間–即鍵對應的“分數”的升序——我們也希望能夠迅速獲得基于當前分數的排名(比如,參與者現在排在第三位,排在第二位的參與者的分數,等等)。

為了達到這個目的,本節給dict的子類增加了一些它本身完全不具備的功能(rating方法、getValueByRating、getKeyByRating),同時,最關鍵和巧妙的地方是,我們修改了keys方法和其他相關的方法,這樣它們就能返回按照指定順序排列的列表或者可選代對象(比如按照分數的升序排列,對于兩個有同樣分數的鍵,我們繼續比較鍵本身)。大多數的文檔都放在類的文檔字符串中——保留文檔和示例是很重要的,可以用Python 標準庫的 doctest模塊來提供單元測試的功能,以確保給出的例子是正確的。

關于這個實現的有趣之處是,它很關心消除冗余(即那些重復和令人厭煩的代碼,很可能滋生 bug),但同時沒有損害性能。Ratings 類同時從 dict 和 DictMixin 繼承,并把后者排在基類列表的第一位,因此,除非明確地覆蓋了基類的方法,Ratings 的方法基本來自于 DictMixin,如果它提供了的話。

Raymond Hettinger 的 DictMixin 類最初是發布在 Python Cookbook 在線版本中的一個例子,后來被吸收到了 Python2.3的標準庫中。DictMixin 提供了各種映射的方法,除了__init__
、copy以及四個基本方法:__getitem__、__setitem__、__delitem__和 keys。如果需要的是一個映射類并且想要支持完整映射所具有的各種方法,可以從DictMixin派生子類,并且提供那些基本的方法(具體依賴于你的類的語義————比如,如果你的類有不可修改的實例,你無須提供屬性設置方法__setitem__和__delitem__)。還可以添加一些可選的方法以提升性能,覆蓋 DictMixin 所提供的原有方法。整個 DictMixin 的架構可以被看做是一個經典的模板方法設計模式(Template Method Design Pattern),它用一種混合的變體提供了廣泛的適用性。

在本節的類中,從基類繼承了__getitem__(準確地說,是從內建的dict類型繼承),出于性能上的考慮,我們把能委托的都委托給了dict。我們必須自己實現基本的屬性設置方法(__setitem__和__delitem__),因為除了委托給基類的方法,還需要維護一個數據結構 self._rating——這是一個列表,包含了許多(score,key)值對,此列表在標準庫模塊 bisect 的幫助下完成了排序。我們也重新實現了keys(在這個步驟中,還重新實現了__iter__,即 iterkeys,很明顯,借助__iter__可以更容易地實現 keys)來利用self._rating 并按照我們需要的順序返回鍵。最后,除了上面三個和排名有關的方法,我們又為__init__和 copy 添加了實現。

這個結果是一個很有趣的例子,它取得了簡潔和清晰的平衡,并最大化地重用了 Python標準庫的眾多功能。如果你在應用程序中使用這個模塊,測試結果可能會顯示,本節的類從 DictMixin 繼承來的方法的性能不是太讓人滿意,畢競 DictMixin 的實現是基于必要的通用性的考慮。如果它的性能不能滿足你的要求,可以自己提供一個實現來獲取最高性能。假設有個Ratings類的實例r,你的應用程序需要對r.iteritems()的結果進行大量的循環處理,可以給類的主體部分增加這個方法的實現以獲得更好的性能:

def iteritems(self):for v,k in self._rating:yield k,v

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/901195.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/901195.shtml
英文地址,請注明出處:http://en.pswp.cn/news/901195.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

十四種邏輯器件綜合對比——《器件手冊--邏輯器件》

目錄 邏輯器件 簡述 按功能分類 按工藝分類 按電平分類 特殊功能邏輯器件 應用領域 詳盡闡述 1 邏輯門 一、基本概念 二、主要類型 三、實現方式 四、應用領域 2 反相器 工作原理 基本功能 主要應用 常見類型 特點 未來發展趨勢 3 鎖存器 基本概念 工作原理 主要類型…

如何更改wsl2中的ubuntu默認安裝位置

先前的一篇文章提到了如何更改wsl里面ubuntu的home目錄,wsl裝ubuntu的home目錄在哪,如何更改home?_wsl安裝的ubuntu在哪里-CSDN博客 這次是要更改wsl中ubuntu的安裝目錄,畢竟默認安裝到c盤下會占用不少空間的。 從微軟商店get后…

最近在工作中感受到了設計模式的重要性

之前了解設計模式:只是應付一下面試 在之前一年多的工作中也沒遇到使用場景 最近在搭建驗證環境的時候,才發現這玩意這么重要 首先是設計模式的使用場景一定是在很復雜繁瑣的場景下進行的 之所以說是復雜/繁瑣的場景,因為一些場景也許邏輯不難…

Python深度學習基礎——卷積神經網絡(CNN)(PyTorch)

CNN原理 從DNN到CNN 卷積層與匯聚 深度神經網絡DNN中,相鄰層的所有神經元之間都有連接,這叫全連接;卷積神經網絡 CNN 中,新增了卷積層(Convolution)與匯聚(Pooling)。DNN 的全連接…

Linux 第三講 --- 基礎指令(三)

前言: 在前面我們已經講了有十幾個Linux的基礎指令,今天我們再補充幾個常用的基礎指令,為后面的學習做準備 。 目錄 前言: 一、兩個與時間相關的指令 1.date指令 演示 : 時間戳 設置時間 2、cal指令 演示&#x…

基于SiamFC的紅外目標跟蹤

基于SiamFC的紅外目標跟蹤 1,背景與原理2,SiamFC跟蹤方法概述2.1 核心思想2.2 算法優勢3,基于SiamFC的紅外跟蹤代碼詳解3.1 網絡定義與交叉相關模塊3.2 SiamFC 跟蹤器實現3.3 主程序:利用 OpenCV 實現視頻跟蹤4,總結與展望在紅外監控、無人機防御以及低光照場景中,紅外圖…

Odoo 部署本地 把現時的excel計算表格部署上odoo 教程

要將現有的 Excel 計算表格部署到 Odoo 平臺上,您可以按照以下步驟進行操作: 將 Excel 表格中的數據轉移到 Odoo 模塊中:首先,您需要將 Excel 表格中的數據導出為 CSV 格式,然后可以使用 Odoo 的數據導入功能將這些數據…

KWDB創作者計劃—KWDB認知引擎:數據流動架構與時空感知計算的范式突破

引言:數據智能的第三范式 在數字化轉型進入深水區的2025年,企業數據系統正面臨三重悖論:數據規模指數級增長與實時決策需求之間的矛盾、多模態數據孤島與業務連續性要求之間的沖突、靜態存儲范式與動態場景適配之間的鴻溝。KWDB(K…

C語言 數據結構 【棧】動態模擬實現

引言 動態模擬實現棧的各個接口 一、棧的概念與結構 棧:一種特殊的線性表,其只允許在固定的一端進行插入和刪除元素操作。進行數據插入和刪除操作的一端稱為棧頂,另一端稱為棧底。棧中的數據元素遵守后進先出LIFO(LastInFirstOut…

Python itertools模塊的groupby函數介紹

itertools.groupby 是 Python 標準庫 itertools 模塊中的一個函數,它的主要功能是對可迭代對象中相鄰的相同元素進行分組。 itertools.groupby(iterable, keyNone) 函數 作用: 將連續的(相鄰的)相同元素分組,返回 (…

Python實例題:使用Python生成分形圖片

目錄 Python實例題 題目 題目分析 需求理解 關鍵知識點 實現思路分析 代碼實現 代碼解釋 mandelbrot 函數: 設置復平面區域和圖像參數: 計算分形數據: 繪圖展示: 運行思路 Python實例題 題目 使用Python生成分形圖…

系統編程1(進程的概念與原理)

進程的概念與原理 計算機組成部分一般遵循馮諾依曼結構,也就是由控制器、運算器、存儲器、輸入設備、輸出設備五個部分組成。 ? 程序的編譯 一般在編寫出程序之后,并不能直接運行,而是需要把程序通過編譯器進行編譯,生成可執行…

《Vue Router實戰教程》5.嵌套路由

歡迎觀看《Vue Router 實戰(第4版)》視頻課程 嵌套路由 一些應用程序的 UI 由多層嵌套的組件組成。在這種情況下,URL 的片段通常對應于特定的嵌套組件結構,例如: 通過 Vue Router,你可以使用嵌套路由配置…

使用Python解決Logistic方程

引言 在數學和計算機科學中,Logistic 方程是描述人口增長、傳播過程等現象的一種常見模型。它通常用于表示一種有限資源下的增長過程,比如動物種群、疾病傳播等。本文將帶領大家通過 Python 實現 Logistic 方程的求解,幫助你更好地理解這一經典數學模型。 1.什么是 Logist…

《從零搭建Vue3項目實戰》(AI輔助搭建Vue3+ElemntPlus后臺管理項目)零基礎入門系列第十二篇(完結篇):數據統計功能實現

🤟致敬讀者 🟩感謝閱讀🟦笑口常開🟪生日快樂?早點睡覺 📘博主相關 🟧博主信息🟨博客首頁🟫專欄推薦🟥活動信息 文章目錄 《從零搭建Vue3項目實戰》(AI輔助…

研究嵌入式軟件架構時遇到的初始化堆棧溢出問題

文章目錄 2025年4月10日新增分析PC寄存器指針值排查問題map文件設計到的知識點1. **.bss 段(Block Started by Symbol)**2. **.data 段**3. **.text 段**4. **.heap 段**5. **.stack 段**6. **.rodata 段(只讀數據段)**7. **.init…

軟件架構評估兩大法:ATAM 和 SAAM 的對比與實踐

架構權衡分析方法(ATAM)和軟件架構分析方法(SAAM)是軟件架構評估領域中非常重要的兩種方法,以下為你詳細介紹: 一、架構權衡分析方法(ATAM) 1.背景與起源:ATAM 是由卡耐…

Python爬蟲-爬取全球股市漲跌幅和漲跌額數據

前言 本文是該專欄的第52篇,后面會持續分享python爬蟲干貨知識,記得關注。 本文中,筆者將基于Python爬蟲,實現批量采集全球股市行情(亞洲,美洲,歐非,其他等)的各股市“漲跌幅”以及“漲跌額”數據。 具體實現思路和詳細邏輯,筆者將在正文結合完整代碼進行詳細介紹。…

電流互感器的兩相星形接線的建模與仿真

微?“電擊小子程高興的MATLAB小屋”獲取巨額優惠 1.模型簡介 本仿真模型基于MATLAB/Simulink(版本MATLAB 2016Rb)軟件。建議采用matlab2016 Rb及以上版本打開。(若需要其他版本可聯系代為轉換) 2.仿真模型 3.仿真結果 3.1一次…

詳解 kotlin 相對 Java 特有的關鍵字及使用

文章目錄 1. val 和 var2. fun3. when4. is 和 !is5. lateinit6. by7. reified8. companion 本文首發地址:https://h89.cn/archives/366.html 最新更新地址:https://gitee.com/chenjim/chenjimblog Kotlin 在兼容Java的基礎上,引入了許多特有…