Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Изменяемые структуры данных (mutable)
Изменяемые (mutable) структуры данных — это объекты, которые можно изменять после создания, не создавая новый объект. В отличие от неизменяемых (immutable), которые нельзя менять.
Основные изменяемые типы в Python
# 1. LIST — изменяемый список
my_list = [1, 2, 3]
my_list[0] = 99 # Изменяем элемент
my_list.append(4) # Добавляем элемент
print(id(my_list)) # id остаётся ТЕМ ЖЕ
# 2. DICT — изменяемый словарь
my_dict = {"a": 1, "b": 2}
my_dict["a"] = 999 # Изменяем значение
my_dict["c"] = 3 # Добавляем новый ключ
print(id(my_dict)) # id остаётся ТЕМ ЖЕ
# 3. SET — изменяемое множество
my_set = {1, 2, 3}
my_set.add(4) # Добавляем элемент
my_set.remove(1) # Удаляем элемент
print(id(my_set)) # id остаётся ТЕМ ЖЕ
Неизменяемые для сравнения
# TUPLE — неизменяемый список
my_tuple = (1, 2, 3)
# my_tuple[0] = 99 # ОШИБКА!
# STRING — неизменяемая строка
my_str = "hello"
# my_str[0] = "H" # ОШИБКА!
# При конкатенации создаётся НОВЫЙ объект
my_str = "hello"
id1 = id(my_str)
my_str = my_str + " world"
id2 = id(my_str)
print(id1 == id2) # False — новый объект!
Проблемы с изменяемостью
Проблема 1: Неожиданные мутации
def process_list(data):
data.append(999) # Модифицируем исходный список!
return data
original = [1, 2, 3]
result = process_list(original)
print(original) # [1, 2, 3, 999] — УПС!
Проблема 2: Использование как ключ словаря
my_dict = {}
my_list = [1, 2, 3]
# my_dict[my_list] = "value" # ОШИБКА!
my_tuple = (1, 2, 3)
my_dict[my_tuple] = "value" # OK
Проблема 3: Значение по умолчанию в функции
# ПЛОХО!
def append_to_list(item, items=[]):
items.append(item)
return items
print(append_to_list(1)) # [1]
print(append_to_list(2)) # [1, 2] — НЕОЖИДАННО!
# ХОРОШО!
def append_to_list(item, items=None):
if items is None:
items = []
items.append(item)
return items
print(append_to_list(1)) # [1]
print(append_to_list(2)) # [2]
Защита от нежелательных мутаций
1. Копирование данных
def process_list(data):
data_copy = data.copy() # Поверхностная копия
data_copy.append(999)
return data_copy
original = [1, 2, 3]
result = process_list(original)
print(original) # [1, 2, 3] — не изменился!
2. Глубокая копия для вложенных структур
import copy
nested = [[1, 2], [3, 4]]
shallow = nested.copy()
deep = copy.deepcopy(nested)
shallow[0].append(999)
print(nested) # [[1, 2, 999], [3, 4]] — изменился!
print(deep) # [[1, 2], [3, 4]] — не изменился
3. Использование tuple вместо list где возможно
# Если не планируешь менять — используй tuple
coordinates = (10, 20) # Более безопасно
# Возвращай tuple из функции
def get_position():
return (100, 200) # Защита от изменений
Производительность: изменяемость vs неизменяемость
import timeit
# LIST — изменяемый
list_code = '''
items = []
for i in range(1000):
items.append(i)
'''
# TUPLE — неизменяемый
tuple_code = '''
items = ()
for i in range(1000):
items = items + (i,)
'''
print("List time:", timeit.timeit(list_code, number=1000))
print("Tuple time:", timeit.timeit(tuple_code, number=1000))
# List НАМНОГО быстрее!
Dataclass и frozen датаклассы
from dataclasses import dataclass
# Изменяемый dataclass
@dataclass
class Person:
name: str
age: int
person = Person("Алиса", 30)
person.age = 31 # OK
# Неизменяемый dataclass
@dataclass(frozen=True)
class ImmutablePerson:
name: str
age: int
ip = ImmutablePerson("Боб", 25)
# ip.age = 26 # ОШИБКА!
Лучшие практики
- Используй изменяемость сознательно — если функция должна менять объект, документируй
- Предпочитай неизменяемость в параллелизме — нет race conditions
- Копируй, если сомневаешься — лучше небольшая потеря производительности
- Используй type hints — указывай
listvstupleдля ясности