类似于namedtuple,但实例是可变的。
项目描述
警告
此包不再维护,除非是特殊情况。请使用内置的dataclasses模块代替。
概述
namedlist提供了2个工厂函数,namedlist.namedlist和namedlist.namedtuple。namedlist.namedtuple类似于collections.namedtuple,有以下不同之处
namedlist.namedtuple支持每个字段的默认值。
namedlist.namedtuple支持可选的默认值,用于所有没有显式默认值的字段。
namedlist.namedlist类似,但有以下额外差异
namedlist.namedlist实例是可变的。
典型用法
您可以使用namedlist像可变namedtuple一样使用
>>> from namedlist import namedlist >>> Point = namedlist('Point', 'x y') >>> p = Point(1, 3) >>> p.x = 2 >>> assert p.x == 2 >>> assert p.y == 3
或者,您可以指定所有字段的默认值
>>> Point = namedlist('Point', 'x y', default=3) >>> p = Point(y=2) >>> assert p.x == 3 >>> assert p.y == 2
或者,您可以指定每个字段的默认值
>>> Point = namedlist('Point', [('x', 0), ('y', 100)]) >>> p = Point() >>> assert p.x == 0 >>> assert p.y == 100
您还可以使用映射指定每个字段的默认值,而不是可迭代对象。请注意,这仅适用于有序映射,如OrderedDict
>>> from collections import OrderedDict >>> Point = namedlist('Point', OrderedDict((('y', 0), ... ('x', 100)))) >>> p = Point() >>> p Point(y=0, x=100)
如果提供了默认值且未使用每个字段的默认值,则将使用默认值
>>> Point = namedlist('Point', ['x', ('y', 100)], default=10) >>> p = Point() >>> assert p.x == 10 >>> assert p.y == 100
如果您使用映射,则NO_DEFAULT值方便指定字段使用默认值
>>> from namedlist import NO_DEFAULT >>> Point = namedlist('Point', OrderedDict((('y', NO_DEFAULT), ... ('x', 100))), ... default=5) >>> p = Point() >>> assert p.x == 100 >>> assert p.y == 5
namedtuple类似,但实例不可变
>>> from namedlist import namedtuple >>> Point = namedtuple('Point', 'x y', default=3) >>> p = Point(y=2) >>> assert p.x == 3 >>> assert p.y == 2 >>> p.x = 10 Traceback (most recent call last): ... AttributeError: can't set attribute
以下Specifying Fields和Specifying Defaults部分的所有文档都适用于namedlist.namedlist和namedlist.namedtuple。
创建类型
指定字段
在 namedlist.namedlist 或 namedlist.namedtuple 中,字段可以指定为 collections.namedtuple 中的形式:可以是表示字段名称的字符串,也可以是字段名称的可迭代对象。这两种用法是等效的
>>> Point = namedlist('Point', 'x y') >>> Point = namedlist('Point', ['x', 'y'])
同样,这些也是等效的
>>> Point = namedtuple('Point', 'x y') >>> Point = namedtuple('Point', ['x', 'y'])
如果使用字符串,逗号首先会被转换为空格。因此,这些是等效的
>>> Point = namedlist('Point', 'x y') >>> Point = namedlist('Point', 'x,y')
指定默认值
可以通过提供包含字段名称的元组(name, default_value)来指定每个字段的默认值,而不是只提供字段名称的字符串。这仅在指定字段名称列表时才受支持
>>> Point = namedlist('Point', [('x', 0), ('y', 0)]) >>> p = Point(3) >>> assert p.x == 3 >>> assert p.y == 0
或者,使用 namedtuple
>>> Point = namedtuple('Point', [('x', 0), ('y', 0)]) >>> p = Point(3) >>> assert p.x == 3 >>> assert p.y == 0
除了这些每个字段的默认值之外,还可以指定一个默认值,当未指定每个字段的默认值时,将使用此默认值
>>> Point = namedlist('Point', 'x y z', default=0) >>> p = Point(y=3) >>> assert p.x == 0 >>> assert p.y == 3 >>> assert p.z == 0 >>> Point = namedlist('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 = namedlist('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
写入值
由 namedlist.namedlist 生成的类的实例是可写的,这与由 collections.namedtuple 或 namedlist.namedtuple 返回的基于元组的类不同
>>> Point = namedlist('Point', 'x y') >>> p = Point(1, 2) >>> p.y = 4 >>> assert p.x == 1 >>> assert p.y == 4
指定 __slots__
对于 namedlist.namedlist,默认情况下,返回的类设置 __slots__,它被初始化为字段名称。虽然这通过消除实例字典减少了内存使用,但也意味着您无法创建新的实例成员
要更改此行为,在创建 namedlist 时指定 use_slots=False
>>> Point = namedlist('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
但是,请注意,此方法不会将新变量添加到 _fields 中,因此在遍历实例时不会被识别
>>> list(p) [0, 1] >>> sorted(p._asdict().items()) [('x', 0), ('y', 1)]
额外的类成员
namedlist.namedlist 和 namedlist.namedtuple 类包含以下成员
_asdict(): 返回一个字典,将字段名称映射到其对应的值。
_fields: 包含字段名称的字符串元组。在元编程时很有用。
重命名无效字段名称
此功能与 collections.namedtuple 相同。如果指定 rename=True,则任何无效的字段名称将被更改为 _0、_1 等。字段名称无效的原因包括:
零长度字符串。
包含除字母数字和下划线之外的其他字符。
与 Python 保留标识符冲突。
以数字开头。
以下划线开头。
使用相同的字段名称多次。
例如
>>> Point = namedlist('Point', 'x x for', rename=True) >>> assert Point._fields == ('x', '_1', '_2')
可变默认值
对于 namedlist.namelist,请注意指定可变默认值。由于 Python 处理默认值的方式,每个 namedlist 实例将共享默认值。对于列表等默认值来说,这是一个特别的问题。例如
>>> A = namedlist('A', [('x', [])]) >>> a = A() >>> a.x.append(4) >>> b = A() >>> assert b.x == [4]
这可能是您不希望的行为,所以请看下一节。
为默认值指定工厂函数
对于 namedlist.namedlist,您可以通过将默认值包装在 FACTORY 调用中来提供零参数的可调用对象。在这个例子中,唯一的改变是将默认值从 [] 更改为 FACTORY(list)。但是请注意,b.x 是一个新的列表对象,与 a.x 不共享
>>> from namedlist import FACTORY >>> A = namedlist('A', [('x', FACTORY(list))]) >>> a = A() >>> a.x.append(4) >>> b = A() >>> assert b.x == []
每次创建新实例时,您的可调用对象(在这种情况下为 list)将被调用以产生新的默认值实例。
遍历实例
由于实例是可迭代的(如列表或元组),迭代方式相同。值以定义顺序返回
>>> Point = namedlist('Point', 'x y z t') >>> p = Point(1.0, 42.0, 3.14, 2.71828) >>> for value in p: ... print(value) 1.0 42.0 3.14 2.71828
namedlist 特定函数
_update
namedlist._update() 与 dict.update() 类似。它用于使用新值变异 namedlist.namedlist 实例
>>> Point = namedlist('Point', 'x y z') >>> p = Point(1, 2, 3) >>> p.z = 4 >>> p._update(y=5, x=6) >>> p Point(x=6, y=5, z=4) >>> p._update({'x': 7, 'z': 8}) >>> p Point(x=7, y=5, z=8) >>> p._update([('z', 9), ('y', 10)]) >>> p Point(x=7, y=10, z=9)
创建和使用实例
由于namedlist或namedtuple返回的类型是普通的Python类,因此您创建实例的方式与创建任何Python类的方式相同。
Bitbucket 与 GitLab
之前使用的仓库是以Mercurial格式存在于Bitbucket上的。但是Bitbucket停止了对Mercurial的支持,并且没有提供任何将问题迁移到git仓库(即使是在Bitbucket上托管)的方法。因此,我放弃了Bitbucket,并将代码迁移到了GitLab。因此,所有的问题都丢失了,并且从#1开始重新创建了新问题。我给GitLab的问题命名为#GH-xx,而旧Bitbucket的问题命名为#BB-xx。我仍然对Bitbucket强制进行这种改变感到愤怒。
变更日志
1.8 2020-08-29 Eric V. Smith
添加python 3.8兼容性(#GL-1)。
迁移到gitlab。
需要setuptools,并指定通用wheel(问题#BB-30)。
删除尝试将RPM名称更改为python-namedlist的bdist_rpm代码(问题#BB-31)。
1.7 2015-05-15 Eric V. Smith
如果使用python 3运行,则将RPM名称更改为python3-namedlist。
没有代码更改。
1.6 2014-12-23 Eric V. Smith
添加namedlist._update(),类似于dict.update()。感谢Arthur Skowronek(问题#BB-23)。
添加namedlist._replace(),类似于namedtuple._replace(问题#BB-24)。
1.5 2014-05-20 Eric V. Smith
支持namedlist.__getattr__中的切片(问题#BB-22)。
1.4 2014-03-14 Eric V. Smith
将MANIFEST.in添加到MANIFEST.in中,以便它将被包含在sdists中(问题#BB-21)。
1.3 2014-03-12 Eric V. Smith
支持Python 2.x中的unicode类型和字段名(问题#BB-19)。标识符仍然必须是ASCII码,但您可以将其作为unicode传递。这对于需要在Python 2和Python 3下运行的代码很有用。
1.2 2014-02-13 Eric V. Smith
生成名为python-namedlist的RPM(问题#BB-17)。
添加namedtuple(问题#BB-10)。通过了collections.namedtuple的所有测试,除了与_source相关的测试。这些测试不适用于我们不同的动态类创建方法。所有其他collections.namedtuple测试都已复制到我们的测试套件中。
1.1 2014-02-07 Eric V. Smith
添加__dict__,以便支持vars()。
修复了从另一个模块的序列化问题(问题#BB-14)。
将测试移动到单独的文件中(问题#BB-15)。
1.0 2014-02-04 Eric V. Smith
声明API稳定并发布版本1.0。
支持python 2.6(问题#BB-8)。doctests未通过,因为OrderedDict在2.7之前不可用。
0.4 2014-02-04 Eric V. Smith
添加文档字符串(问题#BB-7)。
修复了README.txt中的错别字(感谢bitbucket上的pombredanne)。
0.3 2014-01-29 Eric V. Smith
删除了recordtype留下的文档。
使实例不可哈希(问题#BB-2)。
对于python3,使用str.isidentifier(问题#BB-1)。
重新组织代码以进行名称检查。没有功能性的更改。
使实例可迭代(问题#BB-3)。
添加collections.Sequence ABC(问题#BB-4)。
使“python setup.py test”也运行doctests(问题#BB-5)。
0.2 2014-01-28 Eric V. Smith
添加MANIFEST.in。
希望修复了CHANGES.txt中.rst格式化的问题。
0.1 2014-01-28 Eric V. Smith
初始发布。
基于我的recordtype项目,但使用ast生成而不是构建字符串并执行。这有几个优点
支持python2和python3更容易,因为exec在不同的语言中有不同的语法。
添加附加功能更容易,因为我可以编写真正的Python,而无需编写字符串版本,并处理所有转义和语法错误。
添加FACTORY,以允许namedlist在可变默认值的情况下也能工作。
项目详情
下载文件
下载适合您平台的文件。如果您不确定选择哪个,请了解有关安装包的更多信息。