Именованные кортежи присваивают имя каждому значению элемента в кортеже и тем самым создают более читаемый код. Они могут использоваться везде, где используются обычные кортежи и добавляют возможность доступа к полям по имени вместо индекса позиции.
import collections ntuple = collections.namedtuple(typename, field_names, *, \ rename=False, defaults=None, module=None)
typename
- строка, имя именованного кортежа,field_names
- последовательность строк, имена элементов кортежа,rename
- bool
, авто-переименование повторяющихся имен элементов,defaults=None
- итерируемая последовательность, значения по умолчанию имен кортежа,module=None
- атрибут __module__
именованного кортежа.Класс namedtuple()
модуля collections
возвращает новый подкласс кортежа с именем typename
. Новый подкласс используется для создания объектов, похожих на кортежи, которые имеют индексируемые и итерируемые поля, доступные для поиска по атрибутам. Экземпляры подкласса также имеют полезную строку документации с typename
и field_names
, а так же метод __repr__()
, который перечисляет содержимое кортежа в формате name=value
.
Имена полей field_names
представляют собой последовательность строк, таких как ['x', 'y']
. В качестве альтернативы, field_names
может быть одной строкой, в которой каждое имя поля разделено пробелами и/или запятыми, например, 'x y'
или 'x, y'
.
Для имен полей (элементов кортежа) может использоваться любой действительный идентификатор Python, за исключением имен, начинающихся с подчеркивания. Допустимые идентификаторы состоят из букв, цифр и символов подчеркивания, но не начинаются с цифры или символа подчеркивания и не могут быть ключевыми словами, такими как class
, for
, return
, global
, pass
и т. д.
Если аргумент rename=True
, то недопустимые имена полей автоматически заменяются позиционными именами. Например ['abc', 'def', 'ghi', 'abc']
преобразуется в ['abc', '_1', 'ghi', '_3']
, исключая ключевое слово def
и повторяющееся имя поля abc
.
Значения аргумента defaults
могут быть None
или итерируемой последовательностью. Поскольку аргумента со значением по умолчанию должны идти после любых обязательных аргументов, то значения по умолчанию будут применяются к самым правым параметрам. Например, если имена полей именованного кортежа это ['x', 'y', 'z']
, а значения по умолчанию (1, 2)
, то тогда x
будет обязательным аргументом, y
по умолчанию будет 1, а z
будет 2.
Если аргумент module
определен, то атрибуту именованного кортежа __module__
присваивается значение module
.
Экземпляры именованных кортежей не имеют словарей, поэтому они легковесны и требуют не больше памяти, чем обычные кортежи.
# Простой пример >>> from collections import namedtuple >>> Point = namedtuple('Point', ['x', 'y']) # создаем с позиционным или именованным параметром >>> p = Point(11, y=22) # можно обращаться по индексу # как к обычному кортежу >>> p[0] + p[1] # 33 # распаковать как обычный кортеж >>> x, y = p >>> x, y # (11, 22) # поля также доступны по названию >>> p.x + p.y # 33 # человеко-читаемый __repr__ >>> p # Point(x=11, y=22)
Именованные кортежи поддерживают функцию getattr()
:
>>> getattr(p, 'x') # 11
В дополнение к методам, унаследованным от кортежей, именованные кортежи поддерживают три дополнительных метода и два атрибута. Чтобы избежать конфликтов с именами полей, имена методов и атрибутов начинаются с подчеркивания.
NamedTuple
, атрибуты и методы:NamedTuple._make(iterable)
:Метод NamedTuple._make()
создает новый экземпляр класса namedtuple()
из существующей последовательности или итерации iterable
.
>>> t = [11, 22] >>> Point._make(t) # Point(x=11, y=22)
NamedTuple._asdict()
:Метод NamedTuple._asdict()
вернет новый словарь dict
, который отображает имена полей в соответствии с их значениями:
>>> p = Point(x=11, y=22) >>> p._asdict() # {'x': 11, 'y': 22}
NamedTuple._replace(**kwargs)
:Метод NamedTuple._replace()
вернет новый экземпляр именованного кортежа, заменив указанные поля новыми значениями:
>>> >>> 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())
NamedTuple._fields
:Свойство NamedTuple._fields
вернет кортеж строк, перечисляющий имена полей. Полезно для самоанализа и для создания новых именованных типов кортежей из существующих именованных кортежей.
# просмотр имен полей >>> p._fields # ('x', 'y') # создание нового именованного кортежа # на основе Pixel (созданного ранее) и Color >>> 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)
NamedTuple._field_defaults
:Свойство NamedTuple._field_defaults
вернет словарь, который сопоставляет имена полей со значениями по умолчанию.
>>> Account = namedtuple('Account', ['type', 'balance'], defaults=[0]) >>> Account._field_defaults # {'balance': 0} >>> Account('premium') # Account(type='premium', balance=0)
Чтобы преобразовать словарь в именованный кортеж, используйте оператор двойной звезды **
как описано в разделе "Распаковка списков аргументов":
>>> from collections import namedtuple >>> Point = namedtuple('Point', ['x', 'y']) >>> d = {'x': 11, 'y': 22} >>> Point(**d) # Point(x=11, y=22)
Именованные кортежи особенно полезны для присвоения имен полей в результате кортежей, возвращаемых модулями csv
или sqlite3
:
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)
Поскольку именованный кортеж является обычным классом Python, его легко добавить или изменить с помощью подкласса. Вот как добавить вычисляемое поле и формат печати фиксированной ширины:
from collections import namedtuple 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
:
>>> from collections import namedtuple >>> Point = namedtuple('Point', ['x', 'y']) >>> Point3D = namedtuple('Point3D', Point._fields + ('z',)) >>> Point3D(10, 20, 30) Point3D(x=10, y=20, z=30)
Строки документов могут быть настроены путем прямого назначения значения атрибуту __doc__
:
>>> from collections import namedtuple >>> 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'