1.18 映射名称到序列元素

您有一段代码,它通过下标访问列表或元组中的元素,但这有时会使代码难以阅读,因此您希望按名称访问元素。

[En]

You have a piece of code that accesses elements in a list or tuple through subscripts, but this sometimes makes your code difficult to read, so you want to access elements by name.

collections.namedtuple()函数通过使用一个普通的元组对象来帮你解决这个问题。这个函数实际上是一个返回Python中标准元组类型子类的一个工厂方法。你需要传递一个类型名和你需要的字段给它,然后它就会返回一个类,你可以初始化这个类,为你定义的字段传递值等。例如:

from collections import namedtuple

Subscriber = namedtuple('Tester', ['addr', 'joined'])
sub = Subscriber('Abu11@cnblogs.com', '2022-01-07')
"""
sub = Tester(addr='Abu11@cnblogs.com', joined='2022-01-07')
sub.addr = Abu11@cnblogs.com
sub.joined = 2022-01-07
"""

尽管 namedtuple的实例看起来像一个普通的类实例,但是它跟元组类型是可交换的,支持所有的普通元组操作,比如索引和解压。例如:

length = len(sub)
addr, joined = sub
"""
length = 2
addr = 'Abu11@cnblogs.com'
joined = '2022-01-07'
"""

命名元组的主要用途之一是将代码从下标操作中解放出来。因此,如果使用下标操作元组列表中的元素,则在向表中添加新列时,代码可能会出错。但如果使用命名元组,就不会有这个问题。

[En]

One of the main uses of named tuples is to free your code from subscript operations. Therefore, if you use subscripts to manipulate elements in a tuple list, your code may go wrong when you add new columns to the table. But if you use named tuples, you won’t have this problem.

为了说明这一点,下面是使用普通元组的代码:

[En]

To illustrate this, here is the code that uses normal tuples:

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

下标操作通常会混淆代码,并且严重依赖记录的结构。以下是使用命名元组的版本:

[En]

Subscript operations usually confuse the code and rely heavily on the structure of the record. Here is the version that uses named tuples:

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

命名元组的另一个功能是作为字典的替代,因为字典存储需要更多的内存空间。如果您需要构建一个包含字典的非常大的数据结构,那么使用命名元组会更有效。但是,请注意,命名元组是不可变的。例如:

[En]

Another function of named tuples is as an alternative to dictionaries, because dictionary storage requires more memory space. If you need to build a very large data structure that contains dictionaries, then using named tuples is more efficient. Note, however, that a named tuple is immutable. For example:

s = Stock('A', 1, 22)  # Stock(name='A', shares=1, price=22)
s.shares = 7
"""
AttributeError: can't set attribute
"""

如果你真的需要改变属性的值,那么可以使用命名元组实例的 _replace()方法,它会创建一个全新的命名元组并将对应的字段用新值取代。例如:

s = s._replace(shares=7)
print(s)
"""输出结果:
Stock(name='A', shares=7, price=22)
"""

_replace()方法还有一个很有用的特性就是当你的命名元组拥有可选或者缺失字段时,它是一个非常方便的填充数据的方法。你可以创建一个包含缺省值的原型元组,然后使用 _replace()方法创建新的值被更新过的实例。例如:

from collections import namedtuple

Stock = namedtuple('Stock', ['name', 'shares', 'price', 'date', 'time'])
stock_instance = Stock('', 0, 0.0, None, None)

def dict_to_stock(s):
    return stock_instance._replace(**s)

if __name__ == '__main__':
    a = {'name': 'ACME', 'shares': 100, 'price': 123.45}
    print(dict_to_stock(a))
    b = {'name': 'ACME', 'shares': 100, 'price': 123.45, 'date': '12/17/2012'}
    print(dict_to_stock(b))

    """输出结果:
    Stock(name='ACME', shares=100, price=123.45, date=None, time=None)
    Stock(name='ACME', shares=100, price=123.45, date='12/17/2012', time=None)
"""

最后要说的是,如果你的目标是定义一个需要更新很多实例属性的高效数据结构,那么命名元组并不是最佳选择。这时候你应该考虑定义一个包含 __slots__方法的类(参考8.4小节)

本小节介绍了 collections.namedtuple()方法,它可以初始化一个类,将一个元组的值依次赋予给类的各字段,这样就可以通过字段访问值。一定程度上可以替代字典。

Original: https://www.cnblogs.com/L999C/p/15776734.html
Author: Abu11
Title: 1.18 映射名称到序列元素

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/510306/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球