#26. Коллекция __slots__ | Объектно-ориентированное программирование Python
HTML-код
- Опубликовано: 27 сен 2024
- Курс по Python ООП: stepik.org/a/1...
Зачем нужна коллекция _slots_ в классах языка Python. Преимущества при ее использовании.
Плейлист по Python ООП: • Объектно-ориентированн...
Инфо-сайт: proproprogs.ru...
Telegram-канал: t.me/python_se...
Спасибо огромное за Ваш труд! Ваш канал точно лучший вариант для учебы в ру сегменте
Традиционное спасибо Сергею за отличный краткий и понятный урок!
Какая классная штука!
Очень доступно,как для младенцев)
Спасибо. Интересно. Вроде понятно. Надо попробовать.
2:42 Про недопустимость "z" - полностью согласен
Сделал замер времени для обоих классов как по инструкции, но класс Point2D со слотс в итоге дольше работал, чем Point без без слотс....
и у меня
У меня тоже
Благодарю!
С новим роком
спасибо
Урок #26 = Пройден
Узнал о __slots__, и его функциональности. На самом деле, в каких то изолированных классах, думаю, он будет полезен
👍
Хотелось бы уточнить, после подсчета используемой памяти мы считаем только сколько занял сам объект класса, но не добавляем объем занимаемой памяти __slots__.
Правильнее ли было, например, a.__sizeof__() + a.__slots__.__sizeof__() ? Поскольку slots тоже хранит атрибуты, не считать занимаемую им память неправильно
print(pt.__sizeof__() + pt.__dict__.__sizeof__()) # -> 120 байт
print(pt2.__sizeof__() + pt2.__slots__.__sizeof__()) # -> 72 байта
Но следует учитывать, что __slots__ - атрибут уровня класса (не копируется в экземпляры).
В общем, с __slots__ эффективнее по памяти.
а у меня без слотс 304 байта вышло,
хотя все как видео @@nevadawolf3040
Сергей, спасибо за труд. Остался вопрос. В чем необходимость создавать коллекцию __slots__, если, чтобы ограничить количество возможных создаваемых переменных экземпляра, можно переопределять метод __setattr__?
Что-то по типу:
def __setattr_(self, key, value):
if key == 'z': # любая переменная
raise AttributeError
Вопрос не относится к проблеме затрачиваемой памяти для каждого экземпляра класса.
этот код не будет работать, будет RecursionError
@@thenoteasy все будет работать, даже показывали такой пример в уроке с __setattr__ , просто логичнее перебрать все разрешенные, а не все запрещенные. Разрешенных то всяко меньше будет)
Можете после этого курса, создать курс по асинхронности в питоне?)
Мне нужен по машинному обучению для студентов - буду его делать.
@@selfedu_rus Сергей у вас уже есть курс по машинному обучению?
@@nomadicus77 Да, см. на канале плейлист "Машинное обучение"
Здравствуйте, Сергей! Спасибо за урок. Возникли вопросы, при создании класса выделяется память именно под него?. Ведь он может иметь свои атрибуты, также о какой именно памяти идется при вызове __sizeof__ на экземпляре класса, другими словами, зачем выделять память под экземпляр класса, если все его атрибуты хранятся в __dict__. В чем разница между памятью выделяемой под __dict__ и для экземпляра класса, __dict__ это же фактически пространство имен, если мы через него можем менять локальные атрибуты?
Хороший вопрос. Я, как то, об этом не задумывался. Сейчас сделал небольшой тест:
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
p = Point(1, 2)
print(p.__sizeof__())
print(p.__dict__.__sizeof__())
print(sys.getsizeof(p))
print(sys.getsizeof(Point))
Здесь getsizeof() функция определения объема занимаемой объектом памяти. Получается класс Point занимает 1064 байт, а p значительно меньше. Я не знаю, как в деталях происходит хранение и представление объектов и отдельно классов. Наверное это нужно погуглить ))
@@selfedu_rus спасибо за ответ)
Огромное спасибо за видео.
Но у меня все же остались вопросы.
Первый вопрос по поводу памяти: при использовании __slots__ коллекция __dict__ отсутствует, но зато появляется коллекция __slots__(извиняюсь за тавтологию) ==> память = pt.__sizeof__() + pt.__slots__.__sizeof__(), или нет?
Второй вопрос по поводу самой коллекции __slots__: __slots__ задаем как кортеж(неизменяемый объект), но никто не мешает задать его списком и тогда мы сможем добавить в коллекцию __slots__ еще один элемент pt.__slots__.append('s'). Но вот беда, элемент добавляется, но тем не менее ему нельзя присвоить значение pt.s = 'что-то' (AttributeError: 'Point3D' object has no attribute 's'). Вот это мне не понятно, элемент в коллекции появился, а сделать с ним ничего нельзя. как так?
Попробую сам ответить на второй вопрос.
__slots__ свойство класса которое не копируется в экземпляр, экземпляр имеет лишь ссылку на это свойство. По всей видимости строчка pt.__slots__.append('s') создает __slots__ в экземпляре (только вот где она сохраняется ведь __dict__ нет???), при попытки записать чего то pt.s = 'что-то' и поскольку __dict__ в экземпляре нет, автоматически берется __slots__ из класса, отсюда и AttributeError: 'Point3D' object has no attribute 's'.
Вообщем-то в первом вопросе понял где не прав))))
Как такое объяснить)))
class Point3D:
__slots__ = ['x', 'y', 'z']
def __init__(self, x , y, z):
self.x = x
self.y = y
self.z = z
pt1 = Point3D(10, 20, 30)
pt1.__slots__.append('s')
print(id(pt1.__slots__), id(Point3D.__slots__), pt1.__slots__, Point3D.__slots__, sep='
')
_____________________________
140379690590688
140379690590688
['x', 'y', 'z', 's']
['x', 'y', 'z', 's']
_____________________________
pt1.s = 100
_______________________
AttributeError: 'Point3D' object has no attribute 's'
@@dubinin_s атрибуту __slots__ можно присвоить любой итерируемый объект, интерпритатор Python помещает его в кортежеподобную структуру в каждом экземпляре. Что при этом происходит мне неизвестно, но я читал, что у __slots __ много подводных камней.
@@n0rmaLman спасибо и на таком ответе))
Если не до конца понятно, пока пропустите. Понадобится - разберетесь. Так во всем )
как я понял, в версии 3.11 теперь можно создавать локальные аттрибуты, даже если они не указаны в коллекции __slots__, то есть эта коллекция теперь используется только для экономии памяти?
Прикинь, у меня вообще __slots__ ускорял работу только при третьей попытки, т1 работал быстрее т2, но я думаю все из-за моего слабого процессора на Ноутбуке, Pentium silver
У меня тож версия 3.11, у тебя __slots__ ускорял работу локальных атрибутов?
Прежде всего коллеция _slots__ запрещает создавать другие атрибуты. Иногда это полезно.
Большое спасибо за ваши уроки! Сначала я понимал процентов 40-60, но с кааждым новым уроком начинаю лучше понимать и предыдущие темы
здравствуйте а где 25 урок ?
Сергей, спасибо вам за ваш труд!!!
Спасибо за урок, с каждой темой понимаю все больше и больше
используя __slots__ далеко не факт, что будет экономиться память. например, если оба класса будут содержать по 8 переменных, то экземпляр класса Point2d уже будет занимать больше памяти, чем экземпляр класса Point.
коллекция __slots__ - атрибут уровня класса и она не копируется в экземпляры, поэтому ее размер учитывать не нужно
@@selfedu_rus понял) хотя, скорее всего, на практике, такое мало пригодится) в __dict__ класса, использующего __slots__ будет содержаться та же информация, что и в классе, использующем __dict__, + __slots__: (переменные). я о том, что сам класс будет занимать немного больше места в памяти, но каждый его экземпляр будет эту память экономить, занимая намного меньше места, по сравнению с классом, использующим __dict__.
Как всегда спасибо. Сергей, если не трудно подтвердите мои умозаключения по данному уроку. Метод __slots__ предлагает способ для оптимизации скорости приложения посредством его внедрения в классы. Экземпляры, которых в рамках общего алгоритма не учавствуют или не требуют манипуляций над локальными свойствами этого объекта.
да, слотс позволяет экономить память по локальным свойствам, дает ускорение и запрещает использовать (создавать) другие локальные свойства в экземплярах
Я объявил __slots__ через метод класса, и он почему-то не работает. Как быть?
slots должен быть атрибутом класса, а не его экземпляра
Почему перезалив?