Какие типы данных в Python являются неизменяемыми (immutable)?

Ответ

Неизменяемые (immutable) типы в Python — это типы, объекты которых нельзя изменить после создания. Любая операция, которая кажется изменяющей объект, на самом деле создает новый объект.

Основные встроенные immutable-типы:

  1. int — целые числа.
  2. float — числа с плавающей точкой.
  3. bool — логические значения (True, False).
  4. str — строки.
  5. tuple — кортежи.
  6. frozenset — неизменяемое множество.
  7. bytes — неизменяемая последовательность байтов.
  8. range — диапазон.
  9. NoneType (тип объекта None).

Почему это важно?

  • Безопасность: Immutable-объекты потокобезопасны.
  • Хешируемость: Их можно использовать как ключи словаря (dict) или элементы множества (set).
  • Предсказуемость: Передача в функцию не приводит к неожиданным изменениям исходного объекта.

Примеры и демонстрация:

# 1. Строки (str) — immutable
my_string = "hello"
print(id(my_string))  # id: 140245... (адрес в памяти)
my_string += " world"  # Конкатенация создает НОВЫЙ объект
print(id(my_string))  # id: 140245... (уже другой адрес!)
# my_string[0] = 'H'  # TypeError: 'str' object does not support item assignment

# 2. Кортежи (tuple) — immutable
my_tuple = (1, 2, [3, 4])
# my_tuple[0] = 10  # TypeError: 'tuple' object does not support item assignment
# Однако, если элемент сам является изменяемым (как список [3,4]), его содержимое можно менять!
my_tuple[2].append(5)  # Это сработает: кортеж хранит ссылку на список, а не сам список.
print(my_tuple)  # (1, 2, [3, 4, 5])

# 3. Использование как ключ словаря (требуется хешируемость)
valid_dict = {(1, 2): "value"}  # Кортеж — immutable, можно как ключ.
# invalid_dict = {[1, 2]: "value"}  # TypeError: unhashable type: 'list' (list — mutable)

Ответ 18+ 🔞

А, вот эта тема про неизменяемые типы в Python! Ну что ж, давайте разберём эту историю, как говорится, по косточкам, блядь.

Представьте себе, что у вас есть кирпич. Обычный, красный, ёбаный кирпич. Вы его слепили, обожгли — и всё, пиши пропало. Хотите на нём что-то нацарапать? Не выйдет, сука. Хотите его сломать пополам? Ну, сломать-то можно, но это будет уже два новых кирпича, а старый — каюк. Вот это и есть immutable, блядь, неизменяемый. Создали — и пошёл он нахуй в том виде, в каком есть.

Так, какие у нас главные "кирпичи" в Python? Запоминайте, а то потом будете ебаться:

  1. int — целые числа. Пять — оно и в Африке пять, его не переделаешь в шесть, только новое число создать.
  2. float — числа с хвостиком. 3.14 — и сиди с этим пирогом, блядь.
  3. boolTrue да False. Правда есть правда, а кривда — кривда, тут не поспоришь.
  4. str — строки. Вот это вообще отдельная песня, про неё ниже.
  5. tuple — кортежи. Скобочки круглые, как наручники. Защёлкнули — и всё, пидарас, сиди.
  6. frozenset — множество, но мороженое, блядь. Замороженное. Не шевелись.
  7. bytes — байты. Ну, типа как строка, но для компа.
  8. range — диапазон. От сих и до сих, и ни шагу в сторону.
  9. NoneType — это тип у этого самого None. Вообще пустота, вакуум, нихуя. Его тем более не изменишь.

А нахуя это всё надо, спросите вы?

  • Безопасность, блядь. Представьте, десять потоков одновременно хотят один объект поменять. С mutable-объектами будет пиздец и race condition, а immutable можно спокойно всем раздать — они всё равно как скала.
  • Хешируемость, ёпта. Это чтобы в словарь ключом запихнуть или в множество. Только immutable-объекты на это способны, потому что их хеш не меняется. С изменяемыми — ни хуя не выйдет, Python сразу орёт TypeError.
  • Предсказуемость, мать его. Передал объект в функцию — и спи спокойно, никто его там исподтишка не перепишет. Возвращают тебе его же, нетронутого.

Ну а теперь, как говорится, смотрим в код, сука:

# 1. Строки (str) — классика жанра, immutable как швейцарские часы
my_string = "hello"
print(id(my_string))  # Смотрим адрес в памяти, типа прописка
my_string += " world"  # О, кажется, мы её изменили! Ан нет, блядь!
print(id(my_string))  # Смотрим прописку ещё раз — охуеть, новый адрес! Это уже другой объект!
# my_string[0] = 'H'  # А вот так напрямую ткнуть не получится. Python скажет: "Иди нахуй, строка не поддерживает присваивание по индексу".

# 2. Кортежи (tuple) — тут ловушка для распиздяев
my_tuple = (1, 2, [3, 4])
# my_tuple[0] = 10  # Опять же, напрямую менять элементы нельзя. Кортеж — он как отец-командир, строгий.
# НО! Если внутри сидит изменяемый гадёныш, как этот список [3,4], то его внутренности можно ебашить!
my_tuple[2].append(5)  # Да-да, это сработает! Кортеж хранит ссылку на список, а не сам список. Хитрая жопа!
print(my_tuple)  # Смотрим: (1, 2, [3, 4, 5]). Кортеж вроде тот же, а список внутри уже другой.

# 3. Ключи словаря — экзамен на хешируемость
valid_dict = {(1, 2): "value"}  # Кортеж — immutable, прошёл проверку, может быть ключом. Молодец.
# invalid_dict = {[1, 2]: "value"}  # А вот список — mutable, негодяй. Python его нахуй пошлёт с ошибкой: unhashable type.

Вот и вся философия. Создал immutable-объект — и живи с ним, как с родным, блядь, не пытайся перевоспитать. Хочешь что-то другое — создавай нового. А mutable — это как пластилин, лепи что хочешь, но и ответственности больше. Выбирай, что тебе ближе, но суть понимай, а то потом будешь сидеть и чесать репу: "И чё это у меня ничего не меняется, ёпта?".