映射名字到序列元素

通常列表或元组通过位置(索引)来访问元素,但这使得代码有时难以阅读。 通常我们希望通过按名称访问元素来减少对结构中位置的依赖。
collections模块的namedtuple()函数(实际上是一个工厂方法)提供了一个tuple的子类,该类拥有tuple的常规操作,同时可以提供了按名称访问序列元素的能力。
命名元组为元组中的每个位置赋予含义,并允许更可读,自我记录的代码。 它们可以在使用常规元组的任何地方使用,并且它们添加了按名称而不是位置索引访问字段的功能。
如下示例:

>>> 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的实例看起来像普通的类实例,但它可以与元组交换,并支持所有常用的元组操作,例如索引和解包。 例如:

>>> len(sub)
2
>>> addr, joined = sub
>>> addr
'jonesy@example.com'
>>> joined
'2012-10-19'
>>>


命名元组的一个主要用例是将代码与其操作的元素的位置分离。 因此,如果从数据库调用中获取大量元组,然后通过访问位置元素来操作它们,那么,如果向表中添加了新列,则代码可能会中断。 如果首先将返回的元组强制转换为namedtuples,则不是这样。
下面用一个代码片段来做解释:

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

以上代码可以看出,计算股票的价格以来元组中位置为1和2的元素,若在某个时间节点在数据库中1和2之间插入了一列,则整个代码将无法使用。
以下是通过namedtuple()的改写:

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是不可变(immutable)的。

>>> 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
>>>

如果要更改namedtuple的任意属性,可以使用该类实例的_replace()方法。

>>> s = s._replace(shares=75)
>>> s
Stock(name='ACME', shares=75, price=123.45)
>>>

实际上该方法并没有更新原有类实例,而是创建了一个全新的对象。
_replace()方法的一个巧妙用途是它可以是一种方便的方法来填充具有可选或缺少字段的命名元组。 为此,创建一个包含默认值的原型元组,然后使用_replace()创建替换值的新实例。 例如:

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)
>>>

转载于:https://www.cnblogs.com/jeffrey-yang/p/11315967.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值