← Назад к вопросам

Что такое именованный кортеж?

2.0 Middle🔥 131 комментариев
#Python Core#Soft Skills

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Именованный кортеж (Named Tuple)

Что это такое?

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

Именованные кортежи неизменяемы (immutable), как обычные кортежи, и занимают меньше памяти, чем классы.

Основное использование

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

from collections import namedtuple

# Определение структуры
Point = namedtuple('Point', ['x', 'y'])

# Создание экземпляра
p = Point(3, 4)

# Обращение к элементам
print(p.x)      # 3
print(p.y)      # 4
print(p[0])     # 3 (как обычный кортеж)
print(p[1])     # 4

Различные способы определения

1. Список строк (наиболее читаемо):

from collections import namedtuple

User = namedtuple('User', ['id', 'name', 'email', 'age'])
user = User(1, "Alice", "alice@example.com", 30)
print(user)
# User(id=1, name='Alice', email='alice@example.com', age=30)

2. Одна строка с пробелами или запятыми:

User = namedtuple('User', 'id name email age')
# или
User = namedtuple('User', 'id, name, email, age')

3. Список полей:

User = namedtuple('User', ['id', 'name', 'email', 'age'])

Практические примеры

Работа с координатами:

from collections import namedtuple
import math

Point = namedtuple('Point', ['x', 'y'])

def distance(p1, p2):
    return math.sqrt((p1.x - p2.x)**2 + (p1.y - p2.y)**2)

point_a = Point(0, 0)
point_b = Point(3, 4)

dist = distance(point_a, point_b)
print(f"Расстояние: {dist}")  # 5.0

Работа с данными из базы:

from collections import namedtuple

User = namedtuple('User', ['id', 'name', 'email'])

# Симуляция данных из БД
users_data = [
    (1, "Alice", "alice@example.com"),
    (2, "Bob", "bob@example.com"),
    (3, "Charlie", "charlie@example.com"),
]

users = [User(*data) for data in users_data]

for user in users:
    print(f"ID: {user.id}, Имя: {user.name}, Email: {user.email}")

Методы именованных кортежей

_fields — получение имён полей:

from collections import namedtuple

Person = namedtuple('Person', ['name', 'age', 'city'])

print(Person._fields)  # ('name', 'age', 'city')

_asdict() — преобразование в словарь:

person = Person('Alice', 30, 'New York')

data_dict = person._asdict()
print(data_dict)
# {'name': 'Alice', 'age': 30, 'city': 'New York'}

# Полезно для сериализации в JSON
import json
json_str = json.dumps(data_dict)
print(json_str)

_make() — создание из итерируемого объекта:

data = ('Bob', 25, 'London')
person = Person._make(data)
print(person)  # Person(name='Bob', age=25, city='London')

_replace() — создание модифицированной копии:

person1 = Person('Alice', 30, 'New York')

# Создаёт новый именованный кортеж с изменённым полем
person2 = person1._replace(age=31)

print(person1)  # Person(name='Alice', age=30, city='New York')
print(person2)  # Person(name='Alice', age=31, city='New York')

Сравнение с классом

Использование класса (много кода):

class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y
    
    def __repr__(self):
        return f"Point({self.x}, {self.y})"
    
    def __eq__(self, other):
        return self.x == other.x and self.y == other.y

p = Point(3, 4)

Использование namedtuple (краткий код):

from collections import namedtuple

Point = namedtuple('Point', ['x', 'y'])
p = Point(3, 4)

Важные характеристики

1. Неизменяемость (Immutability):

Point = namedtuple('Point', ['x', 'y'])
p = Point(3, 4)

# Это вызовет ошибку
# p.x = 5  # AttributeError: can't set attribute

2. Хешируемость (можно использовать как ключ словаря):

Point = namedtuple('Point', ['x', 'y'])
p1 = Point(1, 2)
p2 = Point(1, 2)
p3 = Point(2, 3)

points = {p1: "A", p3: "B"}  # Используются как ключи
print(points[p2])  # "A" (p1 и p2 равны)

3. Памяти меньше, чем у класса:

from collections import namedtuple
import sys

Point = namedtuple('Point', ['x', 'y'])
p = Point(3, 4)

print(sys.getsizeof(p))  # Примерно 56 байт

class PointClass:
    def __init__(self, x, y):
        self.x = x
        self.y = y

pc = PointClass(3, 4)
print(sys.getsizeof(pc))  # Примерно 56 байт (+ __dict__)

Практический пример: обработка результатов запроса

from collections import namedtuple
import asyncpg

UserRecord = namedtuple('UserRecord', ['id', 'name', 'email', 'created_at'])

async def get_users(pool):
    async with pool.acquire() as conn:
        rows = await conn.fetch('SELECT id, name, email, created_at FROM users')
        
        # Преобразование в namedtuples
        users = [UserRecord(*row) for row in rows]
        
        return users

# Использование
for user in await get_users(pool):
    print(f"{user.name} ({user.email})")

Расширенные возможности

Значения по умолчанию (Python 3.7+):

from collections import namedtuple

# Нужно использовать defaults параметр
Config = namedtuple('Config', ['host', 'port', 'timeout'])
Config.__new__.__defaults__ = (8000, 30)  # Значения для port и timeout

c1 = Config('localhost')
print(c1)  # Config(host='localhost', port=8000, timeout=30)

c2 = Config('localhost', 9000)
print(c2)  # Config(host='localhost', port=9000, timeout=30)

Или использовать dataclass (более современный подход):

from dataclasses import dataclass

@dataclass
class Config:
    host: str
    port: int = 8000
    timeout: int = 30

c = Config('localhost')
print(c)  # Config(host='localhost', port=8000, timeout=30)

Когда использовать namedtuple?

Используйте namedtuple для:

  • Простых структур данных с несколькими полями
  • Неизменяемых (immutable) данных
  • Когда нужны лёгкие объекты
  • Возврата нескольких значений из функции
  • Использования как ключей в словаре

Не используйте namedtuple для:

  • Сложной логики и методов
  • Изменяемых данных (используйте список или словарь)
  • Иерархии объектов
  • Когда нужна высокая типизация (используйте dataclass с type hints)

Современные альтернативы

dataclass (Python 3.7+) — более гибкая:

from dataclasses import dataclass

@dataclass
class Person:
    name: str
    age: int
    email: str
    
    def greeting(self):
        return f"Hello, I'm {self.name}"

p = Person("Alice", 30, "alice@example.com")
print(p.greeting())

TypedDict (Python 3.8+) — для словарей с типами:

from typing import TypedDict

class PersonDict(TypedDict):
    name: str
    age: int
    email: str

person: PersonDict = {
    "name": "Alice",
    "age": 30,
    "email": "alice@example.com"
}

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