← Назад к вопросам

Как можно обратиться в ячейке памяти?

3.0 Senior🔥 21 комментариев
#Python Core

Комментарии (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 — для работы с большими массивами в памяти

Получение прямого доступа к памяти требует осторожности — ошибки могут привести к краху программы.

Как можно обратиться в ячейке памяти? | PrepBro