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

Когда нужно использовать кортеж в Python?

1.3 Junior🔥 161 комментариев
#Python Core

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

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

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

Когда использовать кортежи в Python: Полное руководство

Кортежи (tuples) — это иммутабельные (неизменяемые) коллекции, которые часто недооценивают. Вот практические сценарии использования.

1. Ключи в словарях

Кортежи хешируемы, поэтому могут быть ключами словаря:

# Матрица координат
grid = {
    (0, 0): "A",
    (0, 1): "B",
    (1, 0): "C",
    (1, 1): "D"
}

print(grid[(0, 1)])  # B

# Параметры функции как ключ (для кеширования)
cache = {}

def expensive_func(a, b, c):
    key = (a, b, c)
    if key not in cache:
        cache[key] = compute(a, b, c)
    return cache[key]

2. Элементы множества (set)

Уникальные неизменяемые комбинации:

# Уникальные пары
visited_transitions = set()

for event in events:
    transition = (event.from_state, event.to_state)
    if transition not in visited_transitions:
        visited_transitions.add(transition)
        log_new_transition(transition)

# Пример: избегание дубликатов
pairs = [(1, 2), (2, 3), (1, 2), (3, 4)]
unique_pairs = set(pairs)
print(unique_pairs)  # {(1, 2), (2, 3), (3, 4)}

3. Защита от случайных изменений

Если функция должна вернуть неизменяемые данные:

# API должен гарантировать, что данные не изменятся
def get_rgb_colors():
    return {
        'red': (255, 0, 0),
        'green': (0, 255, 0),
        'blue': (0, 0, 255)
    }

colors = get_rgb_colors()
# Даже если попытаемся изменить — ошибка
# colors['red'][0] = 200  # TypeError

# Это гарантирует консистентность в функции
def process_color(rgb):
    # Функция уверена, что rgb не изменится
    r, g, b = rgb
    return (r + g + b) // 3

4. Возврат нескольких значений из функции

Натуральный и элегантный способ:

def parse_datetime(date_string):
    """Возвращает (дата, время, часовой пояс)"""
    parts = date_string.split('T')
    date = parts[0]
    time_and_tz = parts[1].split('+')
    time = time_and_tz[0]
    tz = time_and_tz[1] if len(time_and_tz) > 1 else 'UTC'
    return (date, time, tz)

date, time, tz = parse_datetime("2026-03-22T14:30:00+03:00")
print(f"Дата: {date}, Время: {time}, Зона: {tz}")

# С распаковкой
result = parse_datetime("2026-03-22T14:30:00+03:00")
print(result)  # ('2026-03-22', '14:30:00', '03:00')

5. Неявное присваивание в циклах

Распаковка при итерации:

# Список кортежей
students = [
    ("Alice", 85),
    ("Bob", 92),
    ("Charlie", 78)
]

# Распаковка в цикле
for name, score in students:
    print(f"{name}: {score}%")

# С индексом
for i, (name, score) in enumerate(students):
    print(f"{i}. {name}: {score}%")

# Со словарями
for key, value in {"x": 10, "y": 20}.items():
    print(f"{key} = {value}")

6. Аргументы функции через распаковку

# Функция ждёт 3 параметра
def greet(greeting, name, punctuation):
    return f"{greeting} {name}{punctuation}"

# Распаковка кортежа
args = ("Hello", "Alice", "!")
print(greet(*args))  # Hello Alice!

# Практический пример
db_params = ("localhost", 5432, "mydb")
connection = connect(*db_params)

7. Функции с фиксированной структурой

Когда структура данных не меняется:

# Константные данные
DIRECTIONS = (
    (0, 1, "North"),
    (1, 0, "East"),
    (0, -1, "South"),
    (-1, 0, "West")
)

for dx, dy, name in DIRECTIONS:
    print(f"Direction {name}: dx={dx}, dy={dy}")

# Конфигурация с гарантией неизменяемости
DB_CONFIG = ("localhost", 5432, "admin", "password")
# Гарантируем, что конфиг не будет случайно переписан

8. Именованные кортежи (namedtuple)

Когда нужна семантика с читаемостью:

from collections import namedtuple

# Определяем структуру
Point = namedtuple('Point', ['x', 'y', 'z'])
Color = namedtuple('Color', ['r', 'g', 'b'])

# Создание
p = Point(x=1, y=2, z=3)
color = Color(r=255, g=0, b=0)

# Доступ по имени (читаемо!)
print(p.x, p.y, p.z)
print(color.r, color.g, color.b)

# Всё ещё кортеж
print(p[0])  # 1
print(p == (1, 2, 3))  # True

# Практический пример
from collections import namedtuple

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

def get_user_by_id(user_id):
    row = db.query(f"SELECT id, name, email FROM users WHERE id={user_id}")
    return User(*row)

user = get_user_by_id(123)
print(f"User {user.name} ({user.email})")

9. TypedDict для типизации

Подобно namedtuple но с типами (Python 3.8+):

from typing import TypedDict

class UserDict(TypedDict):
    id: int
    name: str
    email: str

def get_user() -> UserDict:
    return {"id": 1, "name": "Alice", "email": "alice@example.com"}

10. Распаковка с игнорированием значений

# Берём только нужные значения
data = ("Alice", 30, "NYC", 5000)
name, age, *_ = data  # Игнорируем остаток

first, *middle, last = data
print(first, last)  # Alice 5000

# В функциях
def process(main_value, *ignored_values):
    return main_value * 2

result = process(10, 20, 30, 40)  # 20

11. Производительность

Кортежи немного быстрее списков:

import sys

my_list = [1, 2, 3, 4, 5]
my_tuple = (1, 2, 3, 4, 5)

print(sys.getsizeof(my_list))   # ~56 bytes
print(sys.getsizeof(my_tuple))  # ~40 bytes

# Кортежи также быстрее в создании и доступе

Резюме: Используй кортежи когда:

  1. Нужен ключ словаря (списки не подходят)
  2. Хочешь добавить в set (для уникальности)
  3. Возвращаешь из функции несколько значений
  4. Нужна гарантия неизменяемости данных
  5. Используешь в цикле for распаковкой
  6. Константные данные (конфиг, направления и т.д.)
  7. Нужна производительность (немного быстрее списков)
  8. Типизированные данные (namedtuple, TypedDict)

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

Когда нужно использовать кортеж в Python? | PrepBro