После просмотра выступления Нины Захкаренко по управлению памятью Python на Pycon2016 ( link ) показалось, что метод dunder __slots__
был инструментом для уменьшения размера объекта и ускорения поиска атрибутов.
Я ожидал, что нормальный класс будет самым большим, тогда как подход __slots__
/ namedtuple
сэкономит место. Однако быстрый эксперимент доказал, что я не прав:
from collections import namedtuple
from sys import getsizeof
class Rectangle:
'''A class based Rectangle, with a full __dict__'''
def __init__(self, x, y, width, height):
self.x = x
self.y = y
self.width = width
self.height = height
class SlotsRectangle:
'''A class based Rectangle with __slots__ defined for attributes'''
__slots__ = ('x', 'y', 'width', 'height')
def __init__(self, x, y, width, height):
self.x = x
self.y = y
self.width = width
self.height = height
NamedTupleRectangle = namedtuple('Rectangle', ('x', 'y', 'width', 'height'))
NamedTupleRectangle.__doc__ = 'A rectangle as an immutable namedtuple'
print(f'Class: {getsizeof(Rectangle(1,2,3,4))}')
print(f'Slots: {getsizeof(SlotsRectangle(1,2,3,4))}')
print(f'Named Tuple: {getsizeof(NamedTupleRectangle(1,2,3,4))}')
Терминальный выход:
$ python3.7 example.py
Class: 56
Slots: 72
Named Tuple: 80
Что здесь происходит? Из документации * Python Модель данных видно, что для __slots__
используются дескрипторы, которые добавили бы служебную нагрузку к классам, реализующим ее. Однако почему результаты так сильно отклоняются от нормального класса?
Направляя мой внутренний Рэймонд Х .: должен быть более трудный путь!