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

Расскажи про изменяемые и неизменяемые типы данных

1.0 Junior🔥 191 комментариев
#SQL и базы данных

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

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

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

Определение

Неизменяемые (Immutable) типы — объекты, которые не могут быть изменены после создания. Любое "изменение" создаёт новый объект.

Изменяемые (Mutable) типы — объекты, которые можно изменять на месте, без создания новых объектов.

Основные типы в Python

Неизменяемые:

  • int, float, complex (числа)
  • str (строки)
  • tuple (кортежи)
  • frozenset (неизменяемое множество)
  • bytes (байты)
  • None, bool (синглтоны)

Изменяемые:

  • list (списки)
  • dict (словари)
  • set (множества)
  • bytearray (массив байтов)

Примеры и различия

Неизменяемые типы

# Строки (immutable)
s = "hello"
# s[0] = 'H'  # TypeError! Нельзя изменить

# "Изменение" создаёт новую строку
s = "hello"
s_new = s.upper()  # Новый объект
print(s)      # hello (исходная не изменилась)
print(s_new)  # HELLO

# Кортежи (immutable)
t = (1, 2, 3)
# t[0] = 5  # TypeError! Нельзя изменить
t_new = t + (4,)  # Новый кортеж

Изменяемые типы

# Списки (mutable)
lst = [1, 2, 3]
lst[0] = 99  # Можно изменить на месте
print(lst)  # [99, 2, 3]

lst_id = id(lst)
lst.append(4)  # Тот же объект в памяти
print(id(lst) == lst_id)  # True

# Словари (mutable)
d = {"a": 1, "b": 2}
d["a"] = 100  # Изменение на месте

Опасность: Shared References (Ловушка!)

# Список в функции
original = [1, 2, 3]
copy = original  # Не копирование, а указатель!

copy.append(4)
print(original)  # [1, 2, 3, 4] — ИЗМЕНИЛСЯ!

# Правильное копирование
copy_correct = original.copy()
copy_correct.append(5)
print(original)  # [1, 2, 3, 4] — не изменился

Проблема с изменяемыми аргументами

# Классическая ошибка!
def add_element(lst=[]):  # Mutable default argument!
    lst.append(1)
    return lst

print(add_element())  # [1]
print(add_element())  # [1, 1] — список переиспользуется!

# Правильно:
def add_element(lst=None):
    if lst is None:
        lst = []
    lst.append(1)
    return lst

Практические следствия

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

# Неизменяемые типы медленнее при "изменении"
s = "a"
for i in range(1000):
    s = s + "b"  # Каждый раз новая строка — O(n²)!

# Для строк лучше использовать join()
result = "".join("b" for _ in range(1000))  # O(n)

Использование в словарях

# Словари требуют hashable ключей (неизменяемые)
d = {}
d[(1, 2)] = "tuple key works"  # tuple — hashable
# d[[1, 2]] = "list key"  # TypeError!

# Множества требуют hashable элементов
s = {(1, 2), (3, 4)}  # tuple работает
# s = {[1, 2]}  # TypeError!

Многопоточность

# Неизменяемые типы безопаснее в многопоточности
tuple_data = (1, 2, 3)  # Потоки не испортят это

# Проблема с изменяемым типом (без lock)
lst = []
# Может возникнуть race condition при параллельном доступе

Копирование

import copy

original = [[1, 2], [3, 4]]

# Поверхностное копирование (shallow copy)
shallow = original.copy()
shallow[0][0] = 99
print(original)  # [[99, 2], [3, 4]] — изменился!

# Глубокое копирование (deep copy)
deep = copy.deepcopy(original)
deep[0][0] = 99
print(original)  # [[1, 2], [3, 4]] — не изменился

Таблица сравнения

ТипИзменяемостьHashableИспользование
int, float, strНетДаЧисловые данные, тексты
tupleНетДаКлючи словарей, множества
listДаНетИзменяемые последовательности
dictДаНетКлюч-значение
setДаНетУникальные элементы

Итог

  • Используй неизменяемые типы для ключей словарей, элементов множеств, параметров функций
  • Используй изменяемые типы для коллекций, которые часто меняются
  • Помни про shared references — присвоение копирует ссылку, не данные
  • Для многопоточности неизменяемые типы безопаснее