命名元组为元组中的每个位置分配了意义,并允许编写更易读、自说明的代码。它们可以用在普通元组可以使用的任何地方,并且它们增加了按名称而不是位置索引访问字段的能力。
collections.namedtuple(typename, field_names, *, rename=False, default=None, module=None)
返回一个名为typename的新元组子类。这个新的子类用于创建类似于元组的对象,这些对象可以通过属性查找访问字段,同时也可以通过索引和迭代进行访问。子类的实例还具有一个有用的文档字符串(包含typename和field_names),以及一个有用的__repr__()方法,它以name=value的格式列出了元组的内容。
field_names是一个字符串序列,例如[‘x’, ‘y’]。或者,field_names可以是一个单个字符串,其中每个字段名以空格和/或逗号分隔,例如’x y’或’x, y’。
可以使用任何有效的Python标识符作为字段名,但不能以下划线开头。有效的标识符由字母、数字和下划线组成,但不能以数字或下划线开头,并且不能是类似于class、for、return、global、pass或raise之类的关键字。
如果设置了rename参数为True,无效的字段名会自动替换为位置名称。例如,[‘abc’, ‘def’, ‘ghi’, ‘abc’]会被转换为[‘abc’, ‘_1’, ‘ghi’, ‘_3’],从而消除了关键字def和重复的字段名abc。
defaults可以是None或包含默认值的可迭代对象。由于带有默认值的字段必须位于没有默认值的字段之后,因此默认值将应用于最右侧的参数。例如,如果field_names为[‘x’, ‘y’, ‘z’],并且defaults为(1, 2),那么x将是一个必需的参数,y将默认为1,z将默认为2。
如果定义了module参数,那么命名元组的__module__属性将设置为该值。
命名元组的实例没有每个实例的字典,因此它们非常轻量级,并且不需要比普通元组更多的内存。
为了支持pickle(序列化),命名元组类应该被赋值给与typename匹配的变量。
# 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)
除了继承自元组的方法之外,命名元组还支持三个额外的方法和两个属性。为了防止与字段名冲突,这些方法和属性的名称以下划线开头。
这是一个从现有序列或可迭代对象创建新实例的类方法。
t = [11, 22]
Point._make(t)
# Point(x=11, y=22)
返回一个新的字典,将字段名映射到它们对应的值
p = Point(x=11, y=22)
p._asdict()
# {'x': 11, 'y': 22}
返回一个新的命名元组实例,用新值替换指定的字段
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())
返回一个字符串的元组,列出了字段名。对于内省和从现有命名元组创建新的命名元组类型非常有用。
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)
返回一个将字段名映射到默认值的字典。
Account = namedtuple('Account', ['type', 'balance'], defaults=[0])
Account._field_defaults
# {'balance': 0}
Account('premium')
# Account(type='premium', balance=0)