Что такое "именованные кортежи" в Python?
- Что такое именованные кортежи?
- Как их можно использовать?
- Где нужно использовать именованные кортежи вместо обычных?
P. S. Это перевод вопроса c enSO. Интересующихся темой "зачем делать такие переводы" прошу сюда.
Ответы (1 шт):
Что такое именованные кортежи?
Именованные кортежи — это кортежи.
Они могут делать все, что и обычные кортежи.
Но они — больше чем кортежи.
Это — подкласс кортежей, который программным образом создается в соответствии с вашими требованиями (именованные поля и фиксированная длина).
В следующем примере, например, создается подкласс кортежа, и не считая того, что он имеет фиксированную длину (в данном случае три), его без проблем можно использовать везде, где и обычный кортеж. Это известно как принцип подстановки Лисков.
Начиная с Python 3.6 для создания именованного кортежа можно использовать определение класса typing.NamedTuple:
from typing import NamedTuple
class ANamedTuple(NamedTuple):
"""строка документации"""
foo: int
bar: str
baz: list
Пример выше аналогичен классу collections.namedtuple, за исключением того, что он имеет аннотации типов и строку документации. А вот это можно использовать в Python 2 и выше:
>>> from collections import namedtuple
>>> class_name = 'ANamedTuple'
>>> fields = 'foo bar baz'
>>> ANamedTuple = namedtuple(class_name, fields)
Пример создания экземпляра:
>>> ant = ANamedTuple(1, 'bar', [])
Проверяем его и используем атрибуты:
>>> ant
ANamedTuple(foo=1, bar='bar', baz=[])
>>> ant.foo
1
>>> ant.bar
'bar'
>>> ant.baz.append('anything')
>>> ant.baz
['anything']
Более глубокое объяснение:
Чтобы понять концепцию именованных кортежей, нужно сначала понять, что такое кортеж. Кортеж — это, по существу, неизменяемый список (его нельзя изменить в памяти на месте).
Вот пример использования обычного кортежа:
>>> student_tuple = 'Lisa', 'Simpson', 'A'
>>> student_tuple
('Lisa', 'Simpson', 'A')
>>> student_tuple[0]
'Lisa'
>>> student_tuple[1]
'Simpson'
>>> student_tuple[2]
'A'
Его можно "развернуть" с помощью итеративной распаковки:
>>> first, last, grade = student_tuple
>>> first
'Lisa'
>>> last
'Simpson'
>>> grade
'A'
Именованные кортежи — это кортежи, которые позволяют осуществлять доступ к своим элементам по имени, а не просто через индекс!
Например, можно создать такой именованный кортеж:
>>> from collections import namedtuple
>>> Student = namedtuple('Student', ['first', 'last', 'grade'])
Для улучшения читабельности можно также передавать не список, а строку, включающую имена, разделенные пробелами:
>>> Student = namedtuple('Student', 'first last grade')
Как их использовать?
С ними можно делать все, что и с обычными кортежами (смотри выше) а также следующее:
>>> named_student_tuple = Student('Lisa', 'Simpson', 'A')
>>> named_student_tuple.first
'Lisa'
>>> named_student_tuple.last
'Simpson'
>>> named_student_tuple.grade
'A'
>>> named_student_tuple._asdict()
OrderedDict([('first', 'Lisa'), ('last', 'Simpson'), ('grade', 'A')])
>>> vars(named_student_tuple)
OrderedDict([('first', 'Lisa'), ('last', 'Simpson'), ('grade', 'A')])
>>> new_named_student_tuple = named_student_tuple._replace(first='Bart', grade='C')
>>> new_named_student_tuple
Student(first='Bart', last='Simpson', grade='C')
Когда/зачем вместо обычных кортежей следует использовать именованные?
Их можно использовать вместо объекта (если бы в противном случае вы использовали бы объект с неизменяемыми атрибутами и без функций).
Возможность добавлять функции можно осуществить через подкласс:
class Point(namedtuple('Point', 'x y')):
"""adding functionality to a named tuple"""
__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)