Пропустить до содержимого

Как использовать namedtuple в Python?

[

Напишите чистый и пайтонический код с помощью namedtuple

Python-модуль collections предоставляет фабричную функцию namedtuple(), специально разработанную для того, чтобы ваш код стал более “pythonic” при работе с кортежами. С помощью namedtuple() вы можете создавать неизменяемые типы последовательностей, которые позволяют обращаться к их значениям с использованием описательных имен полей и синтаксиса с точкой вместо непонятных целочисленных индексов.

Если у вас есть опыт использования Python, то вы знаете, что написание “pythonic” кода - это основное умение для разработчиков на Python. В этом руководстве вы улучшите свои навыки с помощью namedtuple.

* Использование namedtuple для написания “pythonic” кода

from collections import namedtuple
# Создание namedtuple класса
Person = namedtuple('Person', ['name', 'age', 'gender'])
# Создание экземпляра namedtuple
person = Person('John', 30, 'Male')
# Обращение к значениям через имена полей
print(person.name) # John
print(person.age) # 30
print(person.gender) # Male

* Создание классов похожих на кортежи с помощью namedtuple()

В namedtuple() можно передавать необязательные аргументы, чтобы добавить дополнительные возможности к создаваемым классам.

- Предоставление обязательных аргументов для namedtuple()

from collections import namedtuple
Person = namedtuple('Person', ['name', 'age', 'gender'], defaults=['Unknown'])
# Создание экземпляра namedtuple без указания значения по умолчанию
person1 = Person('John', 30, 'Male')
# Создание экземпляра namedtuple с указанием значения по умолчанию
person2 = Person('Jane', 25)
print(person1) # Person(name='John', age=30, gender='Male')
print(person2) # Person(name='Jane', age=25, gender='Unknown')

- Использование необязательных аргументов с помощью namedtuple()

from collections import namedtuple
# Создание namedtuple класса с необязательными аргументами
Person = namedtuple('Person', ['name', 'age', 'gender'], defaults=[None, None, 'Unknown'])
person1 = Person('John', 30, 'Male')
person2 = Person('Jane', 25)
print(person1) # Person(name='John', age=30, gender='Male')
print(person2) # Person(name='Jane', age=25, gender='Unknown')

* Исследование дополнительных возможностей классов namedtuple

- Создание экземпляров namedtuple из итерируемых объектов

from collections import namedtuple
Person = namedtuple('Person', ['name', 'age', 'gender'])
# Создание экземпляра namedtuple из списка
data = ['John', 30, 'Male']
person1 = Person._make(data)
# Создание экземпляра namedtuple из словаря
data = {'name': 'Jane', 'age': 25, 'gender': 'Female'}
person2 = Person(**data)
print(person1) # Person(name='John', age=30, gender='Male')
print(person2) # Person(name='Jane', age=25, gender='Female')

- Преобразование экземпляров namedtuple в словари

from collections import namedtuple
Person = namedtuple('Person', ['name', 'age', 'gender'])
person = Person('John', 30, 'Male')
# Преобразование экземпляра namedtuple в словарь
person_dict = person._asdict()
print(person_dict) # {'name': 'John', 'age': 30, 'gender': 'Male'}

- Замена полей в существующих экземплярах namedtuple

from collections import namedtuple
Person = namedtuple('Person', ['name', 'age', 'gender'])
person = Person('John', 30, 'Male')
# Замена значения поля 'age'
person = person._replace(age=40)
print(person) # Person(name='John', age=40, gender='Male')

- Исследование дополнительных атрибутов классов namedtuple

from collections import namedtuple
Person = namedtuple('Person', ['name', 'age', 'gender'])
person = Person('John', 30, 'Male')
# Получение имен полей
field_names = person._fields
# Получение количества полей
num_fields = person._field_defaults
print(field_names) # ('name', 'age', 'gender')
print(num_fields) # {}

* Написание “pythonic” кода с использованием namedtuple

- Использование имен полей вместо индексов

from collections import namedtuple
Person = namedtuple('Person', ['name', 'age', 'gender'])
person = Person('John', 30, 'Male')
# Использование имен полей вместо индексов
name = person.name
age = person.age
gender = person.gender
print(f"Name: {name}, Age: {age}, Gender: {gender}")

- Возвращение нескольких именованных значений из функций

from collections import namedtuple
Person = namedtuple('Person', ['name', 'age', 'gender'])
# Возвращение нескольких именованных значений из функции
def get_person_details():
return Person('John', 30, 'Male')
person = get_person_details()
print(person) # Person(name='John', age=30, gender='Male')

- Сокращение количества аргументов функций

namedtuple можно использовать для уменьшения количества аргументов функций.

from collections import namedtuple
Transaction = namedtuple('Transaction', ['sender', 'receiver', 'amount'])
# Использование namedtuple для сокращения количества аргументов функции
def process_transaction(transaction):
# Обработка транзакции
...
print(f"Transaction processed: {transaction}")
transaction = Transaction('John', 'Jane', 100)
process_transaction(transaction)

- Чтение табличных данных из файлов и баз данных

from collections import namedtuple
# Определение структуры данных
Person = namedtuple('Person', ['name', 'age', 'gender'])
# Чтение табличных данных из файла
def read_data_from_file():
data = []
with open('data.csv') as file:
for line in file:
name, age, gender = line.strip().split(',')
person = Person(name, int(age), gender)
data.append(person)
return data
# Чтение табличных данных из базы данных
def read_data_from_database():
data = []
# Подключение к базе данных и выполнение запроса
...
for row in query_result:
name, age, gender = row
person = Person(name, age, gender)
data.append(person)
return data

* Сравнение namedtuple с другими структурами данных

- namedtuple против словаря

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

from collections import namedtuple
Person = namedtuple('Person', ['name', 'age', 'gender'])
# Создание экземпляра namedtuple
person = Person('John', 30, 'Male')
# Доступ к значениям через имена полей
name = person.name
age = person.age
gender = person.gender
print(f"Name: {name}, Age: {age}, Gender: {gender}")

- namedtuple против DataClass

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

from dataclasses import dataclass
@dataclass
class Person:
name: str
age: int
gender: str
# Создание экземпляра DataClass
person = Person('John', 30, 'Male')
# Доступ к значениям через поля
name = person.name
age = person.age
gender = person.gender
print(f"Name: {name}, Age: {age}, Gender: {gender}")

- namedtuple против typing.NamedTuple

namedtuple и typing.NamedTuple предоставляют похожий функционал, но typing.NamedTuple является более мощным инструментом и поддерживает типирование.

from typing import NamedTuple
class Person(NamedTuple):
name: str
age: int
gender: str
# Создание экземпляра NamedTuple
person = Person('John', 30, 'Male')
# Доступ к значениям через поля
name = person.name
age = person.age
gender = person.gender
print(f"Name: {name}, Age: {age}, Gender: {gender}")

* Создание подклассов классов namedtuple

from collections import namedtuple
Person = namedtuple('Person', ['name', 'age', 'gender'])
# Создание подкласса класса namedtuple
class Employee(Person):
def get_salary(self):
return 5000
# Создание экземпляра подкласса
employee = Employee('John', 30, 'Male')
# Получение имени через имя поля
name = employee.name
# Вызов метода подкласса
salary = employee.get_salary()
print(f"Name: {name}, Salary: {salary}")

* Измерение времени создания: tuple против namedtuple

namedtuple может быть эффективнее, чем tuple, при создании множества экземпляров с большим количеством полей.

from collections import namedtuple
import time
# Создание namedtuple класса с 100 полями
Person = namedtuple('Person', ['field' + str(i) for i in range(100)])
# Измерение времени создания 10 миллионов экземпляров namedtuple
start_time = time.time()
for _ in range(10000000):
person = Person(*range(100))
end_time = time.time()
execution_time = end_time - start_time
print(f"Execution time: {execution_time} seconds")

* Выводы

namedtuple - мощный инструмент, который помогает писать более “pythonic” и читабельный код при работе с неизменяемыми последовательностями. Он предоставляет простой способ добавления именованных полей и дополнительных возможностей к кортежам. Вы также узнали о различных вариантах использования namedtuple и сравнили его с другими структурами данных. Надеюсь, что эта статья помогла вам лучше понять и использовать namedtuple в ваших проектах!