美文网首页
Python3 - 映射名称到序列元素(命名元组)

Python3 - 映射名称到序列元素(命名元组)

作者: 惑也 | 来源:发表于2018-12-16 23:21 被阅读34次

    问题

    通过下标访问列表或元组中的元素,代码可读性不强,可以通过名称来访问元素。

    解决方案

    collections.namedtuple() 函数是继承自tuple的子类。可以创建自定义元素个数的tuple对象,它具备tuple的不变性,又可以根据属性而不是索引来引用其中的元素。代码示例:

    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
    

    命名元组的主要用途是将代码从下标操作中解脱出来。 因此,如果在数据库调用中返回了一个很大的元组列表,通过下标去操作其中的元素, 当数据库表中添加了新的列时,代码可能就会出错,但如果使用了命名元组,就不会有这样的顾虑。

    为了说明清楚,下面是使用普通元组的代码:

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

    下标操作通常会让代码表意不清晰,并且非常依赖记录的结构。 下面是使用命名元组的版本:

    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
    

    讨论

    命名元组另一个用途是作为字典的替代,因为字典存储需要更多的内存空间。 如果需要构建一个非常大的包含字典的数据结构,那么使用命名元组会更加高效。 但是需要注意的是,不像字典那样,一个命名元组是不可更改的。比如:

    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() 方法, 它会创建一个全新的命名元组,并将对应的字段用新的值取代。比如:

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

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

    相关文章

      网友评论

          本文标题:Python3 - 映射名称到序列元素(命名元组)

          本文链接:https://www.haomeiwen.com/subject/awkfkqtx.html