《Python Cookbook 3rd》笔记(1.18):映射名称到序列元素
映射名稱到序列元素
問(wèn)題
你有一段通過(guò)下標(biāo)訪問(wèn)列表或者元組中元素的代碼,但是這樣有時(shí)候會(huì)使得你的代碼難以閱讀,于是你想通過(guò)名稱來(lái)訪問(wèn)元素。
解法
collections.namedtuple() 函數(shù)通過(guò)使用一個(gè)普通的元組對(duì)象來(lái)幫你解決這個(gè)問(wèn)題。這個(gè)函數(shù)實(shí)際上是一個(gè)返回 Python 中標(biāo)準(zhǔn)元組類型子類的一個(gè)工廠方法。你需要傳遞一個(gè)類型名和你需要的字段給它,然后它就會(huì)返回一個(gè)類,你可以初始化這個(gè)類,為你定義的字段傳遞值等。代碼示例:
>>> from collections import namedtuple >>> Subscriber = namedtuple('Subscriber', ['addr', 'joined']) >>> sub = Subscriber('jonesy@example.com', '2012-10-19') >>> sub Subscriber(addr='jonesy@example.com', joined='2012-10-19') >>> sub.addr 'jonesy@example.com' >>> sub.joined '2012-10-19' >>>盡管 namedtuple 的實(shí)例看起來(lái)像一個(gè)普通的類實(shí)例,但是它跟元組類型是可交換的,支持所有的普通元組操作,比如索引和拆分。比如:
>>> len(sub) 2 >>> addr, joined = sub >>> addr 'jonesy@example.com' >>> joined '2012-10-19' >>>命名元組的一個(gè)主要用途是將你的代碼從下標(biāo)操作中解脫出來(lái)。因此,如果你從數(shù)據(jù)庫(kù)調(diào)用中返回了一個(gè)很大的元組列表,通過(guò)下標(biāo)去操作其中的元素,當(dāng)你在表中添加了新的列的時(shí)候你的代碼可能就會(huì)出錯(cuò)了。但是如果你使用了命名元組,那么就不會(huì)有這樣的顧慮。(避免魔數(shù))
為了說(shuō)明清楚,下面是使用普通元組的代碼:
def compute_cost(records): total = 0.0 for rec in records:total += rec[1] * rec[2] return total下標(biāo)操作通常會(huì)讓代碼表意不清晰,并且非常依賴記錄的結(jié)構(gòu)。下面是使用命名元組的版本:
from collections import namedtupleStock = namedtuple('Stock', ['name', 'shares', 'price'])def compute_cost(records):total = 0.0for rec in records:s = Stock(*rec)total += s.shares * s.pricereturn total討論
命名元組另一個(gè)用途就是作為字典的替代,因?yàn)樽值浯鎯?chǔ)需要更多的內(nèi)存空間(節(jié)省空間)。如果你需要構(gòu)建一個(gè)非常大的包含字典的數(shù)據(jù)結(jié)構(gòu),那么使用命名元組會(huì)更加高效。但是需要注意的是,不像字典那樣,一個(gè)命名元組是不可更改的。比如:
>>> s = Stock('ACME', 100, 123.45) >>> s Stock(name='ACME', shares=100, price=123.45) >>> s.shares = 75 Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: can't set attribute >>>如果你真的需要改變?nèi)缓蟮膶傩?#xff0c;那么可以使用命名元組實(shí)例的_replace() 方法,它會(huì)創(chuàng)建一個(gè)全新的命名元組并將對(duì)應(yīng)的字段用新的值取代。比如:
>>> s = s._replace(shares=75) >>> s Stock(name='ACME', shares=75, price=123.45) >>>_replace() 方法還有一個(gè)很有用的特性就是當(dāng)你的命名元組擁有可選或者缺失字段時(shí)候,它是一個(gè)非常方便的填充數(shù)據(jù)的方法。你可以先創(chuàng)建一個(gè)包含缺省值的原型元組,然后使用_replace() 方法創(chuàng)建新的值被更新過(guò)的實(shí)例。比如:
from collections import namedtuple Stock = namedtuple('Stock', ['name', 'shares', 'price', 'date', 'time'])# Create a prototype instance stock_prototype = Stock('', 0, 0.0, None, None)# Function to convert a dictionary to a Stock def dict_to_stock(s): return stock_prototype._replace(**s)下面是它的使用方法:
>>> a = {'name': 'ACME', 'shares': 100, 'price': 123.45} >>> dict_to_stock(a) Stock(name='ACME', shares=100, price=123.45, date=None, time=None) >>> b = {'name': 'ACME', 'shares': 100, 'price': 123.45, 'date': '12/17/2012'} >>> dict_to_stock(b) Stock(name='ACME', shares=100, price=123.45, date='12/17/2012', time=None) >>>最后要說(shuō)的是,如果你的目標(biāo)是定義一個(gè)需要更新很多實(shí)例屬性的高效數(shù)據(jù)結(jié)構(gòu),那么命名元組并不是你的最佳選擇。這時(shí)候你應(yīng)該考慮定義一個(gè)包含 slots 方法的類 (參考 8.4 小節(jié))。
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來(lái)咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
以上是生活随笔為你收集整理的《Python Cookbook 3rd》笔记(1.18):映射名称到序列元素的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: NLP复习资料(5)-第九章 句法分析
- 下一篇: python(9)-变量、input函数