Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Обращение к ячейкам памяти в Python
Python высокоуровневый язык, но есть способы работать с памятью напрямую.
1. Функция id() — адрес объекта
x = 42
print(id(x)) # Адрес объекта в памяти, например: 140352345678912
# id() возвращает целое число — адрес в памяти
address = id(x)
print(type(address)) # <class 'int'>
2. Модуль ctypes — работа с указателями
import ctypes
# Получить указатель на объект
x = 42
ptr = id(x) # Это адрес
print(f"Адрес объекта: {ptr}")
# Опасно! Прямое разыменование может привести к краху
# obj = ctypes.cast(ptr, ctypes.py_object).value
# print(obj) # 42
3. Модуль sys.getsizeof() — размер объекта
import sys
x = [1, 2, 3]
print(sys.getsizeof(x)) # Размер списка в байтах, например: 88
# Это только сам объект, не содержимое
print(sys.getsizeof([1, 2, 3, 4, 5])) # Больше
4. Модуль gc — сборка мусора
import gc
# Получить все объекты в памяти
all_objects = gc.get_objects()
print(f"Всего объектов: {len(all_objects)}")
# Получить счётчик ссылок
x = [1, 2, 3]
print(sys.getrefcount(x)) # Сколько ссылок на объект
# Отключить/включить автоматическую сборку мусора
gc.disable()
gc.collect() # Запустить сборку вручную
gc.enable()
5. Прямая работа с памятью через array и memoryview
import array
# Создать массив
arr = array.array('i', [1, 2, 3, 4, 5])
print(arr) # array('i', [1, 2, 3, 4, 5])
# Получить доступ к памяти
mv = memoryview(arr)
print(mv[0]) # 1
mv[0] = 10 # Изменить значение
print(arr) # array('i', [10, 2, 3, 4, 5])
# memoryview не копирует данные, работает напрямую с памятью
data = mv.tobytes()
print(data) # Бинарные данные
6. Использование bytearray
# Изменяемый массив байт
ba = bytearray(b'Hello')
print(ba) # bytearray(b'Hello')
# Изменить конкретный байт
ba[0] = ord('J') # Изменить первый байт
print(ba) # bytearray(b'Jello')
# Работает с памятью эффективно
print(id(ba)) # Адрес объекта
7. Низкоуровневая работа с ctypes
import ctypes
# Выделить память
memory = ctypes.create_string_buffer(10)
print(memory.raw) # Бинарные данные
# Записать данные
memory.value = b'Hello'
print(memory.value) # b'Hello\x00\x00\x00\x00\x00'
# Работать с указателями на функции
libc = ctypes.CDLL('libc.so.6') # Linux
malloc = libc.malloc
malloc.argtypes = [ctypes.c_size_t]
malloc.restype = ctypes.c_void_p
ptr = malloc(1024) # Выделить 1024 байта
8. Взаимодействие с внешней памятью
import numpy as np
# NumPy работает с памятью очень эффективно
arr = np.array([1, 2, 3, 4, 5])
print(arr.data) # Указатель на данные
print(arr.nbytes) # Размер в байтах
# Изменение элемента
arr[0] = 10
# Работать с памятью напрямую
view = np.asarray(arr)
9. Счётчик ссылок (Reference Counting)
import sys
x = [1, 2, 3]
print(sys.getrefcount(x)) # 2 (сам список + аргумент getrefcount)
y = x # Ещё одна ссылка
print(sys.getrefcount(x)) # 3
del y
print(sys.getrefcount(x)) # 2
# Когда счётчик = 0, память освобождается
10. Инструменты профилирования памяти
import tracemalloc
tracemalloc.start()
# Ваш код
data = [i for i in range(1000000)]
current, peak = tracemalloc.get_traced_memory()
print(f"Текущая память: {current / 1024 / 1024:.2f} MB")
print(f"Пиковая память: {peak / 1024 / 1024:.2f} MB")
tracemalloc.stop()
Ключевые моменты
- id() — получить адрес объекта в памяти
- sys.getsizeof() — размер объекта
- ctypes — низкоуровневая работа с памятью (опасно!)
- memoryview — беспроцессный доступ к данным
- gc — управление сборкой мусора и счётчиком ссылок
- NumPy — для работы с большими массивами в памяти
Получение прямого доступа к памяти требует осторожности — ошибки могут привести к краху программы.