Ответ
Это фундаментальная концепция Python, влияющая на поведение кода, производительность и безопасность данных. Понимание мутабельности помогает избежать тонких багов.
Ключевые различия:
- Неизменяемые (immutable) типы:
int,float,str,tuple,bytes,frozenset. При "изменении" создается новый объект. - Изменяемые (mutable) типы:
list,dict,set,bytearray, пользовательские классы (по умолчанию). Объект модифицируется на месте.
Практический пример с последствиями:
# 1. Неожиданное изменение из-за ссылки (mutable)
def append_to_list(value, target=[]): # Опасность: изменяемый аргумент по умолчанию!
target.append(value)
return target
print(append_to_list(1)) # [1]
print(append_to_list(2)) # [1, 2] # Сюрприз! Список сохранился между вызовами.
# Правильно:
def append_to_list_fixed(value, target=None):
if target is None:
target = [] # Создаем новый неизменяемый список каждый раз
target.append(value)
return target
# 2. Хэшируемость и использование в качестве ключа
try:
my_dict = {[1,2]: "value"} # TypeError: unhashable type: 'list'
except TypeError as e:
print(f"Ошибка: {e}") # Изменяемые объекты не могут быть ключами dict.
valid_dict = {(1, 2): "value"} # Кортеж (immutable) — допустимый ключ.
На собеседовании это проверяет, насколько разработчик осознает семантику присваивания (копирование ссылок), побочные эффекты функций и принципы проектирования безопасного API.
Ответ 18+ 🔞
А, ну это, блядь, одна из тех тем, от которой у новичков мозг вскипает, как каша в кастрюле, а потом они месяцами ищут, откуда у них в коде берутся призрачные баги. Ёпта, мутабельность — это про то, можно ли объект поменять прямо на месте, или он как святой — неприкосновенный.
Если по-простому:
- Неизменяемые (immutable):
int,float,str,tuple,bytes,frozenset. Это как татуировка на жопе — переделать не получится, только новую набить. Каждое "изменение" создаёт нового клона. - Изменяемые (mutable):
list,dict,set,bytearray, да и свои классы обычно. Это как пластилин — лепи что хочешь, прямо в том же комке.
Смотри, где собака зарыта, а точнее, где она насрала:
# 1. Классическая ловушка для распиздяев — изменяемый аргумент по умолчанию
def add_value(val, storage=[]): # Опа-на! Список создаётся ОДИН РАЗ при определении функции!
storage.append(val)
return storage
print(add_value(1)) # [1] — вроде норм.
print(add_value(2)) # [1, 2] — а вот нихуя себе! Куда единица подевалась? Она тут и была, блядь!
# Правильный путь, чтобы не охуеть:
def add_value_fixed(val, storage=None):
if storage is None:
storage = [] # А вот тут новый список рождается при каждом вызове, красота!
storage.append(val)
return storage
# 2. Про ключи в словарях — тут вообще терпения ноль ебать
try:
bad_dict = {[1,2,3]: "лажа"} # Список как ключ? Да ты шутишь!
except TypeError as e:
print(f"Ошибка: {e}") # Изменяемое не может быть ключом, потому что хэш от него плавает, как говно в проруби.
good_dict = {(1, 2, 3): "окей"} # А кортеж — священная неизменяемая сущность, его можно.
На собеседовании эту тему впендюривают, чтобы проверить, понимаешь ли ты, что в Python присваивание — это не копирование объекта, а передача ссылки на него. И если ты этого не осознаёшь, то однажды твоя функция начнёт тайком править данные там, где её не просили, и будет тебе волнение ебать, пока ищешь, кто же этот пиздец устроил.