具名元祖
前言
本文将简介 Python 的具名元祖namedtuple
,以及它的使用方式和使用场合。
本文中的命令行示范,都是基于以下环境:
- 操作系统: CentOS 7
- Python:3.7.9
什么是具名元祖
namedtuple
,称为具名元祖
,有些书上也把它叫做有名元祖。在 Python 内置的序列类型 一文中,本人介绍过元祖(tuple),它是 Python 提供的一种基础数据类型,像列表一样可以按序列存放数据,区别在于元祖的元素不可修改,所以不具有可变性。元祖存放的数据,由于没有名称,所以往往没有意义(meaningless),比如:
|
|
虽然从它元素的内容,我们可以大致猜到这些元素的含义,但这些数值本身是没有名称的,整个元祖对象也没有名称。
namedtuple
本质上是一个工厂函数
,它被用来构建一个类对象。比起普通元祖,这个类创建出来的实例对象,每个元素都对应着一个字段名,所以整个实例对象往往是有含义的。而它构造的实例对象,占用的内存和普通元祖一样多,因为它的字段名被存在了类对象里面。这个实例对象和普通的对象实例比起来要小一些,不会用实例对象的__dict__
来存放属性。
具名元祖的特点
用 namedtuple 创建的具名元祖,有以下几个特点:
- 具有普通元祖的所有功能;
- 可以从可迭代对象构造实例对象(_make 方法);
- 可以从字典构造实例对象;
- 可以用字段名访问元素;
- 可以转换成有序字典(OrderedDict);
- 方便调试(因为每个元素都有名字)
基本用法
用 namedtuple 创建一个具名元祖的基本语法如下:
|
|
参数的含义是:
- typename:元组名称
- field_names:元组中元素的名称
- rename:如果设为 True,不合法的名称(Python 关键字)会被替换成以下划线开头的数字
- defaults:None 或者可迭代对象,可迭代对象中的元素值,作为参数的默认值
后面两个参数不常用,这里不展开介绍了。
函数返回一个类对象,用户用这个类对象去创建实例。
下面来看个例子:
|
|
- 调用 namedtuple 创建了一个类对象 Student,它类似于普通元祖,区别在于它有名称:‘Student’,各个元素也有对应的字段名称:”name“,”age“,”sex“,”country“。创建 namedtuple 的时候,可以用一个可迭代对象(例子中用了列表)来创建这些字段,也可以用一个由空格分隔开的字段名组成的字符串来定义。
- 创建一个新实例对象的时候,元祖的元素值必须按照对应字段的顺序传入到构造函数中。可以像普通函数调用一样,用关键字来给参数赋值。
- namedtuple 创建的类,重构了
__repr__
方法,所以用 print() 打印能显示对象具体的信息。 - 可以用位置索引来访问元素。
- 也可以用名称来访问元素。
- 支持迭代。
- 也可以像普通元祖那样拆包。
- 具名元祖和元祖一样,具有不可变性(immutable),不能修改它的元素。
执行结果如下:
|
|
高级用法
获取字段名称
可以用_fields
属性获取具名元祖中所有字段的名称:
|
|
执行结果:
|
|
用可迭代对象构造
_make
方法帮助我们用可迭代对象构造具名元祖的对象:
|
|
这里 student_info 可以是任何可迭代对象,只要长度和具名元祖 Student 的字段个数一致即可。其实,我们也可以直接用 Python 拆包与装包的详解(一) 中介绍过的单星号
来做同样的事:
|
|
转换成 OrderedDict 对象
具名元祖对象的每一个元素都有对应的字段名称,所以它很像是一个 dict。_asdict
方法可以帮助我们根据具名元祖对象的内容生成一个新的 OrderedDict 对象。OrderedDict 是 dict 的子类,和 dict 相比,它是一个有序字典,新增或删除元素不会改变原有元素的顺序:
|
|
执行结果:
|
|
用字典对象构造
上一节我们看到,可以把具名元祖对象转换成新的 OrderedDict 对象,相反,我们也可以用一个 dict 对象来构造具名元祖对象,这里只要用双星号
拆包字典对象即可:
|
|
执行结果:
|
|
替换字段的值
我们可以用_replace
方法生成新的具名元祖对象,新对象替换原对象中的某个字段:
|
|
执行结果:
|
|
可以看到,_replace
函数并不会改变原来对象中的值,事实上它也不可能改变,因为具名元祖对象本身是不可变的。它复制了一个新的对象,并把相关的字段的值修改掉。
具名元祖还有一些其它方法和使用细节,具体可参考 Python 标准库文档 。
参考
https://docs.python.org/3.7/library/collections.html#collections.namedtuple
https://www.runoob.com/note/25726
「 您的赞赏是激励我创作和分享的最大动力! 」
- 原文链接:https://zhuyinjun.me/2020/python_namedtuple/
- 版权声明:本创作采用 CC BY-NC 4.0 国际许可协议,非商业性使用可以转载,但请注明出处(作者、链接),商业性使用请联系作者获得授权。