Перехват изменений атрибутов классов внутри класса — Python
-
21-08-2019 - |
Вопрос
Я возился с pygame и python и хочу иметь возможность вызывать функцию, когда атрибут моего класса изменился.Мое текущее решение:
class ExampleClass(parentClass):
def __init__(self):
self.rect = pygame.rect.Rect(0,0,100,100)
def __setattr__(self, name, value):
parentClass.__setattr__(self,name,value)
dofancystuff()
Firstclass = ExampleClass()
Это работает нормально, и dofancystuff вызывается, когда я меняю прямоугольное значение с помощью Firsclass.rect = pygame.rect.Rect(0,0,100,100)
.Однако если я скажу Firstclass.rect.bottom = 3
. __setattr__
и там мелочами не называют.
Итак, мой вопрос, я думаю, заключается в том, как я могу перехватить любое изменение атрибута подкласса?
редактировать:Также, если я делаю это неправильно, пожалуйста, скажите, что я не очень разбираюсь в Python.
Решение
Ну, простой ответ: вы не можете.В случае Firstclass.rect = <...>
твой __setattr__
называется.Но в случае Firstclass.rect.bottom = 3
тот __setattr__
вызывается метод экземпляра Rect.Единственное решение, которое я вижу, — это создать производный класс pygame.rect.Rect, в котором вы перезапишете __setattr__
метод.Вы также можете обновить класс Rect, но это не рекомендуется по веским причинам.
Другие советы
Вы могли бы попробовать __getattr__
, который следует вызвать Firstclass.rect
.
Но вместо этого сделайте следующее:Создайте отдельный класс (подкласс pygame.rect
?) для ExampleClass.rect
.Осуществлять __setattr__
в этом классе.Теперь вам расскажут обо всем, что будет установлено в вашем rect
член для ExampleClass
.Вы все еще можете реализовать __setattr__
в ExampleClass
(и должен), только теперь убедитесь, что вы создали собственную версию rect
сорт...
КСТАТИ:Не называйте свои объекты Firstclass
, поскольку тогда это выглядит как класс, а не как объект...
Это не ответ на вопрос, но это важно:
self.__dict__[name] = value
вероятно, лучше, чем
parentClass.__setattr__(self, name, value)
Это рекомендуется в документации Python (setattr">http://docs.python.org/2/reference/datamodel.html?highlight=setattr#object.setattr) и в любом случае имеет больше смысла в общем случае, поскольку ничего не предполагает о поведении родительского класса. setattr.
Ура, непрошеный совет опоздал на четыре года!
Я думаю, что причина, по которой у вас возникла эта трудность, заслуживает немного большей информации, чем содержится в других ответах.
Проблема в том, что когда вы делаете:
myObject.attribute.thing = value
Вы не присваиваете значение атрибуту.Код эквивалентен этому:
anAttribute = myObject.attribute
anAttribute.thing = value
Как видит myObject, все, что вы делаете, это получение атрибута;вы не устанавливаете атрибут.
Одним из решений является создание подклассов ваших атрибутов, которыми вы управляете и для которых можете определить __setattr__.
Альтернативное решение, которое может иметь смысл, если у вас много атрибутов разных типов и вы не хотите создавать для них множество отдельных подклассов, — переопределить __getattribute__ или __getattr__, чтобы вернуть фасад атрибуту, который выполняет соответствующие действия. операции в своем методе __setattr__.Я не пытался сделать это сам, но полагаю, что вы сможете создать простой класс фасада, который будет действовать как фасад для любого объекта.
Необходимо будет внимательно отнестись к выбору __getattribute__ и __getattr__.Информацию см. в документации, указанной в предыдущем предложении, но в основном, если используется __getattr__, фактические атрибуты будут каким-то образом инкапсулированы/запутаны, чтобы __getattr__ обрабатывал запросы для них, а если используется __getattribute__, ему придется извлекать атрибуты. через вызовы базового класса.
Если все, что вы пытаетесь сделать, это определить, были ли обновлены некоторые прямоугольники, то это излишне.