Примитивные и ссылочные типы данных: различия
🔍 Как Python хранит данные в памяти?
Каждый раз, когда вы создаёте переменную в Python, интерпретатор решает — положить значение в ячейку памяти как есть или сохранить ссылку на объект. Это фундаментальное различие между примитивными и ссылочными типами!
a = 42 # Примитивный тип (int)
b = [1, 2, 3] # Ссылочный тип (list)
🧱 Примитивные типы: простое значение
Примитивные (скалярные) типы — это базовые "кирпичики", которые хранят непосредственное значение. В Python к ним относятся:
int(целые числа)float(дробные числа)bool(логические значения)str(строки, но с оговорками*)None(специальный тип)
🌟 Ключевая особенность: При присвоении создаётся новая копия значения.
x = 10
y = x # Создаётся копия числа 10
x = 20
print(y) # 10 — y не изменилось!
🏷️ Ссылочные типы: объекты и указатели
Ссылочные (составные) типы — это сложные структуры, которые хранятся как объекты в памяти. К ним относятся:
list(списки)dict(словари)set(множества)tuple(кортежи*)- Экземпляры классов
🔄 Важно: Переменная содержит ссылку на объект, а не сам объект!
list1 = [1, 2, 3]
list2 = list1 # Обе переменные ссылаются на один объект!
list1.append(4)
print(list2) # [1, 2, 3, 4] — изменение видно в list2!
⚡ Практические отличия: 3 важных следствия
1. Изменяемость vs Неизменяемость
- Примитивные типы неизменяемы — любая операция создаёт новый объект.
- Ссылочные типы обычно изменяемы (кроме
tupleиfrozenset).
s = "hello"
s[0] = "H" # Ошибка! str неизменяем
lst = [1, 2]
lst[0] = 10 # OK, list изменяем
2. Сравнение значений
- Примитивы сравниваются по значению.
- Ссылочные типы сравниваются по идентичности (по умолчанию).
a = 1000
b = 1000
print(a == b) # True — значения равны
lst1 = [1, 2]
lst2 = [1, 2]
print(lst1 is lst2) # False — это разные объекты!
3. Передача в функции
- Примитивы передаются по значению (копируются).
- Ссылочные типы передаются по ссылке.
def modify(num, items):
num += 10 # Не влияет на внешнюю переменную
items.append(100) # Изменяет исходный список!
x = 5
lst = [1, 2]
modify(x, lst)
print(x) # 5 (не изменился)
print(lst) # [1, 2, 100] (изменился)
🛠️ Полезные инструменты для работы
1. Функция id() — адрес в памяти
x = 10
y = 10
print(id(x) == id(y)) # True — для маленьких int Python кэширует объекты
2. Оператор is — проверка идентичности
a = [1, 2]
b = a
print(a is b) # True — это один и тот же объект
3. Модуль copy — контролируемое копирование
import copy
original = [[1, 2], [3, 4]]
shallow = copy.copy(original) # Поверхностная копия
deep = copy.deepcopy(original) # Глубокая копия
💡 Главное правило
Всегда учитывайте тип данных, с которым работаете:
- Примитивы — безопасны при передаче, но менее гибки.
- Ссылочные типы — мощные, но требуют осторожности с изменением.
Для глубокого погружения рекомендую разбор Данилы Бежина на YouTube: https://www.youtube.com/@DanilaBezhin.
Теперь вы готовы избегать коварных багов, связанных с неожиданными изменениями объектов! 🎯