Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
id() — уникальный идентификатор объекта в Python
id() — встроенная функция, которая возвращает уникальный целочисленный идентификатор объекта. Это адрес в памяти, где хранится объект (в CPython). Функция существует для всех объектов в Python.
Базовый синтаксис
obj = "Hello"
identifier = id(obj)
print(identifier) # Например: 140234567890256 (адрес в памяти)
print(type(identifier)) # <class 'int'>
Что это на самом деле?
В CPython (самая распространённая реализация Python):
# id() возвращает адрес объекта в памяти
import ctypes
obj = "Hello"
obj_id = id(obj)
print(f"Адрес в памяти: {obj_id}")
print(f"В hex: {hex(obj_id)}")
# Получить объект по адресу (опасно!)
addr_obj = ctypes.cast(obj_id, ctypes.py_object).value
print(addr_obj) # Hello (тот же объект)
Сравнение is vs ==
Это критическая разница:
# == сравнивает ЗНАЧЕНИЯ
a = [1, 2, 3]
b = [1, 2, 3]
print(a == b) # True (одинаковые значения)
# is сравнивает ИДЕНТИЧНОСТЬ (id)
print(a is b) # False (разные объекты в памяти)
print(id(a)) # 140234567890000
print(id(b)) # 140234567890100 (другой адрес!)
# Но если это один и тот же объект:
c = a
print(a is c) # True (одинаковый id)
print(id(a) == id(c)) # True
id() и интерны (Interning)
Python оптимизирует некоторые объекты, переиспользуя их в памяти:
Числа: -5 до 256 интернируются
# Маленькие числа интернируются
a = 100
b = 100
print(id(a) == id(b)) # True (один объект в памяти)
print(a is b) # True
# Большие числа — разные объекты
c = 1000
d = 1000
print(id(c) == id(d)) # False (разные объекты)
print(c is d) # False
Строки интернируются при определённых условиях
# Строковые литералы интернируются
s1 = "hello"
s2 = "hello"
print(id(s1) == id(s2)) # True (один объект)
# Но если создать через конкатенацию — может быть разный id
s3 = "hel" + "lo"
s4 = "hel" + "lo"
print(id(s3) == id(s4)) # Может быть False (зависит от оптимизаций)
# Явная интернизация
import sys
s5 = sys.intern("hello world")
s6 = sys.intern("hello world")
print(id(s5) == id(s6)) # True (гарантированно)
Использование id() для отладки
class User:
def __init__(self, name):
self.name = name
print(f"Создан User {name}, id={id(self)}")
user1 = User("Alice") # Создан User Alice, id=140234567890000
user2 = User("Bob") # Создан User Bob, id=140234567890100
print(f"user1 это user2? {user1 is user2}") # False
# Отследить копирование объектов
user3 = user1
print(f"user1 это user3? {user1 is user3}") # True (одна ссылка)
print(id(user1) == id(user3)) # True
id() и типы данных
# Неизменяемые объекты (immutable)
a = 5
print(id(a)) # Фиксированный адрес
# a = 6 — это создаст НОВЫЙ объект, не изменит старый
# Изменяемые объекты (mutable)
my_list = [1, 2, 3]
original_id = id(my_list)
my_list.append(4) # id() не изменится
print(id(my_list) == original_id) # True (тот же объект)
# Присваивание создаёт новый объект
my_list = [1, 2, 3, 4]
print(id(my_list) == original_id) # False (новый объект)
Отличия в разных реализациях Python
# CPython: id это реальный адрес в памяти
import sys
print(sys.implementation.name) # cpython
# PyPy, Jython, IronPython:
# id может быть просто уникальным числом, не адресом
Практический пример: отслеживание ссылок
class DataCache:
def __init__(self):
self.data = {}
def cache_object(self, key, obj):
# Сохраняем id для отладки
self.data[key] = {
"value": obj,
"id": id(obj),
"type": type(obj).__name__
}
def debug_info(self):
for key, info in self.data.items():
print(f"{key}: {info['type']} (id={info['id']})")
cache = DataCache()
user = {"name": "Alice", "age": 30}
cache.cache_object("user_1", user)
user["age"] = 31 # Изменяем, но id остаётся
cache.cache_object("user_1", user)
cache.debug_info()
# user_1: dict (id=140234567890000) в обоих случаях
id() и сборка мусора (Garbage Collection)
import gc
def create_objects():
obj1 = {"data": "temporary"}
obj2 = [1, 2, 3]
print(f"obj1 id: {id(obj1)}")
print(f"obj2 id: {id(obj2)}")
# Выходим из функции — obj1, obj2 удаляются
create_objects()
# После удаления объекта его id может быть переиспользован
# для нового объекта (переиспользование адреса в памяти)
obj3 = {"data": "new"} # Может получить тот же id, что был obj1
print(f"obj3 id: {id(obj3)}")
Проверка идентичности в коллекциях
class User:
def __init__(self, name):
self.name = name
users = [User("Alice"), User("Bob"), User("Charlie")]
ids_set = {id(user) for user in users}
print(len(ids_set)) # 3 (все разные)
# Проверить, есть ли в списке конкретный объект
alice = users[0]
print(any(user is alice for user in users)) # True
id() для отладки shared состояния
def find_shared_state_issue():
# Проблема: все элементы указывают на ОДИН объект
matrix = [[0] * 3 for _ in range(3)] # ✓ Правильно
wrong_matrix = [[0] * 3] * 3 # ✗ Неправильно!
print("Правильная матрица:")
for row in matrix:
print(id(row), row)
print("\nНеправильная матрица:")
for row in wrong_matrix:
print(id(row), row) # Все id одинаковые!
# Проверка
wrong_matrix[0][0] = 1
print(wrong_matrix) # Все строки изменились!
find_shared_state_issue()
Ключевые моменты
id()возвращает адрес объекта в памяти (в CPython)isсравнивает id,==сравнивает значения- Интернирование оптимизирует память для часто используемых объектов
- Неизменяемые объекты часто переиспользуют id
- Изменяемые объекты (списки, словари) сохраняют id при изменении
- id() полезен для отладки, но не для production кода