1 collections 模块简要介绍
collections 是 Python 的内建集合模块, 即除了 Python 通用内置容器: dict、list、set 和 tuple 等的替代方案。在 IDLE 输入 help(collections) 可查看帮助文档,其中常见的类/函数如下:
函数名 | 函数功能 |
namedtuple | 用于创建具有命名字段的 tuple 子类的 factory 函数 (具名元组) |
deque | 类似 list 的容器,两端都能实现快速 append 和 pop (双端队列) |
ChainMap | 类似 dict 的类,用于创建多个映射的单视图 |
Counter | 用于计算 hashable 对象的 dict 子类 (可哈希对象计数) |
OrderedDict | 记住元素添加顺序的 dict 子类 (有序字典) |
defanltdict | dict 子类调用 factory 函数来提供缺失值 |
UserDict | 包装 dict 对象以便于 dict 的子类化 |
UserList | 包装 list 对象以便于 list 的子类化 |
UserString | 包装 string 对象以便于 string 的子类化 |
2 namedtuple() 函数详解
2.1 namedtuple() 函数的优势
具名元组 namedtuple 的实例和普通元组 tuple 消耗的内存一样多 (因为字段名都被保存在对应的类中) 但却更具可读性 (namedtuple 使 tuple 变成自文档,根据字段名很容易理解用途),令代码更易维护
namedtuple 不用命名空间字典(namespace dictionary) __dict__ 来存放/维护实例属性,故比普通 dict 更加轻量和快速
2.2 参数解析
import collections
collections.namedtuple(typename, field_names, *, verbose=False, rename=False, module=None)
namedtuple,已具命名的元组 (简称具名元组),它返回一个 tuple 子类
namedtuple 名称为参数 typename,各字段名称为参数 field_names
field_names 既可以是一个类似 ['x', 'y'] 的字符串序列 (string-seq),也可以是用空格或逗号分隔开的纯字符串 string,如 'x y' 或 'x, y'。任何 Python 的有效标识符都可作为字段名。所谓有效标识符由字母,数字,下划线组成,但首字母不能是数字或下划线,且不能与 Python 关键词重复,如 class, for, return 等
具名元组 namedtuple 向后兼容普通 tuple,从而既可通过 field_names 获取元素值/字段值,也能通过索引和迭代获取元素值/字段值
2.3 函数扩展
除继承普通 tuple,具名元组 nametuple 还额外支持三个方法和两个属性
类属性 _fields | 包含本类所有字段名的元组 tuple |
类方法 _make(iterable) | 接受一个序列 sequence 或可迭代对象 iterable 来生成本类的实例 |
实例方法 _replace(**kwargs) | 基于本实例修改、替换元素来生成本类的实例 |
实例方法 _asdict() | 将具名元组以 collections.OrdereDict 的形式返回,用于友好地展示元组信息 |
3 示例
3.1 基本属性
>>> from collections import namedtuple
>>> Point2 = namedtuple("Point2", 'x, y') # 初始化一个具名元组对象 Point2
>>> p2 = Point2(1, 4)
>>> p2
Point2(x=1, y=4)
# -------------------------------------------------------------------------
>>> p2._fields # 获取所有字段名构成的 tuple
('x', 'y')
# -------------------------------------------------------------------------
>>> p21 = p2._make([5, 6]) # 使用 list 实例化一个新 Point2 对象
>>> p21
Point2(x=5, y=6)
>>> p2
Point2(x=1, y=4) # 原 namedtuple 不变
# -------------------------------------------------------------------------
>>> p22 = p2._replace(y=4.5) # 使用关键字参数修改并实例化一个新 Point2 对象
>>> p22
Point2(x=1, y=4.5)
>>> p2
Point2(x=1, y=4) # 原 namedtuple 不变
# -------------------------------------------------------------------------
>>> p2._asdict() # 将 namedtuple 对象转换为 OrderedDict 对象
OrderedDict([('x', 1), ('y', 4)])
>>> p2
Point2(x=1, y=4) # 原 namedtuple 不变
3.2 rename = True
若参数 rename=True,无效字段名 field_names 会自动转换成位置名。例如 ['abc', 'def', 'ghi', 'abc'] 转换成 ['abc', '_1', 'ghi', '_3'],转换并消除了关键词 def 和重复域名 abc。否则,在创建伊始就会抛出 ValueError
>>> Point3 = namedtuple("Point3", ['abc', 'def', 'ghi', 'abc'], rename=True)
>>> p3 = Point3(3, 5, 7, 9)
>>> p3._fields
('abc', '_1', 'ghi', '_3')
>>> p3
Point3(abc=3, _1=5, ghi=7, _3=9)
3.3 将 dict 转换为 namedtuple
将 dict 转换为 namedtuple 可使用双星操作符 ** (double-star-operator) 进行解包
>>> dict4 = {'x':14, 'y':16}
>>> Point4 = namedtuple("Point4", 'x y')
>>> p4 = Point4(**dict4)
>>> p4
Point4(x=14, y=16)