题图:Photo by Paulo Jacobe on Unsplash
大家好,我是军哥
今天开始,开一个冷门模块的系列更新。
collections模块算得上是最冷门的模块之一,用得人少,但是功能很强大。
collections提供了4个重要的数据类型,在实际开发中或多或少会接触到,通过使用这些数据类型,可以让你的代码变得更优雅、更地道。
今天先来介绍 namedtuple 这个类型
namedtuple
namedtuple 是 元组(tuple)类型的子类,所以本质上它还是一个元组类型,继承了元组所有的的特性,namedtuple 特别之处在于你可以通过名字来访问元组中的元素,类似字典,通过key来访问value。
以前访问元组中的元素必须通过索引访问
>>> x, y = 1,2
>>> point = (x, y)
>>> point[0]
1
>>> point[1]
2
现在你可以通过属性名来访问,先看如何定义一个 namedtuple
定义
from collections import namedtuple
# 首先定义一个namedtuple类
# 类的名字是 "Point"
# 它有两个属性 x 和 y
>>> Point = namedtuple('Point', ['x', 'y'])
# namedtuple初始化
>>> p = Point(x=11, y=22)
# 和tuple类型一样,通过下标索引访问,等价于 p = (11, 22)
>>> p[0] + p[1]
33
# 通过字段属性来访问,这是namedtuple独有的特性
>>> p.x + p.y
33
咋看起来,要使用 namedtuple还是挺麻烦的,不像tuple一样,直接 p = (11, 22) 就定义了一个元组对象,那什么场景下会用到 namedtuple呢?
答案是在使用tuple可读性不强,但是又不希望用class来自定义类的时候。
比如有这样一组数据
bob = ('Bob', 30, 'male')
看值其实你是不知道这里面的3个元素分别表示什么意思的,也许你能猜出来,但也仅仅是靠猜,那怎么样可读性更好一点呢?其实,我们可以自定义一个类来抽象化这组数据
class Person:
def __init__(name, age, gender):
self.name = name
self.age = age
self.gender = gender
bob = Person('Bob', 30, 'male')
通过Person类,你可以一目了然,知道Bob对应的就是name,30对应的是 age,male 对应的gender字段。
可是这样做,虽然可读性更强一点了,但是代码更麻烦,更重要的是创建一个这样的对象消耗的成本会比纯粹的元组高很多。
而 namedtuple 正好可以解决这种问题,它即继承了tuple良好的性能,又有可读性的特点。
from collections import namedtuple
Person = namedtuple("Person", "name age gender")
bob = Person(name='Bob', age=30, gender='male')
>>> bob[0]
'Bob'
>>> bob.name
'Bob'
>>> bob.age
30
>>> bob[1]
30
你有没有注意到,namedtuple可认为是一种简单的自定义类,可以指定属性,但是不能像class定义的类一样定义方法。因此,在考虑到如果定义一个类,类里面不需要定义方法时,其实就可以用namedtuple来代替。
这就是namedtuple的作用,你了解了吗?
推荐: