str round español python python-2.7 getattr setattr

python - round - Cómo usar__setattr__ correctamente, evitando la recursión infinita



round python 3 (3)

Quiero definir una clase que contenga el método de read y write , que se puede llamar de la siguiente manera:

instance.read instance.write instance.device.read instance.device.write

Para no usar clases entrelazadas, mi idea era sobrescribir los métodos __getattr__ y __setattr__ y verificar, si el nombre de pila es un device para redirigir el retorno a self . Pero encontré un problema dando infinitas recursiones. El código de ejemplo es el siguiente:

class MyTest(object): def __init__(self, x): self.x = x def __setattr__(self, name, value): if name=="device": print "device test" else: setattr(self, name, value) test = MyTest(1)

Como en __init__ el código intentó crear un nuevo atributo x , llama a __setattr__ , que de nuevo llama a __setattr__ y así sucesivamente. ¿Cómo necesito cambiar este código, que, en este caso, se crea un nuevo atributo x de mí self , manteniendo el valor 1 ?

¿O hay alguna forma mejor de manejar llamadas como instance.device.read para ser ''mapeado'' a instance.read ?

Como siempre hay preguntas sobre por qué: Necesito crear abstracciones de llamadas xmlrpc , para lo cual se pueden crear métodos muy fáciles como myxmlrpc.instance,device.read y similares. Necesito ''simular'' esto para imitar esas llamadas de método de puntos múltiples.


Debe llamar al método de clase padre __setattr__ :

class MyTest(object): def __init__(self, x): self.x = x def __setattr__(self, name, value): if name=="device": print "device test" else: super(MyTest, self).__setattr__(name, value) # in python3+ you can omit the arguments to super: #super().__setattr__(name, value)

Con respecto a las mejores prácticas, dado que planea usar esto a través de xml-rpc , creo que esto probablemente se haga mejor dentro del método _dispatch .

Una manera rápida y sucia es simplemente hacer:

class My(object): def __init__(self): self.device = self


O puede modificar self.__dict__ desde inside __setattr__() :

class SomeClass(object): def __setattr__(self, name, value): print(name, value) self.__dict__[name] = value def __init__(self, attr1, attr2): self.attr1 = attr1 self.attr2 = attr2 sc = SomeClass(attr1=1, attr2=2) sc.attr1 = 3


También puedes usar object .

class TestClass: def __init__(self): self.data = ''data'' def __setattr__(self, name, value): print("Attempt to edit the attribute %s" %(name)) object.__setattr__(self, name, value)