跳转到主要内容

类似于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在可变默认值的情况下也能工作。

项目详情


下载文件

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

源代码分发

namedlist-1.8.tar.gz (21.9 kB 查看哈希)

上传时间 源代码

构建分发

namedlist-1.8-py2.py3-none-any.whl (15.5 kB 查看哈希)

上传时间 Python 2 Python 3

由以下组织支持