← Назад к вопросам
Контейнерный типы данных изменяемый или неизменяемый
2.3 Middle🔥 151 комментариев
#DevOps и инфраструктура
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Изменяемость контейнерных типов данных в Python
Контейнерные типы Python делятся на две категории: изменяемые (mutable) и неизменяемые (immutable).
Таблица контейнерных типов
| Тип | Категория | Описание |
|---|---|---|
| list | Mutable | Упорядоченная коллекция, можно менять элементы |
| dict | Mutable | Ключ-значение, можно добавлять/удалять пары |
| set | Mutable | Неупорядоченное множество, можно добавлять/удалять элементы |
| tuple | Immutable | Упорядоченная коллекция, нельзя менять элементы |
| frozenset | Immutable | Неизменяемое множество |
| str | Immutable | Строка, нельзя менять символы |
| bytes | Immutable | Байтовая последовательность, нельзя менять значения |
| bytearray | Mutable | Изменяемая версия bytes |
Изменяемые (mutable) контейнеры
List — изменяемый список
# Создание
my_list = [1, 2, 3]
# Изменение элементов (исходный объект меняется)
my_list[0] = 99
print(my_list) # [99, 2, 3]
# Добавление элементов
my_list.append(4)
print(my_list) # [99, 2, 3, 4]
# Удаление
my_list.pop()
print(my_list) # [99, 2, 3]
# Расширение
my_list.extend([7, 8, 9])
print(my_list) # [99, 2, 3, 7, 8, 9]
# Проверка того же объекта
a = [1, 2, 3]
id_before = id(a)
a[0] = 100
id_after = id(a)
print(id_before == id_after) # True — это тот же объект!
Dict — изменяемый словарь
my_dict = {'name': 'John', 'age': 30}
# Изменение значения
my_dict['age'] = 31
print(my_dict) # {'name': 'John', 'age': 31}
# Добавление нового ключа
my_dict['city'] = 'Moscow'
print(my_dict) # {'name': 'John', 'age': 31, 'city': 'Moscow'}
# Удаление ключа
del my_dict['city']
print(my_dict) # {'name': 'John', 'age': 31}
# Объект меняется на месте
a = {'key': 'value'}
a['key'] = 'new_value'
print(id(a)) # Тот же id
Set — изменяемое множество
my_set = {1, 2, 3}
# Добавление элемента
my_set.add(4)
print(my_set) # {1, 2, 3, 4}
# Удаление элемента
my_set.remove(2)
print(my_set) # {1, 3, 4}
# Объект меняется на месте
a = {1, 2, 3}
a.add(999)
print(id(a)) # Тот же id
Bytearray — изменяемые байты
my_bytes = bytearray(b'Hello')
# Изменение байта
my_bytes[0] = ord('J')
print(my_bytes) # bytearray(b'Jello')
# Объект меняется на месте
a = bytearray(b'test')
a[0] = ord('T')
print(id(a)) # Тот же id
Неизменяемые (immutable) контейнеры
Tuple — неизменяемый кортеж
my_tuple = (1, 2, 3)
# ❌ Попытка изменить — ОШИБКА
my_tuple[0] = 99
# TypeError: 'tuple' object does not support item assignment
# ❌ Попытка добавить — ОШИБКА
my_tuple.append(4)
# AttributeError: 'tuple' object has no attribute 'append'
# ✅ Создание нового кортежа
my_tuple = (1, 2, 3) + (4,)
print(my_tuple) # (1, 2, 3, 4) — это НОВЫЙ объект
print(id(my_tuple)) # Другой id
Frozenset — неизменяемое множество
my_frozenset = frozenset({1, 2, 3})
# ❌ Попытка добавить — ОШИБКА
my_frozenset.add(4)
# AttributeError: 'frozenset' object has no attribute 'add'
# ✅ Создание нового frozenset
my_frozenset = my_frozenset | {4}
print(my_frozenset) # frozenset({1, 2, 3, 4}) — это НОВЫЙ объект
# Frozenset можно использовать как ключ словаря
my_dict = {frozenset({1, 2}): 'value'} # Это сработает
# А обычный set нельзя
my_dict = {set({1, 2}): 'value'} # TypeError
Str — неизменяемая строка
my_str = 'Hello'
# ❌ Попытка изменить — ОШИБКА
my_str[0] = 'J'
# TypeError: 'str' object does not support item assignment
# ✅ Создание новой строки
my_str = 'J' + my_str[1:]
print(my_str) # 'Jello' — это НОВЫЙ объект
# Методы строк возвращают новые строки
a = 'hello'
b = a.upper()
print(a) # 'hello' — исходная не изменилась
print(b) # 'HELLO' — новая строка
print(id(a) == id(b)) # False
Bytes — неизменяемые байты
my_bytes = b'Hello'
# ❌ Попытка изменить — ОШИБКА
my_bytes[0] = ord('J')
# TypeError: 'bytes' object does not support item assignment
# ✅ Создание новых байтов
my_bytes = b'J' + my_bytes[1:]
print(my_bytes) # b'Jello' — это НОВЫЙ объект
Важный момент: вложенные контейнеры
Tuple содержит изменяемый список
my_tuple = (1, 2, [3, 4, 5])
# ❌ Менять сам кортеж нельзя
my_tuple[0] = 99 # TypeError
# ✅ Но содержимое изменяемого контейнера внутри — можно
my_tuple[2][0] = 99
print(my_tuple) # (1, 2, [99, 4, 5])
# Причина: tuple неизменяем на уровне структуры,
# но не отвечает за содержимое внутренних объектов
Frozenset содержит только неизменяемое
# ❌ Frozenset не может содержать список
my_frozenset = frozenset({(1, 2), [3, 4]}) # TypeError
# Потому что list изменяем и может быть изменён
# Это нарушит целостность frozenset
# ✅ Только неизменяемое
my_frozenset = frozenset({(1, 2), (3, 4)}) # Ok
Практическое применение
Когда использовать immutable
# 1. Как ключи в словаре (tuple можно, list нельзя)
config = {
(1, 2): 'point A', # ✅ Tuple работает
(3, 4): 'point B',
}
config = {
[1, 2]: 'point A', # ❌ TypeError: unhashable type
}
# 2. В множествах
cached_ids = {1, 2, 3} # ✅ Set работает
cached_ids = {(1, 2), (3, 4)} # ✅ Tuple работает
cached_ids = {[1, 2], [3, 4]} # ❌ TypeError
# 3. Как параметр функции (более безопасно)
def process_data(data: tuple):
# Функция уверена, что data не изменится внутри
return len(data)
# 4. Для потокобезопасности
from threading import Thread
data = (1, 2, 3) # ✅ Безопасно для многопоточности
def worker(data):
for x in data: # Можно читать, не боясь что изменится
print(x)
Thread(target=worker, args=(data,)).start()
Когда использовать mutable
# 1. Нужна хорошая производительность
items = [] # Добавлять элементы в список — эффективнее
for i in range(1000000):
items.append(i)
# Чем каждый раз создавать новый tuple
my_tuple = ()
for i in range(1000000):
my_tuple = my_tuple + (i,) # Создаётся новый объект каждый раз!
# 2. Нужна структура типа словаря
user = {}
user['name'] = 'John'
user['age'] = 30
Проверка изменяемости
# Функция для проверки
def is_mutable(obj):
"""Проверяет, изменяем ли объект"""
try:
# Пытаемся хешировать объект
hash(obj)
return False # Если хеш успешен, то immutable
except TypeError:
return True # Если ошибка, то mutable
print(is_mutable([1, 2, 3])) # True (list mutable)
print(is_mutable((1, 2, 3))) # False (tuple immutable)
print(is_mutable({1, 2, 3})) # True (set mutable)
print(is_mutable(frozenset([1]))) # False (frozenset immutable)
print(is_mutable('hello')) # False (str immutable)
Вывод
Контейнерные типы Python делятся на:
Mutable (изменяемые):
- list — список
- dict — словарь
- set — множество
- bytearray — изменяемые байты
Можно менять, добавлять, удалять элементы на месте. Хешировать нельзя.
Immutable (неизменяемые):
- tuple — кортеж
- frozenset — неизменяемое множество
- str — строка
- bytes — байты
Нельзя менять элементы, но можно создавать новые объекты. Можно использовать как ключи словаря и элементы множеств.
Выбор между ними зависит от того, нужна ли изменяемость, производительность и потокобезопасность.