問題
通過下標(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 方法的類瞒渠。