Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Как реализован кортеж в Python
Кортеж (tuple) — это один из фундаментальных типов данных в Python, и его реализация имеет интересные особенности на уровне CPython.
Структура кортежа на C уровне
В CPython кортеж реализован как C структура PyTupleObject:
typedef struct {
PyObject_HEAD
Py_ssize_t ob_size; // Количество элементов
PyObject *ob_item[1]; // Указатели на элементы (массив переменной длины)
} PyTupleObject;
Ключевые особенности:
ob_item— это массив указателей на объекты Python- Размер кортежа (
ob_size) фиксирован при создании - Данные лежат в памяти контигуально
Операции основных
# Создание
t = (1, 2, 3) # Литеральный синтаксис
t = tuple([1, 2, 3]) # Конвертирование
# Чтение по индексу - O(1)
value = t[0] # Прямой доступ к ob_item[0]
# Слайсинг - O(k) где k размер слайса
slice = t[1:3] # Создаёт новый кортеж
# Итерация - O(n)
for item in t:
print(item)
Неизменяемость (Immutability)
Кортеж является неизменяемым типом:
t = (1, 2, 3)
t[0] = 10 # TypeError: tuple object does not support item assignment
del t[0] # TypeError: tuple object does not support item deletion
t.append(4) # AttributeError: нет метода append
Реализация неизменяемости:
- В CPython нет операций изменения кортежа
- Попытка изменения вызывает исключение на уровне интерпретатора
- Это позволяет безопасно использовать кортежи как ключи словарей
Хеширование
Кортежи хешируемы, если все их элементы хешируемы:
# Можно использовать как ключи словаря
dict_with_tuple_keys = {
(1, 2): "value1",
(3, 4): "value2"
}
# Но не если содержат списки
my_tuple = (1, [2, 3]) # Мутабельный элемент
hash(my_tuple) # TypeError: unhashable type: 'list'
Реализация хеша:
- Хеш кортежа вычисляется из хешей его элементов
- Кэшируется внутри объекта кортежа для быстрого доступа
Оптимизация: Tuple pooling
Python кэширует пустые кортежи и однозначные для производительности:
# Пустой кортеж - всегда один и тот же объект
t1 = ()
t2 = ()
print(t1 is t2) # True - один объект в памяти!
# Однозначные кортежи с целыми числами
t3 = (1,)
t4 = (1,)
print(t3 is t4) # True в некоторых контекстах
# Больше нет гарантии
t5 = (1, 2)
t6 = (1, 2)
print(t5 is t6) # Может быть True или False
Реализация методов
t = (1, 2, 3, 2, 1)
# count - O(n) поиск по значению
count_2 = t.count(2) # 2
# index - O(n) первое вхождение
index_2 = t.index(2) # 1
# len - O(1) просто читаем ob_size
len_t = len(t) # 3
Упаковка и распаковка
# Упаковка - создаёт новый кортеж
a, b, c = 1, 2, 3 # Создаёт (1, 2, 3) затем распаковывает
# Распаковка - итерирует элементы
t = (10, 20, 30)
x, y, z = t # Обращается к t[0], t[1], t[2]
# Extended unpacking
first, *middle, last = (1, 2, 3, 4, 5)
# first=1, middle=[2,3,4], last=5
Сравнение с другими типами
import sys
list_obj = [1, 2, 3]
tuple_obj = (1, 2, 3)
print(sys.getsizeof(list_obj)) # ~56 байт (зависит от системы)
print(sys.getsizeof(tuple_obj)) # ~40 байт (компактнее)
Преимущества кортежа:
- Меньше памяти - нет выделения места для роста
- Быстрее создание - размер известен
- Хеширование - может быть ключом словаря
- Потокобезопасность - не меняется
Производительность операций
import timeit
t = tuple(range(10000))
l = list(range(10000))
# Чтение по индексу - одинаково
print(timeit.timeit(lambda: t[5000], number=1000000)) # ~0.04s
print(timeit.timeit(lambda: l[5000], number=1000000)) # ~0.04s
# Создание
print(timeit.timeit(lambda: (1, 2, 3), number=1000000)) # Быстро
print(timeit.timeit(lambda: [1, 2, 3], number=1000000)) # Немного медленнее
# Итерация
print(timeit.timeit(lambda: [x for x in t], number=10000)) # ~0.3s
print(timeit.timeit(lambda: [x for x in l], number=10000)) # ~0.3s
Named tuples - расширение
from collections import namedtuple
# Более удобный синтаксис
Point = namedtuple('Point', ['x', 'y'])
p = Point(10, 20)
print(p.x) # 10
print(p[0]) # 10
# Это всё ещё кортеж
print(isinstance(p, tuple)) # True
print(hash(p)) # Хешируется
Резюме
- Структура: Массив указателей на Python объекты с фиксированным размером
- Неизменяемость: Встроена на уровне интерпретатора
- Хеширование: Вычисляется и кэшируется
- Оптимизация: Пулинг пустых и однозначных кортежей
- Производительность: Компактнее и быстрее создаётся чем список
- Use case: Ключи словарей, множеств, возвращаемые значения, потокобезопасность