Python3 - 映射名稱到序列元素(命名元組)

問題

通過下標(biāo)訪問列表或元組中的元素癞揉,代碼可讀性不強(qiáng),可以通過名稱來訪問元素铣猩。

解決方案

collections.namedtuple() 函數(shù)是繼承自tuple的子類揖铜。可以創(chuàng)建自定義元素個數(shù)的tuple對象达皿,它具備tuple的不變性天吓,又可以根據(jù)屬性而不是索引來引用其中的元素。代碼示例:

from collections import namedtuple

User = namedtuple('User', ['mail_add', 'joined_date'])
print(User)
<class '__main__.User'>

user = User('python@gmail.com', '2017-11-10')
print(user)
print(user.mail_add)
print(user.joined_date)

User(mail_add='python@gmail.com', joined_date='2017-11-10')
python@gmail.com
2017-11-10

盡管 namedtuple 的實例看起來像一個普通的類實例峦椰,但是它跟元組類型是可交換的龄寞,支持所有的普通元組操作,如索引和解壓汤功。 比如:

print(len(user))
mail, joined = user
print(mail)
print(joined)

2
python@gmail.com
2017-11-10

命名元組的主要用途是將代碼從下標(biāo)操作中解脫出來物邑。 因此,如果在數(shù)據(jù)庫調(diào)用中返回了一個很大的元組列表滔金,通過下標(biāo)去操作其中的元素色解, 當(dāng)數(shù)據(jù)庫表中添加了新的列時,代碼可能就會出錯餐茵,但如果使用了命名元組科阎,就不會有這樣的顧慮。

為了說明清楚忿族,下面是使用普通元組的代碼:

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

下標(biāo)操作通常會讓代碼表意不清晰锣笨,并且非常依賴記錄的結(jié)構(gòu)。 下面是使用命名元組的版本:

from collections import namedtuple

Stock = namedtuple('Stock', ['name', 'shares', 'price'])
def cumputer_cost(records):
    total = 0.0
    for record in records:
        r = Stock(*record)
        total += s.shares * s.price
    return total

討論

命名元組另一個用途是作為字典的替代肠阱,因為字典存儲需要更多的內(nèi)存空間票唆。 如果需要構(gòu)建一個非常大的包含字典的數(shù)據(jù)結(jié)構(gòu),那么使用命名元組會更加高效屹徘。 但是需要注意的是走趋,不像字典那樣,一個命名元組是不可更改的噪伊。比如:

s = Stock('ACME', 100, 123.45)
s.shares = 75

Traceback (most recent call last):
File "<stdin>", line 1, in <module>
    s.shares = 75
AttributeError: can't set attribute

如果確實需要改變屬性的值簿煌,可以使用命名元組實例的 _replace() 方法氮唯, 它會創(chuàng)建一個全新的命名元組,并將對應(yīng)的字段用新的值取代姨伟。比如:

s = Stock('ACME', 100, 123.45)
s = s._replace(shares=75)
print(s)

Stock(name='ACME', shares=75, price=123.45)

最后要說的是惩琉,如果目標(biāo)是定義一個需要更新很多實例屬性的高效數(shù)據(jù)結(jié)構(gòu),那么命名元組并不是最佳選擇夺荒。 這時候應(yīng)該考慮定義一個包含 slots 方法的類瞒渠。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市技扼,隨后出現(xiàn)的幾起案子伍玖,更是在濱河造成了極大的恐慌,老刑警劉巖剿吻,帶你破解...
    沈念sama閱讀 222,681評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件窍箍,死亡現(xiàn)場離奇詭異,居然都是意外死亡丽旅,警方通過查閱死者的電腦和手機(jī)椰棘,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,205評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來榄笙,“玉大人邪狞,你說我怎么就攤上這事“彀撸” “怎么了外恕?”我有些...
    開封第一講書人閱讀 169,421評論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長乡翅。 經(jīng)常有香客問我鳞疲,道長,這世上最難降的妖魔是什么蠕蚜? 我笑而不...
    開封第一講書人閱讀 60,114評論 1 300
  • 正文 為了忘掉前任尚洽,我火速辦了婚禮,結(jié)果婚禮上靶累,老公的妹妹穿的比我還像新娘腺毫。我一直安慰自己,他們只是感情好挣柬,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,116評論 6 398
  • 文/花漫 我一把揭開白布潮酒。 她就那樣靜靜地躺著,像睡著了一般邪蛔。 火紅的嫁衣襯著肌膚如雪急黎。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,713評論 1 312
  • 那天,我揣著相機(jī)與錄音勃教,去河邊找鬼淤击。 笑死,一個胖子當(dāng)著我的面吹牛故源,可吹牛的內(nèi)容都是我干的污抬。 我是一名探鬼主播,決...
    沈念sama閱讀 41,170評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼绳军,長吁一口氣:“原來是場噩夢啊……” “哼印机!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起删铃,我...
    開封第一講書人閱讀 40,116評論 0 277
  • 序言:老撾萬榮一對情侶失蹤耳贬,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后猎唁,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,651評論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡顷蟆,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,714評論 3 342
  • 正文 我和宋清朗相戀三年诫隅,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片帐偎。...
    茶點(diǎn)故事閱讀 40,865評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡逐纬,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出削樊,到底是詐尸還是另有隱情豁生,我是刑警寧澤,帶...
    沈念sama閱讀 36,527評論 5 351
  • 正文 年R本政府宣布漫贞,位于F島的核電站甸箱,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏迅脐。R本人自食惡果不足惜芍殖,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,211評論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望谴蔑。 院中可真熱鬧豌骏,春花似錦、人聲如沸隐锭。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,699評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽钦睡。三九已至蒂窒,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背刘绣。 一陣腳步聲響...
    開封第一講書人閱讀 33,814評論 1 274
  • 我被黑心中介騙來泰國打工樱溉, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人纬凤。 一個月前我還...
    沈念sama閱讀 49,299評論 3 379
  • 正文 我出身青樓福贞,卻偏偏與公主長得像,于是被迫代替她去往敵國和親停士。 傳聞我的和親對象是個殘疾皇子挖帘,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,870評論 2 361