Sys.getsizeof: примеры (PYTHON)
sys.getsizeof(object: any, default: int): intОписание функции sys.getsizeof
Функция sys.getsizeof() из модуля sys в Python предназначена для получения размера объекта в байтах. Её основное применение - анализ использования памяти и оптимизация, когда требуется понимать, сколько памяти занимает конкретная структура данных. Это бывает полезно при работе с большими объемами информации, например, в сферах анализа данных, веб-скрапинга или разработки высоконагруженных приложений.
Аргументы функции:
- object (обязательный): Любой объект Python, размер которого необходимо определить.
- default (необязательный): Значение, возвращаемое функцией, если объект не поддерживает определение размера. Если этот параметр не задан, в такой ситуации возникает исключение
TypeError.
Возвращаемое значение:
Целое число (int), представляющее размер переданного объекта в байтах. Важно помнить, что возвращаемый размер включает только память, непосредственно занятую самим объектом, и не учитывает память объектов, на которые он может ссылаться (например, элементы внутри списка или словаря).
Простые примеры использования
Определение размера для различных базовых типов данных.
Пример 1: Числа и строки
import sys
print(sys.getsizeof(5))
print(sys.getsizeof(3.14))
print(sys.getsizeof('a'))
print(sys.getsizeof('строка'))28 24 50 104
Пример 2: Коллекции
import sys
empty_list = []
small_list = [1, 2, 3]
print(sys.getsizeof(empty_list))
print(sys.getsizeof(small_list))
empty_dict = {}
print(sys.getsizeof(empty_dict))56 88 64
Пример 3: Использование параметра default
import sys
# Попытка получить размер объекта, не поддерживающего эту операцию
class MyClass:
pass
obj = MyClass()
# Без default возникнет ошибка
# size = sys.getsizeof(obj, default='Неизмеримо')
# С default
size = sys.getsizeof(obj, default='Размер не поддерживается')
print(size)Размер не поддерживается
Похожие функции в Python
В Python существуют другие инструменты для оценки использования памяти.
1. Метод объекта __sizeof__()
Функция sys.getsizeof() вызывает именно этот специальный метод. Его можно вызвать напрямую, но это не рекомендуется, так как sys.getsizeof() добавляет обработку сборщика мусора. Используется редко в пользовательском коде.
x = [1, 2, 3]
print(x.__sizeof__())88
2. Модуль pympler.asizeof или pympler.asizeof.asizeof
Функция asizeof() из сторонней библиотеки Pympler рассчитывает рекурсивный размер объекта, включая все вложенные объекты. Это кардинальное отличие от sys.getsizeof. Предпочтительнее для точного анализа общего потребления памяти сложной структурой.
# Требует установки: pip install pympler
from pympler import asizeof
list_of_lists = [[1, 2], [3, 4, 5]]
print('sys.getsizeof:', sys.getsizeof(list_of_lists))
print('asizeof:', asizeof.asizeof(list_of_lists))sys.getsizeof: 80 asizeof: 504
Когда что использовать: sys.getsizeof применяют для быстрой оценки размера отдельного объекта. Для получения полного размера сложного объекта со всем содержимым лучше использовать pympler.asizeof.
Альтернативы в других языках программирования
Аналогичная функциональность в разных языках реализована с особенностями.
JavaScript
Прямого аналога нет. Можно приблизительно оценить через сериализацию в JSON строку, но это неточно. В Node.js есть process.memoryUsage() для общей памяти.
// Неточная оценка для строки
let str = 'test';
let size = new TextEncoder().encode(str).length;
console.log(size); // Байты в UTF-84
Java
Используют инструментарий JVM (например, java.lang.instrument.Instrumentation), но он сложен для прямого вызова. Нет встроенной простой функции.
// Пример с использованием Instrumentation (упрощенно)
// Требует запуска с javaagent
// Runtime.getRuntime().totalMemory() - свободная память даёт общую картину.PHP
Функция memory_get_usage() возвращает объем памяти, выделенный скрипту, а не размер конкретной переменной.
$start = memory_get_usage();
$array = range(1, 1000);
$end = memory_get_usage();
echo 'Приблизительно: ' . ($end - $start) . ' байт';Приблизительно: 52840 байт
C#
Метод GC.GetTotalMemory() для общей памяти. Для объекта используется System.Runtime.InteropServices.Marshal.SizeOf(), но только для неуправляемых типов или структур.
// Для структуры (значимый тип)
using System.Runtime.InteropServices;
[StructLayout(LayoutKind.Sequential)]
struct Point { public int X; public int Y; }
int size = Marshal.SizeOf(typeof(Point)); // 8 байтGolang
Пакет unsafe с функцией Sizeof(), но она работает аналогично C, определяя размер типа, а не конкретного значения или сложной структуры данных с динамическими полями.
package main
import (
"fmt"
"unsafe"
)
func main() {
var x int64 = 10
fmt.Println(unsafe.Sizeof(x)) // Размер типа int64
}8
Основное отличие Python - наличие в стандартной библиотеке простой функции для любого объекта, хотя и с ограничением на вложенность.
Типичные ошибки и недоразумения
1. Ожидание рекурсивного подсчета размера
Самая частая ошибка - предположение, что sys.getsizeof(list) вернет размер списка вместе со всеми его элементами.
import sys
list_of_numbers = [1, 2, 3, 4, 5]
print(sys.getsizeof(list_of_numbers))
# Ожидание: размер 5 чисел. Реальность: размер только объекта-контейнера списка.104
2. Попытка измерить размер бесконечного генератора
Генератор как объект имеет размер, но это не размер всех генерируемых им данных, которые потенциально бесконечны.
import sys
gen = (i for i in range(1000000))
print(sys.getsizeof(gen)) # Размер объекта-генератора112
3. Забывание импортировать модуль sys
# NameError: name 'sys' is not defined
print(getsizeof([]))Traceback (most recent call last): File "", line 1, in NameError: name 'getsizeof' is not defined
4. Сравнение размеров разных типов без контекста
Размер целого числа (28 байт) больше, чем размер булева значения (28 байт), что кажется нелогичным. Это накладные расходы CPython на хранение любого объекта.
Изменения в последних версиях Python
Функция sys.getsizeof() появилась в Python 2.6. С тех пор её интерфейс и базовое поведение оставались стабильными. В Python 3.x она работает аналогично. Однако внутренняя реализация может меняться от версии к версии CPython, что приводит к разному базовому размеру для одних и тех же типов объектов из-за оптимизаций в структурах данных интерпретатора. Например, размер пустого списка или словаря может незначительно отличаться между минорными версиями Python 3. Это не изменение функции, а изменение объектов. Рекомендуется не полагаться на конкретные числовые значения, а использовать функцию для сравнительного анализа в рамках одной версии интерпретатора.
Расширенные и специальные примеры
1. Сравнение эффективности структур данных
import sys
# Кортеж vs Список
tuple_data = (1, 2, 3, 4, 5)
list_data = [1, 2, 3, 4, 5]
print(f'Кортеж: {sys.getsizeof(tuple_data)}')
print(f'Список: {sys.getsizeof(list_data)}')
# Кортеж часто занимает меньше памяти, так как он неизменяем.Кортеж: 80 Список: 104
2. Влияние длины строки на размер
import sys
for length in [0, 1, 10, 100]:
s = 'x' * length
print(f'Длина {length}: {sys.getsizeof(s)} байт')Длина 0: 49 байт Длина 1: 50 байт Длина 10: 59 байт Длина 100: 149 байт
3. Размер объекта класса и его экземпляра
import sys
class SimpleClass:
def __init__(self, value):
self.value = value
obj = SimpleClass(42)
print(f'Размер экземпляра: {sys.getsizeof(obj)}')
print(f'Размер класса: {sys.getsizeof(SimpleClass)}')
# Размер экземпляра - это размер служебного объекта, атрибуты - отдельные объекты.Размер экземпляра: 56 Размер класса: 1056
4. Использование для отслеживания утечек памяти (шаблон)
import sys
import tracemalloc # Более современный и надежный инструмент
# Но для демонстрации с getsizeof:
def check_memory_growth(data_storage):
baseline = sys.getsizeof(data_storage)
# ... выполнение операций ...
data_storage.append('new_data' * 100)
after = sys.getsizeof(data_storage)
print(f'Рост памяти контейнера: {after - baseline} байт')
storage = []
check_memory_growth(storage)Рост памяти контейнера: 32 байт
5. Определение размера numpy массива
import sys
import numpy as np
arr = np.zeros((10, 10), dtype=np.float64)
print(f'sys.getsizeof (объект ndarray): {sys.getsizeof(arr)}')
print(f'nbytes (только данные): {arr.nbytes}')
# sys.getsizeof дает размер объекта Python-обертки, а nbytes - размер буфера данных.sys.getsizeof (объект ndarray): 176 nbytes (только данные): 800