跳转到主要内容

类似于namedtuple,但实例是可变的。

项目描述

注意

在Python 3.7中,dataclasses比recordtype提供了更好的解决方案。

我已经将主要开发转向了我的 namedlist项目。它有一个更好的实现,使修改代码更加容易。它应该与recordtype完全兼容。

通常,attrs项目(https://attrs.readthedocs.io/en/stable/)是recordtype和namedlist的改进。

概述

recordtype提供了一个名为recordtype.recordtype的工厂函数。它与collections.namedtuple类似,但有以下不同

  • recordtype实例是可变的。

  • recordtype支持每个字段的默认值。

  • recordtype支持一个可选的默认值,用于所有没有显式默认值的字段。

典型用法

您可以使用recordtype像一个可变的namedtuple一样使用

>>> from recordtype import recordtype

>>> Point = recordtype('Point', 'x y')
>>> p = Point(1, 3)
>>> p.x = 2
>>> assert p.x == 2
>>> assert p.y == 3

或者,您可以指定所有字段的默认值

>>> Point = recordtype('Point', 'x y', default=3)
>>> p = Point(y=2)
>>> assert p.x == 3
>>> assert p.y == 2

或者,您可以指定每个字段的默认值

>>> Point = recordtype('Point', [('x', 0), ('y', 100)])
>>> p = Point()
>>> assert p.x == 0
>>> assert p.y == 100

您还可以使用映射指定每个字段的默认值,而不是可迭代对象。请注意,这仅适用于有序映射,如OrderedDict

>>> from collections import OrderedDict
>>> Point = recordtype('Point', OrderedDict((('y', 0),
...                                          ('x', 100))))
>>> p = Point()
>>> assert p.x == 100
>>> assert p.y == 0

只有当提供了默认值且未使用每个字段的默认值时,才会使用默认值

>>> Point = recordtype('Point', ['x', ('y', 100)], default=10)
>>> p = Point()
>>> assert p.x == 10
>>> assert p.y == 100

如果您使用映射,值NO_DEFAULT方便指定字段使用默认值

>>> from recordtype import NO_DEFAULT
>>> Point = recordtype('Point', OrderedDict((('y', NO_DEFAULT),
...                                          ('x', 100))),
...                             default=5)
>>> p = Point()
>>> assert p.x == 100
>>> assert p.y == 5

创建类型

指定字段

字段可以指定为 namedtuple 中的形式:可以是字段名称的字符串,或者字段名称的可迭代序列。这两种用法是等价的

>>> Point = recordtype('Point', 'x y')
>>> Point = recordtype('Point', ['x', 'y'])

如果使用字符串,逗号首先会被转换为空格。因此,这些是等价的

>>> Point = recordtype('Point', 'x y')
>>> Point = recordtype('Point', 'x,y')

指定默认值

可以通过提供包含字段名称的元组(name, default_value)来指定每字段的默认值,而不是仅提供字段名称的字符串。这仅在指定字段名称列表时才受支持

>>> Point = recordtype('Point', [('x', 0), ('y', 0)])
>>> p = Point(3)
>>> assert p.x == 3
>>> assert p.y == 0

除了这些每字段默认值之外,还可以指定一个默认值,当未指定每字段默认值时使用

>>> Point = recordtype('Point', 'x y z', default=0)
>>> p = Point(y=3)
>>> assert p.x == 0
>>> assert p.y == 3
>>> assert p.z == 0

>>> Point = recordtype('Point', [('x', 0), 'y', ('z', 0)], default=4)
>>> p = Point(z=2)
>>> assert p.x == 0
>>> assert p.y == 4
>>> assert p.z == 2

除了将字段名称作为 2 元组序列提供之外,还可以指定一个映射。键将是字段名称,值将是每字段的默认值。这对于 OrderedDict 非常有用,因为这样字段的顺序将是确定的。如果想要字段使用每类型的默认值而不是使用字段指定它,可以指定模块变量 NO_DEFAULT

>>> Point = recordtype('Point', OrderedDict((('x', 0),
...                                          ('y', NO_DEFAULT),
...                                          ('z', 0),
...                                          )),
...                             default=4)
>>> p = Point(z=2)
>>> assert p.x == 0
>>> assert p.y == 4
>>> assert p.z == 2

写入值

由工厂函数返回的对象是可完全写入的,与 namedtuple 返回的基于元组的类不同

>>> Point = recordtype('Point', 'x y')
>>> p = Point(1, 2)
>>> p.y = 4
>>> assert p.x == 1
>>> assert p.y == 4

指定 __slots__

默认情况下,返回的类设置 __slots__,它被初始化为字段名称。虽然这通过消除实例字典减少了内存使用,但也意味着您不能创建新的实例成员。

要更改此行为,请在创建 recordtype 时指定 use_slots=False

>>> Point = recordtype('Point', 'x y', use_slots=False)
>>> p = Point(0, 1)
>>> p.z = 2
>>> assert p.x == 0
>>> assert p.y == 1
>>> assert p.z == 2

其他类成员

recordtype 类包含以下成员

  • _asdict(): 返回一个字典,将字段名称映射到其对应的值。

  • _source: 用于创建 recordtype 类的纯 Python 源代码字符串。源代码使 recordtype 自动文档化。它可以打印,可以使用 exec() 执行,或保存到文件中并导入。

  • _fields: 包含字段名称的字符串元组。对于内省很有用。

重命名无效字段名称

此功能与 namedtuple 相同。如果您指定 rename=True,则任何无效的字段名称都会被更改为 _0、_1 等。字段名称无效的原因包括

  • 空字符串。

  • 包含除字母数字和下划线之外的字符。

  • 与 Python 保留标识符冲突。

  • 以数字开头。

  • 以下划线开头。

  • 使用相同的字段名称多次。

例如

>>> Point = recordtype('Point', 'x x for', rename=True)
>>> assert Point._fields == ('x', '_1', '_2')

可变默认值

请注意创建可变默认值。由于 Python 处理默认值的方式,recordtype 的每个实例都将共享默认值。这对于默认值为列表的情况尤其有问题。例如

>>> A = recordtype('A', [('x', [])])
>>> a = A()
>>> a.x.append(4)
>>> b = A()
>>> assert b.x == [4]

这可能不是预期的行为。

创建和使用实例

因为 recordtype 返回的类型是正常的 Python 类,所以您创建实例的方式与任何 Python 类一样。

变更日志

1.4 2022-09-22 Eric V. Smith

  • 为了与 Python 3.10 兼容,尝试导入 collections.abc.Mapping。

  • 使用 black 重新格式化。

1.3 2018-08-03 Eric V. Smith

  • Python 3 支持(感谢 Jakob Stasiak)。

  • 使用 black 重新格式化。

1.2 <未发布> Eric V. Smith

  • 将 README.txt 转换为支持 doctest。

  • 添加可变默认值的测试。

  • 添加关于可变默认值的警告。

1.1 2011-11-14 Eric V. Smith

  • 没有 API 或代码更改。

  • 在 setup.py 中修复了项目 URL。

  • 在 setup.py 中修复了许可证描述。

1.0 2011-10-23 Eric V. Smith

  • 稳定 API,升级到版本 1.0。

  • 添加“python setup.py test”支持以运行单元测试。

  • 改进文档示例。

  • 将“default_default”重命名为“default”。

  • 公开“NO_DEFAULT”。

  • 支持 field_names 的字符串和列表以外的映射对象。

  • 为 field_names 添加对可迭代的测试,而不仅仅是列表。

0.2 2011-10-13 Eric V. Smith

  • 修复文档中的错别字,没有代码更改。

0.1 2011-10-12 Eric V. Smith

  • 初始发布。

项目详情


下载文件

下载适合您平台的文件。如果您不确定选择哪个,请了解更多关于安装包的信息。

源代码分发

recordtype-1.4.tar.gz (13.7 kB 查看哈希值)

上传时间 源代码

构建分发

recordtype-1.4-py2.py3-none-any.whl (13.8 kB 查看哈希值)

上传时间 Python 2 Python 3

由以下组织支持