Именованные кортежи - это, в основном, простые в создании, легковесные типы объектов. Ссылки на экземпляры именованных кортежей можно использовать объектно-подобное разыменование переменных или стандартный синтаксис кортежей. Они могут использоваться аналогично struct или другим распространенным типам записей, за исключением того, что они неизменяемы. Они были добавлены в Python 2.6 и Python 3.0, хотя есть рецепт для реализации в Python 2.4.
Например, точку принято представлять в виде кортежа (x, y). Это приводит к коду, подобному следующему:
pt1 = (1.0, 5.0) pt2 = (2.5, 1.5)
from math import sqrt line_length = sqrt((pt1[0]-pt2[0])**2 + (pt1[1]-pt2[1])**2)
Использование именованного кортежа становится более читабельным:
from collections import namedtuple Point = namedtuple('Point', 'x y') pt1 = Point(1.0, 5.0) pt2 = Point(2.5, 1.5)
from math import sqrt line_length = sqrt((pt1.x-pt2.x)**2 + (pt1.y-pt2.y)**2)
Однако именованные кортежи по-прежнему обратно совместимы с обычными кортежами, поэтому следующее все равно будет работать:
from math import sqrt # use index referencing line_length = sqrt((pt1[0]-pt2[0])**2 + (pt1[1]-pt2[1])**2) # use tuple unpacking x1, y1 = pt1
Таким образом, вам следует использовать именованные кортежи вместо кортежей везде, где, по вашему мнению, объектная нотация сделает ваш код более питонистским и более легко читаемым. Я лично начал использовать их для представления очень простых типов значений, особенно при передаче их в качестве параметров функциям. Это делает функции более удобочитаемыми, не видя контекста упаковки кортежей.
Кроме того, вы также можете заменить обычные неизменяемые классы, у которых нет функций, только поля с ними. Вы даже можете использовать свои именованные типы кортежей в качестве базовых классов:
classPoint(namedtuple('Point', 'x y')): [...]
Однако, как и в случае с кортежами, атрибуты в именованных кортежах неизменяемы:
>>> Point = namedtuple('Point', 'x y') >>> pt1 = Point(1.0, 5.0) >>> pt1.x = 2.0 AttributeError: can't set attribute
Если вы хотите иметь возможность изменять значения, вам нужен другой тип. Существует удобный рецепт для изменяемых типов записей, которые позволяют вам устанавливать новые значения для атрибутов.
Однако я не знаю ни о какой форме "именованного списка", которая позволяет добавлять новые поля. Возможно, в этой ситуации вам просто захочется использовать словарь. Именованные кортежи могут быть преобразованы в словари с помощью pt1._asdict() который возвращает {'x': 1.0, 'y': 5.0}, и с ними можно работать с помощью всех обычных функций словаря.
Как уже отмечалось, вам следует проверить документацию для получения дополнительной информации, на основе которой были созданы эти примеры.
Ответ 2
Что такое именованные кортежи?
Именованный кортеж - это кортеж.
Он делает все, что может кортеж.
Но это больше, чем просто кортеж.
Это определенный подкласс кортежа, который программно создается в соответствии с вашей спецификацией, с именованными полями и фиксированной длиной.
Это, например, создает подкласс tuple , и помимо того, что он имеет фиксированную длину (в данном случае три), его можно использовать везде, где используется кортеж, без разрыва. Это известно как заменяемость по Лискову.
classANamedTuple(NamedTuple): """a docstring""" 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', [])
Мы можем проверить это и использовать его атрибуты:
Чтобы понять, что такое именованные кортежи, вам сначала нужно знать, что такое кортеж. Кортеж по сути представляет собой неизменяемый (не может быть изменен на месте в памяти) список.
Где обычно определяется именованный кортеж в большом скрипте или программе?
Типы, которые вы создаете с помощью namedtuple, в основном представляют собой классы, которые вы можете создавать с помощью простого сокращения. Относитесь к ним как к классам. Определите их на уровне модуля, чтобы pickle и другие пользователи могли их найти.
Рабочий пример на уровне глобального модуля:
>>> from collections import namedtuple >>> NT = namedtuple('NT', 'foo bar') >>> nt = NT('foo', 'bar') >>> import pickle >>> pickle.loads(pickle.dumps(nt)) NT(foo='foo', bar='bar')
И это демонстрирует невозможность поиска определения:
Почему / когда я должен использовать именованные кортежи вместо обычных?
Используйте их, когда хотите улучшить свой код, чтобы семантика элементов кортежей была выражена в вашем коде.
Вы можете использовать их вместо объекта, если в противном случае вы использовали бы объект с неизменяемыми атрибутами данных и без какой-либо функциональности.
Почему / когда я должен использовать обычные кортежи вместо именованных?
Вероятно, переход от использования именованных кортежей к кортежам был бы регрессией. Первоначальное проектное решение сосредоточено на том, оправдывают ли затраты на дополнительный код улучшенную читаемость при использовании кортежа.
Именованные кортежи не используют дополнительной памяти по сравнению с кортежами.
Существует ли какой-либо "именованный список" (изменяемая версия именованного кортежа)?
Вы ищете либо щелевой объект, который реализует все функциональные возможности списка статического размера, либо подклассный список, который работает как именованный кортеж (и который каким-то образом блокирует изменение размера списка).
Теперь расширенный и, возможно, даже заменяемый по Лискову пример первого:
from collections importSequence
classMutableTuple(Sequence): """Abstract Base Class for objects that work like mutable namedtuples. Subclass and define your named fields with __slots__ and away you go. """ __slots__ = () def__init__(self, *args): for slot, arg inzip(self.__slots__, args): setattr(self, slot, arg) def__repr__(self): returntype(self).__name__ + repr(tuple(self)) # more direct __iter__ than Sequence's def__iter__(self): for name in self.__slots__: yieldgetattr(self, name) # Sequence requires __getitem__ & __len__: def__getitem__(self, index): returngetattr(self, self.__slots__[index]) def__len__(self): returnlen(self.__slots__)
И для использования просто создайте подкласс и определите __slots__:
>>> student = Student('Lisa', 'Simpson', 'A') >>> student Student('Lisa', 'Simpson', 'A') >>> first, last, grade = student >>> first 'Lisa' >>> last 'Simpson' >>> grade 'A' >>> student[0] 'Lisa' >>> student[2] 'A' >>> len(student) 3 >>> 'Lisa'in student True >>> 'Bart'in student False >>> student.first = 'Bart' >>> for i in student: print(i) ... Bart Simpson A
Ответ 3
namedtuple - это фабричная функция для создания класса tuple. С помощью этого класса мы можем создавать кортежи, которые также можно вызывать по имени.
import collections
#Create a namedtuple class with names "a" "b" "c" Row = collections.namedtuple("Row", ["a", "b", "c"])
row = Row(a=1,b=2,c=3) #Make a namedtuple from the Row class we created
row = Row._make([2, 3, 4]) #Make a namedtuple from a list of values
print row #Prints: Row(a=2, b=3, c=4)
Ответ 4
именованные кортежи - отличная функция, они являются идеальным контейнером для данных. Когда вам нужно "хранить" данные, вы бы использовали кортежи или словари, например:
user = dict(name="John", age=20)
или:
user = ("John", 20)
Словарный подход является подавляющим, поскольку dict изменяемы и работают медленнее, чем кортежи. С другой стороны, кортежи неизменяемы и легковесны, но им не хватает удобочитаемости для большого количества записей в полях данных.
namedtuples - идеальный компромисс для двух подходов, они обладают отличной читабельностью, малым весом и неизменяемостью (плюс они полиморфны!).