collections.namedtuple 用法详解完整版

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。有效标识符由字母,数字和下划线组成,但不能以数字或下划线开头,并且不能是诸如classforreturnglobalpassraise之类的关键字。

>>> 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
如果 renameTrue,不合法的 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 的默认值是 1z 的默认值是 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 在对 csvsqlite3 模块返回的结果元组进行 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'

你可能感兴趣的:(python)