Сообщить об ошибке.

Класс namedtuple() модуля collections в Python

Именованные кортежи в Python

Именованные кортежи присваивают имя каждому значению элемента в кортеже и тем самым создают более читаемый код. Они могут использоваться везде, где используются обычные кортежи и добавляют возможность доступа к полям по имени вместо индекса позиции.

Синтаксис:

import collections

ntuple = collections.namedtuple(typename, field_names, *, \
                                rename=False, defaults=None, module=None)

Параметры:

Возвращаемое значение:

Описание:

Класс 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'