__slots__ в классе и при наследовании
То есть мы вместо того, чтобы наследоваться от классов с конкретной реализацией (BaseA, BaseB), наследуемся от абстрактных классов
Однако __slots__
может вызвать проблемы при множественном наследовании.
Создание дочернего класса от родителей с обоими непустыми слотами не удается:
Если вы столкнетесь с этой проблемой, вы можете просто удалить __slots__
у родителей или, если вы контролируете родителей, дать им пустые слоты или выполнить рефакторинг для абстракций:
Добавьте '__dict__'
к __slots__
чтобы получить динамическое назначение:
и сейчас
Таким образом, с '__dict__'
в слотах мы теряем некоторые преимущества размера с преимуществом наличия динамического назначения и по-прежнему наличия слотов для имен, которые мы ожидаем
Когда вы наследуете объект, который не имеет слотов, вы получаете такую же семантику, когда используете __slots__
- имена, которые находятся в __slots__
, указывают на значения, размещенные в слотах, тогда как любые другие значения помещаются в __dict__
экземпляра.
Избегать __slots__
, потому что вы хотите иметь возможность добавлять атрибуты на лету, на самом деле не является хорошей причиной - просто добавьте '__dict__'
в свой __slots__
, если это необходимо.
Вы можете точно так же явно добавить __weakref__
в __slots__
, если вам нужна эта функция.
Подводя итоги: если вы составляете миксины или используете абстрактные базовые классы, которые не предназначены для создания экземпляров, пустой __slots__
в этих родителях кажется лучшим способом гибкости для подклассов.
Чтобы продемонстрировать, сначала давайте создадим код с классом, который мы хотели бы использовать при множественном наследовании.
Мы могли бы использовать вышесказанное непосредственно путем наследования и объявления ожидаемых слотов:
Но нас это не волнует, это тривиальное одиночное наследование, нам нужен другой класс, от которого мы также могли бы унаследовать, возможно, с шумным атрибутом:
Теперь, если бы на обеих базах были непустые слоты, мы не смогли бы сделать следующее. (На самом деле, если бы мы хотели, мы могли бы дать AbstractBase
непустые слоты a
и b
и исключить их из приведенного ниже объявления - оставлять их было бы неправильно):
И теперь у нас есть функциональность от обоих через множественное наследование, и мы все еще можем запретить создание экземпляров __dict__
и __weakref__
:
Last updated