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

Какие типы данных в Python изменяемые, а какие неизменяемые?

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

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

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

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

Изменяемые и неизменяемые типы данных в Python

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

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

Объекты этих типов не могут быть изменены после создания. Любые операции, которые кажутся изменением, на самом деле создают новый объект.

Основные неизменяемые типы:

# 1. int (целые числа)
a = 5
print(id(a))  # адрес в памяти
a = 10
print(id(a))  # ДРУГОЙ адрес (новый объект)

# 2. float (числа с плавающей запятой)
f = 3.14
f = 2.71
# f указывает на новый объект

# 3. str (строки)
s = "Hello"
print(id(s))
s = s + " World"  # создаёт новую строку
print(id(s))  # ДРУГОЙ адрес

# 4. tuple (кортежи)
t = (1, 2, 3)
print(id(t))
# t[0] = 5  # TypeError: 'tuple' object does not support item assignment

# 5. bool (булевы значения)
b = True
b = False
# Каждое присваивание указывает на другой объект

# 6. frozenset (неизменяемое множество)
fs = frozenset([1, 2, 3])
# fs.add(4)  # AttributeError: 'frozenset' object has no attribute 'add'

# 7. None (None объект)
n = None
# Это синглтон, всегда один и тот же объект

# 8. bytes (неизменяемая последовательность байт)
b = b"hello"
print(id(b))
b = b"hello" + b" world"
print(id(b))  # ДРУГОЙ адрес

# 9. Числовые типы: complex, decimal.Decimal
c = 1 + 2j
c = 3 + 4j  # новый объект

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

Объекты этих типов могут быть изменены без создания нового объекта. Изменение происходит «на месте».

Основные изменяемые типы:

# 1. list (списки)
lst = [1, 2, 3]
print(id(lst))
lst[0] = 10  # изменяем элемент на месте
print(id(lst))  # ТОТ ЖЕ адрес!
lst.append(4)
print(id(lst))  # ТОТ ЖЕ адрес!

# 2. dict (словари)
d = {"a": 1, "b": 2}
print(id(d))
d["a"] = 10  # изменяем значение
print(id(d))  # ТОТ ЖЕ адрес!
d["c"] = 3  # добавляем ключ
print(id(d))  # ТОТ ЖЕ адрес!

# 3. set (множества)
s = {1, 2, 3}
print(id(s))
s.add(4)  # добавляем элемент
print(id(s))  # ТОТ ЖЕ адрес!
s.remove(1)  # удаляем элемент
print(id(s))  # ТОТ ЖЕ адрес!

# 4. bytearray (изменяемая последовательность байт)
ba = bytearray(b"hello")
print(id(ba))
ba[0] = ord('H')
print(id(ba))  # ТОТ ЖЕ адрес!

# 5. lists, дополнительные методы
lst = [1, 2, 3]
lst.extend([4, 5])  # расширяем
lst.clear()  # очищаем
lst.sort()  # сортируем
# Все на месте, id не меняется

Сравнение при присваивании

# Неизменяемые — присваивание создаёт ссылку на новый объект
a = "hello"
b = a
print(id(a) == id(b))  # True (пока строка одна и та же)

a = "goodbye"
print(a)
print(b)  # "hello" — не изменилась!
print(id(a) == id(b))  # False

# Изменяемые — присваивание создаёт ссылку на один объект
lst1 = [1, 2, 3]
lst2 = lst1
print(id(lst1) == id(lst2))  # True

lst1[0] = 10
print(lst1)  # [10, 2, 3]
print(lst2)  # [10, 2, 3] — ИЗМЕНИЛАСЬ!
print(id(lst1) == id(lst2))  # True (один объект)

Изменяемые объекты в неизменяемых контейнерах

# Кортеж сам неизменяем, но может содержать изменяемые объекты
t = (1, [2, 3], 4)
print(id(t))

# Не можем изменить сам кортеж
# t[1] = [5, 6]  # TypeError

# Но можем изменить список внутри кортежа
t[1][0] = 10
print(t)  # (1, [10, 3], 4)
print(id(t))  # ТОТ ЖЕ адрес!

# Словари также могут содержать изменяемые значения
data = {
    "name": "Alice",
    "hobbies": ["reading", "coding"]
}
data["hobbies"].append("gaming")  # изменяем список
print(data)

Последствия для функций

# Неизменяемые — функция не может изменить оригинал
def modify_string(s):
    s = s + " modified"
    return s

original = "hello"
result = modify_string(original)
print(original)  # "hello" — не изменилась
print(result)    # "hello modified"

# Изменяемые — функция МОЖЕТ изменить оригинал
def modify_list(lst):
    lst.append(4)
    return lst

original = [1, 2, 3]
result = modify_list(original)
print(original)  # [1, 2, 3, 4] — ИЗМЕНИЛАСЬ!
print(result)    # [1, 2, 3, 4]

# Правильный способ (создаём копию)
def modify_list_safely(lst):
    new_list = lst.copy()  # или lst[:]
    new_list.append(4)
    return new_list

original = [1, 2, 3]
result = modify_list_safely(original)
print(original)  # [1, 2, 3] — не изменилась
print(result)    # [1, 2, 3, 4]

Таблица типов данных

ТипИзменяемыйПримеры операций
intНетa = 5; a = 6 (новый объект)
floatНетf = 3.14; f = 2.71 (новый объект)
strНетs = "hi"; s = s + "!" (новый объект)
tupleНетt = (1, 2); t[0] = 5 — ошибка
frozensetНетfs.add(1) — ошибка
bytesНетb[0] = 65 — ошибка
listДаlst[0] = 5; lst.append(6)
dictДаd["key"] = val; d.pop("key")
setДаs.add(1); s.remove(2)
bytearrayДаba[0] = 65; ba.append(66)

Хеширование

Неизменяемые типы можно использовать как ключи словаря и в множествах:

# ✅ Неизменяемые — можно хешировать
d = {
    "key": "value",
    (1, 2): "tuple key",
    5: "integer key"
}

s = {"string", 42, ("a", "b")}

# ❌ Изменяемые — нельзя хешировать
d = {
    [1, 2]: "value"  # TypeError: unhashable type: 'list'
}

s = {{"a": 1}}  # TypeError: unhashable type: 'dict'

Лучшие практики

  1. Знайте, какие типы изменяемые — избегайте неожиданных побочных эффектов
  2. Копируйте при необходимости — используйте .copy() или slice
  3. Возвращайте новые объекты — не изменяйте входные параметры
  4. Документируйте изменяемость — в docstrings указывайте, изменяется ли аргумент
def process_data(data_list):
    """Обрабатывает данные.
    
    Args:
        data_list: Список для обработки (будет изменён)
    
    Returns:
        Обработанный список
    """
    data_list.sort()
    return data_list

Понимание изменяемости — это основа для написания надежного Python кода без скрытых ошибок.