Python實用技法第17篇:將名稱映射到序列的元素中

上一篇文章: Python實用技法第16篇:從字典中提取子集
下一篇文章: Python實用技法第18篇:同時對數據作轉換和換算

一、需求🙀

咱們的代碼是經過位置(即索引或下標)來訪問列表會元組的,但有時候這會讓代碼變得有些難以閱讀。咱們但願能夠經過名稱來訪問元素,以此減小結構中對位置的依賴性。

二、解決方案😸

相比普通的元組,collections.namedtuple()(命名元組)只增長了極少的開銷就提供了這些便利。實際上collections.namedtuple()是一個工廠方法,它返回的是Python中標準元組類型的子類。咱們提供給它一個類型名稱以及相應的字段,它就返回一個可實例化的類、爲你已經定義好的字段傳入值等。數據庫

from collections import namedtuple
Subscriber=namedtuple('Subsciber',['addr','joined'])
sub=Subscriber("1782980833@qq.com","2018-10-23")

print(sub)
print(sub.addr)
print(sub.joined)

print(len(sub))
addr,joined=sub
print(addr)
print(joined)

#下面錯誤,由於namedtuple是不可變的
#sub.joined="2019"

結果:segmentfault

Subsciber(addr='1782980833@qq.com', joined='2018-10-23')
1782980833@qq.com
2018-10-23
2
1782980833@qq.com
2018-10-23

儘管namedtuple的實例看起來就像一個普通的類實例,但它的實例與普通的元組是可互換的,並且支持全部普通元組所支持的操做。數組

命名元組的主要做用在於將代碼同它所控制的元素位置間解耦。因此,若是從數據庫調用中獲得了一個大型的元組列表,並且經過元素的位置來訪問元素,那麼假如在表單中新增了一列數據,那麼代碼就會崩潰,但若是首先將返回的元組轉換爲命名元組,就不會出現問題。數據結構

爲了說明這個問題,下面有一些使用普通元組的代碼:設計

def compute_cost(records):
    total=0.0
    for rec in records:
        total+=rec[1]*rec[2]
    return total

經過位置來引用元素經常使得代碼的表達力不夠強,並且也很依賴於記錄的具體結構。code

下面是使用命名元組的版本:索引

from collections import namedtuple
Stock=namedtuple('Stock',['name','shares','price'])
def compute_cost(records):
    total=0.0
    for rec in records:
        s=Stock(*rec)
        total+=s.shares*s.price
    return total

三、分析😈

namedtuple的一種可能用法是做爲字典的替代,後者須要更多的空間來存儲。所以,若是要構建設計字典的大型數據,使用namedtuple會更加高效,可是請注意,與字典不一樣的是,namedtuple是不可變的。ci

若是須要修改任何屬性,能夠經過使用namedtuple實例_replace()方法來實現。該方法會建立一個全新的命名元組,並對相應的值作替換。get

from collections import namedtuple
Subscriber=namedtuple('Subsciber',['addr','joined'])
sub=Subscriber("1782980833@qq.com","2018-10-23")

print(sub)

sub=sub._replace(joined="2018-10-24")
print(sub)

結果:原型

Subsciber(addr='1782980833@qq.com', joined='2018-10-23')
Subsciber(addr='1782980833@qq.com', joined='2018-10-24')

_replace()方法有一個微妙的用途,那就是它能夠做爲一種簡單的方法填充具備可選或缺失字段的命名元組。要作到這點,首先建立一個包含默認值得原型數組,而後使用_replace()方法建立一個新的實例,把相應的值替換掉。

from collections import namedtuple
Subscriber=namedtuple('Subsciber',['addr','joined','age'])
sub=Subscriber("",None,0)

def dict_to_stock(s):
    return sub._replace(**s)

a={"addr":"111111@qq.com","joined":"1111-11-11","age":11}
a=dict_to_stock(a)
print(a)

b={"addr":"111111@qq.com","joined":"1111-11-11"}
b=dict_to_stock(b)
print(b)

結果:

Subsciber(addr='111111@qq.com', joined='1111-11-11', age=11)
Subsciber(addr='111111@qq.com', joined='1111-11-11', age=0)

最後,也是至關重要的是,應該要注意若是咱們的目標是定義一個高效的數據結構,並且未來會修改各類實例屬性,那麼使用namedtuple並非最佳選擇,相反,能夠考慮頂一個使用了__slots__屬性的類。

上一篇文章: Python實用技法第16篇:從字典中提取子集
下一篇文章: Python實用技法第18篇:同時對數據作轉換和換算
相關文章
相關標籤/搜索