collections.namedtuple(typename, field_names, *, rename=False, defaults=None, module=None)
typename
返回的是一个名为 typename
的元组子类。
这个返回的子类用于创建类似元组的对象,这些对象具有可通过属性查找访问的字段以及可索引和可迭代的字段。
field_names
field_names
是形如 [ 'x', 'y' ]
的字符串序列。或者为另外两种形式,以逗号或空格分隔的字符串,如 ‘x, y'
和 ’x y'
。
除下划线开头的名称外,任何有效的 Python
标识符均可用于 fieldname
。有效标识符由字母,数字和下划线组成,但不能以数字或下划线开头,并且不能是诸如class
,for
,return
,global
,pass
或raise
之类的关键字。
>>> from collections import namedtuple
>>> Point = namedtuple('Point', ['x', 'y'])
# Point = namedtuple('Point', 'x, y')
# Point = namedtuple('Point', 'x y')
>>> p = Point(11, y=22)
# p = Point(11, 22)
# p = Point(x=11, y=22)
>>> p[0]+p[1]
# p.x+p.y
# getattr(p,'x') + getattr(p,'y')
33
>>>
>>> x, y = p # unpack
>>> x, y
(11, 22)
rename
如果 rename
是True
,不合法的 fieldname
会被自动替换为位置名。例如,['abc', 'def', 'ghi', 'abc']
会变为 ['abc', '_1', 'ghi', '_3']
,用 _1
替换了关键字 def
,用 _3
替换了重复出现的 abc
。
合法 fieldname
>>> from collections import namedtuple
>>> Point = namedtuple('Point', ['x', 'y'],rename=True)
>>> Point._fields
('x', 'y')
>>> Point(11,22)
Point(x=11, y=22)
不合法 fieldname
>>> from collections import namedtuple
>>> Point = namedtuple('Point', ['class', 'def'],rename=True)
>>> Point._fields
('_0', '_1')
>>> Point(11,22)
Point(_0=11, _1=22)
defaults
defaults
可以是 None
或者可迭代的默认值。而且 defaults
从右往左匹配。
例如,如果 fieldnames
是 ['x', 'y', 'z']
,defaults
是 (1,2)
,那么x
是需要传入的参数, y
的默认值是 1
,z
的默认值是 2
。
>>> from collections import namedtuple
>>> Point = namedtuple('Point', ['x', 'y', 'z'], defaults=(1,2))
>>> Point(3)
Point(x=3, y=1, z=2)
>>> Point(3,4)
Point(x=3, y=4, z=2)
>>> Point(3,4,5)
Point(x=3, y=4, z=5)
module
如果 module
被定义了,那么 named tuple
的 __module__
属性会被设为该值。
>>> from collections import namedtuple
>>> import numpy
>>> Point = namedtuple('Point', ['x', 'y'],module=numpy)
>>> Point.__module__
<module 'numpy' from 'D:\\Users\\lenovo\\Anaconda3\\lib\\site-packages\\numpy\\__init__.py'>
————————————————————
namedtuple
实例没有 per-instance
的字典,因此它们是轻量级的,并且比常规元组不需要更多的内存。
named tuples
在对 csv
或 sqlite3
模块返回的结果元组进行 field
分配时特别有用。
from collections import namedtuple
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)
除了从元组中继承到的方法, named tuples
还支持三种额外的方法和两种属性。为了避免和 field names
产生矛盾,这些方法和属性名以下划线开头。
classmethod somenamedtuple._make(iterable)
类方法,从现有的序列或可迭代对象中创建一个新的实例。
>>> t = [11, 22]
>>> Point._make(t)
Point(x=11, y=22)
somenamedtuple._asdict()
返回一个新的字典,将 field names
映射到对应的值。
>>> p = Point(x=11, y=22)
>>> p._asdict()
{'x': 11, 'y': 22}
python 3.1 - 3.7
中,这里返回的字典是有序字典 OrderedDict
python 3.8
中,这里返回的字典是普通字典 dict
somenamedtuple._replace(**kwargs)
返回一个新的实例,将指定的 field
替换为新的值
>>> 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
以元组形式返回所有 field names
。在从现有 name tuples
中创建新的 named tuple
时很有用。
>>> Point._fields # 查看 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
返回映射 field names
到默认值的字典。
>>> Account = namedtuple('Account', ['type', 'balance'], defaults=[0])
>>> Account._field_defaults
{'balance': 0}
>>> Account('premium')
Account(type='premium', balance=0)
————————————————————————————————
要检索名称存储在字符串中的 field
,使用 getattr()
:
>>> getattr(p, 'x')
11
为了把字典转为 named tuple
,使用 **
操作符:
>>> d = {'x': 11, 'y': 22}
>>> Point(**d)
Point(x=11, y=22)
因为 named tuple
是一个常规的 Python
类,所以可以很容易地用一个子类来增加或改变函数。下面展示如何增加一个 calculated field
和 一个固定宽度的打印格式:
>>> 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
时,子类不是很有用,比较有用的是简单的从 _fields
属性中创建一个新的 named tuple
:
>>> Point._fields # Point 指的是上面的类 Point
('x', 'y')
>>> Point3D = namedtuple('Point3D', Point._fields + ('z',))
Docstrings
能够通过修改 __doc__ fields
实现定制化:
>>> 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'