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)