Перехват изменений атрибутов классов внутри класса — Python

StackOverflow https://stackoverflow.com/questions/676826

Вопрос

Я возился с 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__, ему придется извлекать атрибуты. через вызовы базового класса.

Если все, что вы пытаетесь сделать, это определить, были ли обновлены некоторые прямоугольники, то это излишне.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top