命名元組:namedtuple,是Python語言裏沒有引發足夠重視的一種數據類型。這是Python中容易被忽略的神奇功能之一。數據結構
當須要定義一個類時,namedtuple是一個很好的選擇。函數
那麼命名元組以及它有什麼特性?咱們能夠把namedtuples看做是Python內置的元組數據類型的擴展。對象
Python的元組是一種用於對任意對象進行分組的簡單數據結構。元組的內容是不可變的,一旦被建立,數據元素就不能被修改。以下:索引
元組有一個缺點,存儲在其中的數據只能經過索引來訪問。你不能對存儲在元組中的單個屬性進行命名。這會影響代碼的可讀性。
並且,元組一般是一個ad-hoc結構。你很難確保兩個元組存儲有相同數量的字段和相同的屬性。這使得當混合字段順序時很容易引入「slip-of-the-mind」的bug。接口
Namedtuples主要用來解決以下兩個問題。ip
首先,namedtuples和常規元組同樣,它的內容是不可改變的。 一旦你將數據存儲在其中,就不能再修改。內存
除此以外,命名元組也是,命名的元組。能夠經過惟一的標識符來訪問存儲在其中的對象。您沒必要記住元素的下標索引,也沒必要爲了記憶方便把索引定義爲常量。字符串
一個典型的命名元組以下所示:it
使用命名元組前須要先導入collections模塊。Python 2.6的標準庫中即包含。在上面的例子裏,定義了一個簡單的命名元組數據類型:「Car」,包含「color」 和「mileage」兩個字段。io
也許你你會發現上面的語法有一點怪:爲何咱們把兩個字段寫爲一個字符串「color mileage」?
答案是由於命名元組的工廠函數會在字段字符串後默認調用split()函數對字段進拆解。因此上面的寫法就是下面寫法的快捷方式:
也能夠直接把字段寫成列表形式。這樣寫的優勢是,把字段使用多行分隔,利於代碼格式化。
接下來可使用「Car」的工廠函數建立"car"對象了,就建立一個類對象「Car」,而且建立了參數值爲「color」 和「mileage」的構造函數。
元組的解包以及帶有*函數參數的解包也可正常工做。
命名元組中元素的便可以經過ID來訪問,也能夠經過其索引來訪問。這樣命名元組能夠直接替代常規的元組。
命名元組的輸出甚至能夠是一個標準的字符串表達式,以下,這樣省去了很多的輸入冗餘。
像元組同樣,命名元組的內容也是不可修改的。當你試圖重寫其中字段值時,系統會拋出AttributeError異常:
在Python內部,命名元組是經過一個常規的類對象實現的。可是在內存使用效率上比常規類要高,和正常元組同樣。
你能夠把命名元組看作是一個自定義的不可修改的類的快捷方式,可是更節約內存。
由於命名元組是在常規類的基礎上構建的,因此也能夠添加方法到命名元組的類中。舉個例子,你經過能夠添加方法和屬性擴展這個類,和擴展常規的類同樣。例子以下:
咱們能夠建立對象MyCarWithMethods,而且定義一個 hexcolor()方法,結果以下
這個方法可能看起來有點笨拙。可是當你想獲得一個不可修改的類時能夠這麼試一下。可是注意別搬起石頭砸了本身的腳!
舉個例子,因爲命名元組的內部構建機制,添加一個新的不可改變的字段是比較麻煩的。最簡單的方法就是利用基本元組的._field屬性。
結果以下:
除了._fields屬性,每一個命名元組實例還內置了一些很是有用的幫助函數。這些函數都如下劃線開頭,一般用下劃線開頭表示它們是私有的方法或者屬性,不屬於類或者模塊的公共接口。
在命名元組中這些如下劃線命名的函數方法則有不一樣的含義:這些幫助函數或者屬性是命名元組公共接口的一部分。之因此這麼命名是爲了不和用戶自定義的元組字段衝突。您能夠隨意使用這些幫助函數。
下面我會給你們展現一些十分有用的命名元組的幫助函數,咱們以 _asdict() 函數爲例,此函數返回值是一個字典,字典內容是命名元組中存儲的元素,以下:
當你使用JSON樣式的輸出時,這個函數能避免輸入錯誤,至關有用,舉例以下:
另外一個有用的幫助函數是 _replace() ,它會生成當前元組的一個副本(淺拷貝),而且容許用戶對其中字段進行選擇性替換。
最後,_make()類方法能夠用來在序列或者迭代中建立一個新的命名元組實例,以下:
命名元組是使代碼變得簡潔有效的一個簡單快速的方法。它經過更好的結構化數據也加強了代碼的可讀性。
舉個例子,我發現把有混合數據的字典這樣的 ad-hoc數據類型用命名元組來代替,可以更清楚的表達個人意圖。當我把數據做爲命名元組重構時,代碼中面臨的一些問題,總能找到意想不到的解決辦法。
使用命名元組處理非結構化的元組和字典,也會讓個人同事們工做變的輕鬆,由於函數直接傳遞的數據是「自解釋的」,很是容易理解(在某種程度上)。
另外一方面,若是命名元組沒法使您的代碼變得更簡潔,更易讀,可維護性更高,我就不建議使用它們。由於「一件事太好的話可能就是壞事了」。
謹慎的使用命名元組的話,無疑會使您的代碼更好,更富有表現力。
collection.namedtuple,是一個自定義的不可修改的類的快捷方式,可是更節約內存。
命名元組經過更容易讓人理解的方式結構化您的數據,使您的代碼更乾淨整潔。
命名元組提供了一些十分有用的如下劃線開頭幫助函數,您能夠放心使用它們。