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

問題

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

解決方案

collections.namedtuple() 函數(shù)是繼承自tuple的子類??梢詣?chuàng)建自定義元素個(gè)數(shù)的tuple對(duì)象,它具備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 的實(shí)例看起來像一個(gè)普通的類實(shí)例,但是它跟元組類型是可交換的,支持所有的普通元組操作,如索引和解壓。 比如:

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

2
python@gmail.com
2017-11-10

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

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

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

下標(biāo)操作通常會(huì)讓代碼表意不清晰,并且非常依賴記錄的結(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

討論

命名元組另一個(gè)用途是作為字典的替代,因?yàn)樽值浯鎯?chǔ)需要更多的內(nèi)存空間。 如果需要構(gòu)建一個(gè)非常大的包含字典的數(shù)據(jù)結(jié)構(gòu),那么使用命名元組會(huì)更加高效。 但是需要注意的是,不像字典那樣,一個(gè)命名元組是不可更改的。比如:

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

如果確實(shí)需要改變屬性的值,可以使用命名元組實(shí)例的 _replace() 方法, 它會(huì)創(chuàng)建一個(gè)全新的命名元組,并將對(duì)應(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)是定義一個(gè)需要更新很多實(shí)例屬性的高效數(shù)據(jù)結(jié)構(gòu),那么命名元組并不是最佳選擇。 這時(shí)候應(yīng)該考慮定義一個(gè)包含 slots 方法的類。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容