《Python Cookbook(第3版)中文版》——1.18 将名称映射到序列的元素中

简介:

本节书摘来自异步社区《Python Cookbook(第3版)中文版》一书中的第1章,第1.18节,作者[美]David Beazley , Brian K.Jones,陈舸 译,更多章节内容可以访问云栖社区“异步社区”公众号查看。

1.18 将名称映射到序列的元素中

1.18.1 问题

我们的代码是通过位置(即索引,或下标)来访问列表或元组的,但有时候这会使代码变得有些难以阅读。我们希望可以通过名称来访问元素,以此减少结构中对位置的依赖性。

1.18.2 解决方案

相比普通的元组,collections.namedtuple()(命名元组)只增加了极小的开销就提供了这些便利。实际上collections.namedtuple()是一个工厂方法,它返回的是Python中标准元组类型的子类。我们提供给它一个类型名称以及相应的字段,它就返回一个可实例化的类、为你已经定义好的字段传入值等。例如:

>>> 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'
>>>
AI 代码解读

尽管namedtuple的实例看起来就像一个普通的类实例,但它的实例与普通的元组是可互换的,而且支持所有普通元组所支持的操作,例如索引(indexing)和分解(unpacking)。比如:

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

命名元组的主要作用在于将代码同它所控制的元素位置间解耦。所以,如果从数据库调用中得到一个大型的元组列表,而且通过元素的位置来访问数据,那么假如在表单中新增了一列数据,那么代码就会崩溃。但如果首先将返回的元组转型为命名元组,就不会出现问题。

为了说明这个问题,下面有一些使用普通元组的代码:

def compute_cost(records):
    total = 0.0
    for rec in records:
        total += rec[1] * rec[2]
    return total
AI 代码解读

通过位置来引用元素常常使得代码的表达力不够强,而且也很依赖于记录的具体结构。下面是使用命名元组的版本:

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
AI 代码解读

当然,如果示例中的records序列已经包含了这样的实例,那么可以避免显式地将记录转换为Stock命名元组[4]。

1.18.3 讨论

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
>>>
AI 代码解读

如果需要修改任何属性,可以通过使用namedtuple实例的_replace()方法来实现。该方法会创建一个全新的命名元组,并对相应的值做替换。示例如下:

>>> s = s._replace(shares=75)
>>> s
Stock(name='ACME', shares=75, price=123.45)
>>>
AI 代码解读

_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)
AI 代码解读

让我们演示一下上面的代码是如何工作的:

>>> 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)
>>>
AI 代码解读
相关文章
Python入门:6.深入解析Python中的序列
在 Python 中,**序列**是一种有序的数据结构,广泛应用于数据存储、操作和处理。序列的一个显著特点是支持通过**索引**访问数据。常见的序列类型包括字符串(`str`)、列表(`list`)和元组(`tuple`)。这些序列各有特点,既可以存储简单的字符,也可以存储复杂的对象。 为了帮助初学者掌握 Python 中的序列操作,本文将围绕**字符串**、**列表**和**元组**这三种序列类型,详细介绍其定义、常用方法和具体示例。
Python入门:6.深入解析Python中的序列
时间序列结构变化分析:Python实现时间序列变化点检测
在时间序列分析和预测中,准确检测结构变化至关重要。新出现的分布模式往往会导致历史数据失去代表性,进而影响基于这些数据训练的模型的有效性。
816 1
6种有效的时间序列数据特征工程技术(使用Python)
在本文中,我们将探讨使用日期时间列提取有用信息的各种特征工程技术。
274 1
|
6月前
|
Python 序列类型(1)
【10月更文挑战第8天】
82 1
Python 序列类型(2)
【10月更文挑战第8天】
54 0
Python 序列类型(2)
|
7月前
|
Python 选出列表中特定的元素
Python 选出列表中特定的元素
107 3
python获取windows机子上运行的程序名称
python获取windows机子上运行的程序名称
Python列表与元素修改的操作技巧
Python列表提供了丰富的方法和技巧来进行高效的数据操作。熟练运用上述技巧,可以大大提高数据处理的效率和代码的可读性。实践中,根据具体需求灵活选择合适的方法,可以在保证代码效率的同时,也使代码更加简洁明了。
165 2
|
7月前
|
Python批量复制指定名称文件的技巧
通过上述步骤和示例代码,你可以轻松实现批量复制特定名称文件的功能。这种技术不仅节省了时间,而且通过脚本自动化,提高了工作效率。
106 2