collections额外数据类型
collections
--- 容器数据类型
这个模块实现了特定目标的容器,以提供Python标准内建容器 dict
, list
, set
, 和 tuple
的替代选择。
创建命名元组子类的工厂函数 |
|
类似列表(list)的容器,实现了在两端快速添加(append)和弹出(pop) |
|
类似字典(dict)的容器类,将多个映射集合到一个视图里面 |
|
字典的子类,提供了可哈希对象的计数功能 |
|
字典的子类,保存了他们被添加的顺序 |
|
字典的子类,提供了一个工厂函数,为字典查询提供一个默认值 |
|
封装了字典对象,简化了字典子类化 |
|
封装了列表对象,简化了列表子类化 |
|
封装了列表对象,简化了字符串子类化 |
namedtuple()
命名元组的工厂函数
命名元组赋予每个位置一个含义,提供可读性和自文档性。它们可以用于任何普通元组,并添加了通过名字获取值的能力,通过索引值也是可以的。
collections.
namedtuple
(typename, field_names, *, rename=False, defaults=None, module=None)-
返回一个新的元组子类,名为 typename 。这个新的子类用于创建类元组的对象,可以通过域名来获取属性值,同样也可以通过索引和迭代获取值。子类实例同样有文档字符串(类名和域名)另外一个有用的
__repr__()
方法,以name=value
格式列明了元组内容。field_names 是一个像
[‘x’, ‘y’]
一样的字符串序列。另外 field_names 可以是一个纯字符串,用空白或逗号分隔开元素名,比如'x y'
或者'x, y'
。任何有效的Python 标识符都可以作为域名,除了下划线开头的那些。有效标识符由字母,数字,下划线组成,但首字母不能是数字或下划线,另外不能是关键词
keyword
比如 class, for, return, global, pass, 或 raise 。如果 rename 为真, 无效域名会自动转换成位置名。比如
['abc', 'def', 'ghi','abc']
转换成['abc', '_1', 'ghi', '_3']
, 消除关键词def
和重复域名abc
。defaults 可以为
None
或者是一个默认值的 iterable 。如果一个默认值域必须跟其他没有默认值的域在一起出现,defaults 就应用到最右边的参数。比如如果域名['x', 'y','z']
和默认值(1, 2)
,那么x
就必须指定一个参数值 ,y
默认值1
,z
默认值2
。如果 module 值有定义,命名元组的
__module__
属性值就被设置。命名元组实例没有字典,所以它们要更轻量,并且占用更小内存。
在 3.1 版更改: 添加了对 rename 的支持。
在 3.6 版更改: verbose 和 rename 参数成为 仅限关键字参数.
在 3.6 版更改: 添加了 module 参数。
在 3.7 版更改: 移去了 verbose 参数和属性
_source
。在 3.7 版更改: 添加了 defaults 参数和
_field_defaults
属性。
>>> # Basic example
>>> Point = namedtuple('Point', ['x', 'y'])
>>> p = Point(11, y=22) # instantiate with positional or keyword arguments
>>> p[0] + p[1] # indexable like the plain tuple (11, 22)
33
>>> x, y = p # unpack like a regular tuple
>>> x, y
(11, 22)
>>> p.x + p.y # fields also accessible by name
33
>>> p # readable __repr__ with a name=value style
Point(x=11, y=22)
命名元组尤其有用于赋值 csv
sqlite3
模块返回的元组
EmployeeRecord = namedtuple('EmployeeRecord', 'name, age, title, department, paygrade')
import csv
for emp in map(EmployeeRecord._make, csv.reader(open("employees.csv", "rb"))):
print(emp.name, emp.title)
import sqlite3
conn = sqlite3.connect('/companydata')
cursor = conn.cursor()
cursor.execute('SELECT name, age, title, department, paygrade FROM employees')
for emp in map(EmployeeRecord._make, cursor.fetchall()):
print(emp.name, emp.title)
除了继承元组的方法,命名元组还支持三个额外的方法和两个属性。为了防止域名冲突,方法和属性以下划线开始。
- classmethod
somenamedtuple.
_make
(iterable) -
类方法从存在的序列或迭代实例创建一个新实例。
>>> t = [11, 22] >>> Point._make(t) Point(x=11, y=22)
somenamedtuple.
_asdict
()-
返回一个新的
dict
,它将字段名称映射到它们对应的值:>>> p = Point(x=11, y=22) >>> p._asdict() OrderedDict([('x', 11), ('y', 22)])
在 3.1 版更改: 返回一个
OrderedDict
而不是dict
。
somenamedtuple.
_replace
(**kwargs)-
返回一个新的命名元组实例,并将指定域替换为新的值
>>> p = Point(x=11, y=22) >>> p._replace(x=33) Point(x=33, y=22) >>> for partnum, record in inventory.items(): ... inventory[partnum] = record._replace(price=newprices[partnum], timestamp=time.now())
somenamedtuple.
_fields
-
字符串元组列出了域名。用于提醒和从现有元组创建一个新的命名元组类型。
>>> p._fields # view the field names ('x', 'y') >>> Color = namedtuple('Color', 'red green blue') >>> Pixel = namedtuple('Pixel', Point._fields + Color._fields) >>> Pixel(11, 22, 128, 255, 0) Pixel(x=11, y=22, red=128, green=255, blue=0)
somenamedtuple.
_field_defaults
-
默认值的字典。
>>> Account = namedtuple('Account', ['type', 'balance'], defaults=[0]) >>> Account._field_defaults {'balance': 0} >>> Account('premium') Account(type='premium', balance=0)
要获取这个名字域的值,使用 getattr()
函数 :
>>> getattr(p, 'x')
11
要将字典转换为命名元组,请使用 **
运算符(如 解包参数列表 中所述):
>>> d = {'x': 11, 'y': 22}
>>> Point(**d)
Point(x=11, y=22)
因为一个命名元组是一个正常的Python类,它可以很容易的通过子类更改功能。这里是如何添加一个计算域和定宽输出打印格式:
>>> class Point(namedtuple('Point', ['x', 'y'])):
... __slots__ = ()
... @property
... def hypot(self):
... return (self.x ** 2 + self.y ** 2) ** 0.5
... def __str__(self):
... return 'Point: x=%6.3f y=%6.3f hypot=%6.3f' % (self.x, self.y, self.hypot)
>>> for p in Point(3, 4), Point(14, 5/7):
... print(p)
Point: x= 3.000 y= 4.000 hypot= 5.000
Point: x=14.000 y= 0.714 hypot=14.018
上面的子类设置 __slots__
为一个空元组。通过阻止创建实例字典保持了较低的内存开销。
子类化对于添加和存储新的名字域是无效的。应当通过 _fields
创建一个新的命名元组来实现它:
>>> Point3D = namedtuple('Point3D', Point._fields + ('z',))
文档字符串可以自定义,通过直接赋值给 __doc__
属性:
>>> Book = namedtuple('Book', ['id', 'title', 'authors'])
>>> Book.__doc__ += ': Hardcover book in active collection'
>>> Book.id.__doc__ = '13-digit ISBN'
>>> Book.title.__doc__ = 'Title of first printing'
>>> Book.authors.__doc__ = 'List of authors sorted by last name'
在 3.5 版更改: 文档字符串属性变成可写。
默认值可以用 _replace()
来实现, 通过自定义一个原型实例:
>>> Account = namedtuple('Account', 'owner balance transaction_count')
>>> default_account = Account('<owner name>', 0.0, 0)
>>> johns_account = default_account._replace(owner='John')
>>> janes_account = default_account._replace(owner='Jane')
参见
-
请参阅
typing.NamedTuple
,以获取为命名元组添加类型提示的方法。 它还使用class
关键字提供了一种优雅的符号:class Component(NamedTuple): part_number: int weight: float description: Optional[str] = None
-
对于以字典为底层的可变域名, 参考
types.SimpleNamespace()
。 -
dataclasses
模块提供了一个装饰器和一些函数,用于自动将生成的特殊方法添加到用户定义的类中。 -
OrderedDict
对象有序词典就像常规词典一样,但有一些与排序操作相关的额外功能。由于内置的
dict
类获得了记住插入顺序的能力(在 Python 3.7 中保证了这种新行为),它们变得不那么重要了。一些与
dict
的不同仍然存在:-
常规的
dict
被设计为非常擅长映射操作。 跟踪插入顺序是次要的。 -
OrderedDict
旨在擅长重新排序操作。 空间效率、迭代速度和更新操作的性能是次要的。 -
算法上,
OrderedDict
可以比dict
更好地处理频繁的重新排序操作。 这使其适用于跟踪最近的访问(例如在 LRU cache 中)。 -
对于
OrderedDict
,相等操作检查匹配顺序。 -
OrderedDict
类的popitem()
方法有不同的签名。它接受一个可选参数来指定弹出哪个元素。 -
OrderedDict
类有一个move_to_end()
方法,可以有效地将元素移动到任一端。 -
Python 3.8之前,
dict
缺少__reversed__()
方法。
- class
collections.
OrderedDict
([items]) -
返回一个
dict
子类的实例,它具有专门用于重新排列字典顺序的方法。3.1 新版功能.
popitem
(last=True)-
有序字典的
popitem()
方法移除并返回一个 (key, value) 键值对。 如果 last 值为真,则按 LIFO 后进先出的顺序返回键值对,否则就按 FIFO 先进先出的顺序返回键值对。
move_to_end
(key, last=True)-
将现有 key 移动到有序字典的任一端。 如果 last 为真值(默认)则将元素移至末尾;如果 last 为假值则将元素移至开头。如果 key 不存在则会触发
KeyError
:>>> d = OrderedDict.fromkeys('abcde') >>> d.move_to_end('b') >>> ''.join(d.keys()) 'acdeb' >>> d.move_to_end('b', last=False) >>> ''.join(d.keys()) 'bacde'
3.2 新版功能.
相对于通常的映射方法,有序字典还另外提供了逆序迭代的支持,通过
reversed()
。OrderedDict
之间的相等测试是顺序敏感的,实现为list(od1.items())==list(od2.items())
。OrderedDict
对象和其他的Mapping
的相等测试,是顺序敏感的字典测试。这允许OrderedDict
替换为任何字典可以使用的场所。在 3.5 版更改:
OrderedDict
的项(item),键(key)和值(value) 视图 现在支持逆序迭代,通过reversed()
。在 3.6 版更改: PEP 468 赞成将关键词参数的顺序保留, 通过传递给
OrderedDict
构造器和它的update()
方法。OrderedDict
例子和用法创建记住键值 最后 插入顺序的有序字典变体很简单。 如果新条目覆盖现有条目,则原始插入位置将更改并移至末尾:
class LastUpdatedOrderedDict(OrderedDict): 'Store items in the order the keys were last added' def __setitem__(self, key, value): super().__setitem__(key, value) super().move_to_end(key)
一个
OrderedDict
对于实现functools.lru_cache()
的变体也很有用:class LRU(OrderedDict): 'Limit size, evicting the least recently looked-up key when full' def __init__(self, maxsize=128, *args, **kwds): self.maxsize = maxsize super().__init__(*args, **kwds) def __getitem__(self, key): value = super().__getitem__(key) self.move_to_end(key) return value def __setitem__(self, key, value): super().__setitem__(key, value) if len(self) > self.maxsize: oldest = next(iter(self)) del self[oldest
-