← Назад к вопросам
Какие типы данных являются 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 | ❌ Immutable | x = x + 1 | Новый объект |
| float | ❌ Immutable | x = x * 2 | Новый объект |
| str | ❌ Immutable | s = s.upper() | Новая строка |
| tuple | ❌ Immutable | t = t + (4,) | Новый кортеж |
| frozenset | ❌ Immutable | Нет методов изменения | Не меняется |
| list | ✅ Mutable | .append(), .remove() | Тот же объект |
| dict | ✅ Mutable | [key] = value, .pop() | Тот же объект |
| set | ✅ Mutable | .add(), .remove() | Тот же объект |
| bytearray | ✅ Mutable | ba[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,complexstrtuplefrozensetbool,None
Mutable типы:
listdictsetbytearray
Правила:
- Immutable типы безопаснее (не меняются случайно)
- Mutable типы быстрее (изменения in-place)
- Будь осторожен с mutable параметрами функций
- Используй
.copy()илиcopy.deepcopy()при необходимости - Не используй mutable объекты как default параметры