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

Какие типы данных являются mutable, а какие immutable?

1.0 Junior🔥 131 комментариев
#Python Core

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

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

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

Mutable и Immutable типы данных в Python

Это фундаментальное различие определяет, можно ли менять объект после его создания. Это влияет на производительность, использование памяти и поведение функций.

Immutable (неизменяемые) типы

Объект нельзя изменить после создания. Любое изменение создаёт новый объект.

1. Numbers (int, float, complex)

x = 5
id(x)  # 140324935247840
x = x + 1  # Создаёт новый объект!
id(x)  # 140324935247856 — ДРУГОЙ адрес в памяти

# Попытка "изменить" число
y = 10
y[0] = 5  # TypeError: 'int' object does not support item assignment

2. Strings (str)

s = "hello"
id(s)  # 140324935319280

# Кажется, что меняем:
s = s + " world"
id(s)  # 140324935319368 — новая строка!

# Попытка изменить символ
s[0] = "H"  # TypeError: 'str' object does not support item assignment

# Правильный способ
s = "hello"
s_upper = s.upper()  # Создаёт новую строку

3. Tuple (кортеж)

t = (1, 2, 3)
id(t)  # 140324935447328

# Попытка изменить элемент
t[0] = 5  # TypeError: 'tuple' object does not support item assignment

# Попытка добавить элемент
t.append(4)  # AttributeError: 'tuple' object has no attribute 'append'

# Можно создать новый кортеж
t = t + (4,)  # Создаёт новый кортеж!

4. Frozenset

fs = frozenset([1, 2, 3])
id(fs)  # 140324935319440

# Попытка добавить элемент
fs.add(4)  # AttributeError: 'frozenset' object has no attribute 'add'

# Попытка удалить элемент
fs.remove(1)  # AttributeError: 'frozenset' object has no attribute 'remove'

5. Boolean (bool)

b = True
id(b)  # 140324912837440

# Изменяем
b = False
id(b)  # 140324912837408 — другой объект

6. None

n = None
id(n)  # 140324912828040

# None всегда один и тот же объект!
n2 = None
id(n2)  # 140324912828040 — ТОТ ЖЕ ОБЪЕКТ
n is n2  # True

Mutable (изменяемые) типы

Объект можно изменять после создания. Изменения происходят «на месте» (in-place).

1. List (список)

my_list = [1, 2, 3]
id(my_list)  # 140324935447320

# Изменяем элемент
my_list[0] = 10
id(my_list)  # 140324935447320 — ТОТ ЖЕ ОБЪЕКТ!
print(my_list)  # [10, 2, 3]

# Добавляем элемент
my_list.append(4)
id(my_list)  # 140324935447320 — всё ещё тот же объект
print(my_list)  # [10, 2, 3, 4]

# Удаляем элемент
my_list.remove(2)
id(my_list)  # 140324935447320 — один и тот же!
print(my_list)  # [10, 3, 4]

2. Dictionary (словарь)

my_dict = {"name": "John", "age": 30}
id(my_dict)  # 140324935447360

# Изменяем значение
my_dict["age"] = 31
id(my_dict)  # 140324935447360 — тот же объект
print(my_dict)  # {'name': 'John', 'age': 31}

# Добавляем новый ключ
my_dict["email"] = "john@example.com"
id(my_dict)  # 140324935447360
print(my_dict)  # {'name': 'John', 'age': 31, 'email': 'john@example.com'}

# Удаляем ключ
del my_dict["age"]
id(my_dict)  # 140324935447360

3. Set (множество)

my_set = {1, 2, 3}
id(my_set)  # 140324935447380

# Добавляем элемент
my_set.add(4)
id(my_set)  # 140324935447380 — тот же объект
print(my_set)  # {1, 2, 3, 4}

# Удаляем элемент
my_set.remove(2)
id(my_set)  # 140324935447380
print(my_set)  # {1, 3, 4}

4. Bytearray

ba = bytearray(b"hello")
id(ba)  # 140324935447400

# Изменяем элемент
ba[0] = ord('H')  # Меняем 'h' на 'H'
id(ba)  # 140324935447400 — тот же объект
print(ba)  # bytearray(b'Hello')

Опасность mutable объектов

Проблема 1: Изменение через ссылку

# Изменяемый объект (list)
list1 = [1, 2, 3]
list2 = list1  # Обе переменные указывают на один и тот же объект!

list1.append(4)

print(list1)  # [1, 2, 3, 4]
print(list2)  # [1, 2, 3, 4] — тоже изменился!

# Неизменяемый объект (tuple)
tuple1 = (1, 2, 3)
tuple2 = tuple1  # Просто копия ссылки

tuple1 = tuple1 + (4,)  # Создаёт НОВЫЙ объект

print(tuple1)  # (1, 2, 3, 4)
print(tuple2)  # (1, 2, 3) — не изменился!

Проблема 2: Mutable как параметр функции

def add_item(items):
    items.append("new")  # Изменяет оригинальный список!
    return items

my_list = ["a", "b"]
add_item(my_list)
print(my_list)  # ["a", "b", "new"] — список изменился!

# Правильно: работать с копией
def add_item_safe(items):
    new_items = items.copy()  # Или items[:]
    new_items.append("new")
    return new_items

my_list = ["a", "b"]
add_item_safe(my_list)
print(my_list)  # ["a", "b"] — не изменился!

Проблема 3: Mutable как default параметр

# ❌ ОПАСНЫЙ паттерн
def append_to_list(item, my_list=[]):
    my_list.append(item)  # Список переиспользуется!
    return my_list

print(append_to_list(1))  # [1]
print(append_to_list(2))  # [1, 2] — ЧТО?!
print(append_to_list(3))  # [1, 2, 3] — список растёт!

# ✅ Правильно
def append_to_list(item, my_list=None):
    if my_list is None:
        my_list = []
    my_list.append(item)
    return my_list

print(append_to_list(1))  # [1]
print(append_to_list(2))  # [2]
print(append_to_list(3))  # [3]

Проблема 4: Вложенные структуры

# Shallow copy (поверхностная копия)
original = [[1, 2], [3, 4]]
copy_list = original.copy()  # Копирует только внешний список

copy_list[0][0] = 99  # Меняем вложенный элемент
print(original)  # [[99, 2], [3, 4]] — оригинал изменился!

# Deep copy (глубокая копия)
import copy
original = [[1, 2], [3, 4]]
deep_copy = copy.deepcopy(original)  # Копирует всё рекурсивно

deep_copy[0][0] = 99
print(original)  # [[1, 2], [3, 4]] — оригинал НЕ изменился

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

ТипMutableПримеры операцийИзменяется?
int❌ Immutablex = x + 1Новый объект
float❌ Immutablex = x * 2Новый объект
str❌ Immutables = s.upper()Новая строка
tuple❌ Immutablet = t + (4,)Новый кортеж
frozenset❌ ImmutableНет методов измененияНе меняется
list✅ Mutable.append(), .remove()Тот же объект
dict✅ Mutable[key] = value, .pop()Тот же объект
set✅ Mutable.add(), .remove()Тот же объект
bytearray✅ Mutableba[0] = 65Тот же объект

Практические примеры

Immutable для безопасности

def process_data(config):
    """config — immutable dict (или используем типы.NamedTuple)"""
    # Если config immutable, мы уверены, что функция его не испортит
    return config

from typing import NamedTuple

class Config(NamedTuple):
    debug: bool
    timeout: int

config = Config(debug=True, timeout=30)
process_data(config)  # Безопасно

Mutable для производительности

# Неэффективно с immutable strings
s = ""
for i in range(1000000):
    s = s + str(i)  # Создаёт 1 миллион новых объектов!

# Эффективно с mutable list
items = []
for i in range(1000000):
    items.append(str(i))  # Один объект!
result = "".join(items)  # Один раз объединяем

Резюме

Immutable типы:

  • int, float, complex
  • str
  • tuple
  • frozenset
  • bool, None

Mutable типы:

  • list
  • dict
  • set
  • bytearray

Правила:

  1. Immutable типы безопаснее (не меняются случайно)
  2. Mutable типы быстрее (изменения in-place)
  3. Будь осторожен с mutable параметрами функций
  4. Используй .copy() или copy.deepcopy() при необходимости
  5. Не используй mutable объекты как default параметры