Namedtuple python 3 методы

№36 Namedtuple (именные кортежи) / для начинающих

Именованные кортежи ( namedtuple ) — это подкласс кортежей в Python. У них те же функции, что и у обычных, но их значения можно получать как с помощью имени (через точку, например, .name ), так и с помощью индекса (например [0] ). В этом материале на примерах разберем синтаксис и функции этих кортежей.

Зачем нужны именованные кортежи?

Именованные кортежи улучшают читаемость кода и отдельных функций.

Разберемся на примере. Предположим, что есть программа, которая сохраняет оценки студента в кортеже под названием marks . Но с этим кодом комфортно работать, если помнить назначение кортежа. Однако, скорее всего, оно забудется уже через несколько дней.

 
marks = (98, 80, 95)
print(marks)
print(marks[0])
print(marks[2])

Namedtuple — это замена обычных кортежей. Они выполняют те же функции, но улучшают читаемость кода. Даже если программист приостановит работу над программой на несколько месяцев, синтаксис или значение самого кортежа будут говорить сами за себя. Теперь время поговорить о самом синтаксисе таких кортежей.

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

По сравнению с другими структурами данных в Python (список, словарь, кортеж и множество) именованный кортеж — не часть стандартной библиотеки. Он доступен в модуле collections . Последний включает и другие альтернативы встроенных структур в Python.

 
from collections import namedtuple

Когда namedtuple импортирован, можно переходить к его использованию.

Синтаксис namedtuple в Python

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

Создание именованного кортежа

Мы уже импортировали именованный кортеж, теперь рассмотрим синтаксис.

 
from collections import namedtuple

Marks = namedtuple('Marks', 'Physics Chemistry Math English')
marks = Marks(90, 85, 95, 100)
print(marks)
Marks(Physics=90, Chemistry=85, Math=95, English=100)

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

В качестве второго параметра можно использовать итерируемую структуру данных: список, словарь, кортеж или множество.
Если же это строка, то разные имена нужно разделить с помощью отдельного символа.

marks = Marks(90, 85, 95, 100) — эта строка создает именованный кортеж. «Marks» — это объявление именованного кортежа, которое может использоваться для создания бесконечного количества аналогичных структур. Это еще называется фабрикой именованных кортежей.

Позиционные аргументы соответствуют определению кортежа.
Для улучшения читабельности можно создавать именованные кортежи с помощью ключевых слов: marks = Marks(Physics=90, Chemistry=85, Math=95, English=100) .

Создание namedtuple с помощью списка

 
from collections import namedtuple

lst = ['Physics', 'Chemistry', 'Math', 'English']
Marks = namedtuple('Marks', lst)
marks = Marks(90, 85, 95, 100)
print(marks)

Создание namedtuple с помощью словаря

Стартовое значение словаря — 0 , поскольку значение поля игнорируется кортежем.

 
from collections import namedtuple

dct =
Marks = namedtuple('Marks', dct)
marks = Marks(90, 85, 95, 100)
print(marks)

Источник

Именованные кортежи. Пишем код на Python чище

В стандартной библиотеке питона содержится специализированный тип "namedtuple", который, кажется, не получает того внимания, которое он заслуживает. Это одна из прекрасных фич в питоне, которая скрыта с первого взгляда.

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

Так что же такое именованный кортеж и что делает его таким специализированным? Хороший способ поразмышлять над этим — рассмотреть именованные кортежи как расширение над обычными кортежами.

Кортежи в питоне представляют собой простую структуру данных для группировки произвольных объектов. Кортежи являются неизменяемыми — они не могут быть изменены после их создания.

>>> tup = ('hello', object(), 42) >>> tup ('hello', , 42) >>> tup[2] 42 >>> tup[2] = 23 TypeError: "'tuple' object does not support item assignment"

Обратная сторона кортежей — это то, что мы можем получать данные из них используя только числовые индексы. Вы не можете дать имена отдельным элементам сохранённым в кортеже. Это может повлиять на читаемость кода.

Также, кортеж всегда является узкоспециализированной структурой. Тяжело обеспечить, чтобы два кортежа имели одни и те же номера полей и одни и те же свойства сохранённые в них. Это делает их лёгкими для знакомства со “slip-of-the-mind” багами, где легко перепутать порядок полей.

Именованные кортежи идут на выручку

Цель именованных кортежей — решить эти две проблемы.

Прежде всего, именованные кортежи являются неизменяемыми подобно обычным кортежам. Вы не можете изменять их после того, как вы что-то поместили в них.

Кроме этого, именованные кортежи это, эм. именованные кортежи. Каждый объект сохраненный в них может быть доступен через уникальный, удобный для чтения человеком, идентификатор. Это освобождает вас от запоминания целочисленных индексов или выдумывания обходных путей типа определения целочисленных констант как мнемоник для ваших индексов.

Вот как выглядит именованный кортеж:

>>> from collections import namedtuple >>> Car = namedtuple('Car' , 'color mileage')

Чтобы использовать именованный кортеж, вам нужно импортировать модуль collections . Именованные кортежи были добавлены в стандартную библиотеку в Python 2.6. В примере выше мы определили простой тип данных "Car" с двумя полями: "color" и "mileage".

Вы можете найти синтакс немного странным здесь. Почему мы передаём поля как строку закодированную с "color mileage"?

Ответ в том, что функция фабрики именованных кортежей вызывает метод split() на строки с именами полей. Таким образом, это, действительно, просто сокращение, чтобы сказать следующее:

>>> 'color mileage'.split() ['color', 'mileage'] >>> Car = namedtuple('Car', ['color', 'mileage'])

Конечно, вы также можете передать список со строками имён полей напрямую, если вы предпочитаете такой стиль. Преимущество использования списка в том, что в этом случае легко переформатировать этот код, если вам понадобится разделить его на несколько линий:

>>> Car = namedtuple('Car', [ . 'color', . 'mileage', . ])

Как бы вы ни решили, сейчас вы можете создать новые объекты "car" через фабричную функцию Car . Поведение будет такое же, как если бы вы решили определить класс Car вручную и дать ему конструктор принимающий значения "color" и "mileage":

>>> my_car = Car('red', 3812.4) >>> my_car.color 'red' >>> my_car.mileage 3812.4

Распаковка кортежей и оператор '*' для распаковки аргументов функций также работают как ожидается:

>>> color, mileage = my_car >>> print(color, mileage) red 3812.4 >>> print(*my_car) red 3812.4

Несмотря на доступ к значениям сохранённым в именованном кортеже через их идентификатор, вы всё ещё можете обращаться к ним через их индекс. Это свойство именованных кортежей может быть использовано для их распаковки в обычный кортеж:

>>> my_car[0] 'red' >>> tuple(my_car) ('red', 3812.4)

Вы даже можете получить красивое строковое отображение объектов бесплатно, что сэкономит вам время и спасёт от избыточности:

>>> my_car Car(color='red' , mileage=3812.4)

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

>>> my_car.color = 'blue' AttributeError: "can't set attribute"

Объекты именованных кортежей внутренне реализуются в питоне как обычные классы. Когда дело доходит до использованию памяти, то они так же "лучше", чем обычные классы и просто так же эффективны в использовании памяти как и обычные кортежи.

Хороший путь судить о них — считать, что именованные кортежи являются краткой формой для создания вручную эффективно работающего с памятью неизменяемого класса.

Наследование от именованных кортежей

Поскольку именованные кортежи построены на обычных классах, то вы можете добавить методы в класс, унаследованный от именованного кортежа.

>>> Car = namedtuple('Car', 'color mileage') >>> class MyCarWithMethods(Car): . def hexcolor(self): . if self.color == 'red': . return '#ff0000' . else: . return '#000000'

Сейчас мы можем создать объекты MyCarWithMethods и вызвать их метод hexcolor() так, как ожидалось:

>>> c = MyCarWithMethods('red', 1234) >>> c.hexcolor() '#ff0000'

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

Например, добавление нового неизменяемого поля является каверзной операцией из-за того как именованные кортежи устроены внутри. Более простой путь создания иерархии именованных кортежей — использование свойства ._fields базового кортежа:

>>> Car = namedtuple('Car', 'color mileage') >>> ElectricCar = namedtuple( . 'ElectricCar', Car._fields + ('charge',))

Это даёт желаемый результат:

>>> ElectricCar('red', 1234, 45.0) ElectricCar(color='red', mileage=1234, charge=45.0)

Встроенные вспомогательные методы именованного кортежа

Кроме свойства _fields каждый экземпляр именованного кортежа также предоставляет ещё несколько вспомогательных методов, которые вы можете найти полезными. Все их имена начинаются со знака подчёркивания, который говорит нам, что метод или свойство "приватное" и не является частью устоявшегося интерфейса класса или модуля.

Что касается именованных кортежей, то соглашение об именах начинающихся со знака подчёркивания здесь имеет другое значение: эти вспомогательные методы и свойства являются частью открытого интерфейса именованных кортежей. Символ подчёркивания в этих именах был использован для того, чтобы избежать коллизий имён с полями кортежа, определёнными пользователем. Так что, не стесняйтесь использовать их, если они вам понадобятся!

Я хочу показать вам несколько сценариев где вспомогательные методы именованного кортежа могут пригодиться. Давайте начнём с метода _asdict(). Он возвращает содержимое именованного кортежа в виде словаря:

>>> my_car._asdict() OrderedDict([('color', 'red'), ('mileage', 3812.4)])

Это очень здорово для избегания опечаток при создании JSON, например:

Другой полезный помощник — функция _replace(). Она создаёт поверхностную(shallow) копию кортежа и разрешает вам выборочно заменять некоторые поля:

>>> my_car._replace(color='blue') Car(color='blue', mileage=3812.4)

И, наконец, метод класса _make() может быть использован чтобы создать новый экземпляр именованного кортежа из последовательности:

>>> Car._make(['red', 999]) Car(color='red', mileage=999)

Когда стоит использовать именованные кортежи

Именованные кортежи могут быть простым способом для построения вашего кода, делая его более читаемым и обеспечивая лучшее структурирование ваших данных.

Я нахожу, например, что путь от узкоспециализированных структур данных с жёстко заданным форматом, таких как словари к именованным кортежам помогает мне выражать мои намерения более чисто. Часто когда я пытаюсь это рефакторить, то я магически достигаю лучших решений проблем, с которыми я сталкиваюсь.

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

С другой стороны, я стараюсь не использовать именованные кортежи ради их пользы, если они не помогают мне писать чище, читабельнее и не делают код более лёгким в сопровождении. Слишком много хороших вещей может оказаться плохой вещью.

Однако, если вы используете их с осторожностью, то именованные кортежи, без сомнения, могут сделать ваш код на Python лучше и более выразительным.

Что нужно запомнить

  • collections.namedtuple — краткая форма для создания вручную эффективно работающего с памятью неизменяемого класса.
  • Именованные кортежи могут помочь сделать ваш код чище, обеспечивая вас более простыми в понимании структурами данных.
  • Именованные кортежи предоставляют несколько полезных вспомогательных методов которые начинаются с символа подчёркивания (_), но являются частью открытого интерфейса. Использовать их — это нормальная практика.

Источник

Читайте также:  Strtolower для кириллицы php
Оцените статью