Pregunta

He estado jugando con pygame y python, y quiero ser capaz de llamar a una función cuando un atributo de mi clase ha cambiado.Mi solución:

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()

Esto funciona bien y dofancystuff se llama cuando cambio el valor rect con Firsclass.rect = pygame.rect.Rect(0,0,100,100).Sin embargo, si yo digo Firstclass.rect.bottom = 3. __setattr__ y no para dofancystuff no es llamado.

Así que mi pregunta supongo que es ¿cómo puedo interceptar cualquier cambio a un atributo de una subclase?

editar:También Si voy sobre esto de la manera equivocada por favor, dígale que no estoy muy bien informado cuando se trata de python.

¿Fue útil?

Solución

Bueno, la respuesta simple es que no puede. En el caso de Firstclass.rect = <...> su __setattr__ se llama. Pero en el caso de Firstclass.rect.bottom = 3 el método de la instancia Rect <=> se llama. La única solución que veo, es crear una clase derivada de pygame.rect.Rect donde se puede sobreescribir el método <=>. También puede mono parchear la clase Rect, pero esto no se recomienda por buenas razones.

Otros consejos

Usted podría intentar __getattr__, que debe ser llamado a Firstclass.rect.

Sin embargo, debe hacerse lo siguiente: Crear una clase separada (subclase de pygame.rect?) Para ExampleClass.rect. Implementar __setattr__ en esa clase. Ahora se le informará sobre cualquier cosa que consigue el sistema en su rect miembro por ExampleClass. Todavía se puede poner en práctica en Firstclass <=> (y debe ), sólo que ahora asegurarse de que se ejemplariza una versión de su propia clase <=> ...

Por cierto: No llame a sus objetos <=>, como entonces se ve como una clase en lugar de un objeto ...

Esto no es responder a la pregunta, pero es relevante:

self.__dict__[name] = value

es probablemente mejor que

parentClass.__setattr__(self, name, value)

Esto es recomendado por la documentación de Python (setattr "> http://docs.python.org/2/reference/datamodel.html?highlight=setattr#object. setattr ) y hace más sentido de todos modos, en el caso general, ya que no asume nada sobre el comportamiento de ParentClass setattr .

Yay para el consejo no solicitado cuatro años demasiado tarde!

Creo que la razón por la que tiene esta dificultad merece un poco más información que la proporcionada por las otras respuestas.

El problema es que cuando haces:

myObject.attribute.thing = value

Usted no está asignando un valor al atributo. El código es equivalente a esto:

anAttribute = myObject.attribute
anAttribute.thing = value

Como es visto por myObject, todo lo que estamos haciendo conseguir el atributo; usted no está estableciendo el atributo.

Hacer subclases de sus atributos que usted controla, y puede definir para __setattr__ es una solución.

Una solución alternativa, que puede tener sentido si usted tiene un montón de características de diferentes tipos y no quiere hacer un montón de subclases individuales para todos ellos, es para anular o __getattribute__ __getattr__ para devolver una fachada para el atributo que realiza las operaciones pertinentes en su método __setattr__. No he tratado de hacer esto, pero me imagino que debe ser capaz de hacer una clase simple fachada que actuará como una fachada para cualquier objeto.

tendría que ser tomada en la elección de __getattribute__ Cuidado y __getattr__ . Consulte la documentación vinculada en la frase anterior para obtener información, pero básicamente, si se utiliza __getattr__, los atributos reales habrán de ser encapsulado superior / ofuscado alguna manera para que __getattr__ gestiona las peticiones para ellos, y si __getattribute__ que se utilice, tendrá que recuperar los atributos a través de llamadas a una clase base.

Si todo lo que estamos tratando de hacer es determinar si algunas rectas han sido actualizadas, entonces esto es una exageración.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top