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

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

2.0 Middle🔥 111 комментариев
#DevOps и инфраструктура

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

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

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

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

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

1. Неизменяемость как требование

Когда нужна гарантия, что данные не будут случайно изменены:

# Плохо: список можно случайно изменить
config = ["db_host", "localhost", 3306]
config[0] = "wrong"  # Опс, переписали конфиг

# Хорошо: кортеж защищён от изменений
config = ("db_host", "localhost", 3306)
# config[0] = "wrong"  # TypeError: tuple does not support item assignment

2. Использование как ключи словаря

Кортежи хешируемы, списки — нет:

# Правильно: кортеж как ключ
coordinates = {
    (0, 0): "origin",
    (1, 1): "diagonal",
    (2, 3): "point_a"
}

print(coordinates[(1, 1)])  # diagonal

# Неправильно: список как ключ
try:
    bad_dict = {
        [0, 0]: "origin"  # TypeError
    }
except TypeError:
    print("Списки не могут быть ключами")

# Практический пример: кеш по множественным параметрам
cache = {}

def cached_query(user_id, start_date, end_date):
    key = (user_id, start_date, end_date)
    if key in cache:
        return cache[key]
    
    result = db.query(user_id, start_date, end_date)
    cache[key] = result
    return result

3. Множество (set) элементов

Кортежи можно добавить в set, списки — нет:

# Правильно: кортежи в множестве
unique_coordinates = {
    (0, 0),
    (1, 1),
    (2, 3),
    (1, 1)  # Дублирование удалится
}

print(len(unique_coordinates))  # 3

# Неправильно: списки в множестве
try:
    bad_set = {[1, 2], [3, 4]}  # TypeError
except TypeError:
    print("Списки не могут быть в set")

# Пример: хранение уникальных комбинаций
visited_states = set()
for user_id, action, timestamp in events:
    state = (user_id, action)
    if state not in visited_states:
        visited_states.add(state)
        process_new_state(state)

4. Возврат множественных значений

Функции часто возвращают несколько значений как кортеж:

# Стандартный подход
def get_user_info(user_id):
    user = db.get_user(user_id)
    return (user.name, user.email, user.age)

name, email, age = get_user_info(123)

# С именованными кортежами (namedtuple)
from collections import namedtuple

UserInfo = namedtuple('UserInfo', ['name', 'email', 'age'])

def get_user_info_named(user_id):
    user = db.get_user(user_id)
    return UserInfo(user.name, user.email, user.age)

info = get_user_info_named(123)
print(info.name)   # Доступ по имени
print(info.email)

# Или с dataclass (Python 3.7+)
from dataclasses import dataclass

@dataclass
class UserInfo:
    name: str
    email: str
    age: int

5. Функция с множественными возвращаемыми значениями

# Распаковка значений
def divide_with_remainder(a, b):
    return (a // b, a % b)

quotient, remainder = divide_with_remainder(17, 5)
print(f"{quotient} с остатком {remainder}")  # 3 с остатком 2

# Функция которая может вернуть результат или ошибку
def parse_number(value):
    try:
        return (int(value), None)  # (результат, ошибка)
    except ValueError as e:
        return (None, str(e))

result, error = parse_number("42")
if error:
    print(f"Ошибка: {error}")
else:
    print(f"Число: {result}")

6. Неявное использование в for циклах

# Распаковка при итерации
for key, value in {"a": 1, "b": 2}.items():
    print(f"{key}={value}")

# Похоже на распаковку кортежей
data = [(1, 2), (3, 4), (5, 6)]
for x, y in data:
    print(f"x={x}, y={y}")

# Распаковка в enumerate
for index, (name, age) in enumerate([("Alice", 30), ("Bob", 25)]):
    print(f"{index}: {name} ({age})")

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

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

import timeit

# Создание списка
list_time = timeit.timeit(
    "x = [1, 2, 3, 4, 5]",
    number=1000000
)

# Создание кортежа
tuple_time = timeit.timeit(
    "x = (1, 2, 3, 4, 5)",
    number=1000000
)

print(f"Список: {list_time:.4f}s")
print(f"Кортеж: {tuple_time:.4f}s")
# Кортеж обычно быстрее на 5-10%

8. Константные последовательности

# Дни недели как константа
WEEKDAYS = ("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday")

# Направления движения
DIRECTIONS = (
    (0, 1),    # North
    (1, 0),    # East
    (0, -1),   # South
    (-1, 0)    # West
)

for dx, dy in DIRECTIONS:
    new_x = current_x + dx
    new_y = current_y + dy

9. Функции со множественными параметрами

# Распаковка кортежа как аргументы функции
args = (2, 3)
result = pow(*args)  # pow(2, 3) = 8

# Практический пример
def connect(host, port, timeout):
    return f"Connecting to {host}:{port} (timeout={timeout}s)"

connection_params = ("localhost", 5432, 30)
print(connect(*connection_params))

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

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

В остальных случаях используй списки — они удобнее для изменяемых последовательностей.

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