Je veux définir une classe contenant la méthode read
et write
, qui peut être appelée comme suit:
instance.read
instance.write
instance.device.read
instance.device.write
Pour ne pas utiliser de classes entrelacées, mon idée était d'écraser le __getattr__
et __setattr__
méthodes et pour vérifier si le nom donné est device
pour rediriger le retour vers self
. Mais j'ai rencontré un problème donnant des récursions infinies. L'exemple de code est le suivant:
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)
Un péché __init__
le code a essayé de créer un nouvel attribut x
, il appelle __setattr__
, qui appelle à nouveau __setattr__
etc. Comment dois-je changer ce code, que, dans ce cas, un nouvel attribut x
de self
est créé, contenant la valeur 1
?
Ou existe-t-il une meilleure façon de gérer les appels comme instance.device.read
à "mapper" à instance.read
?
Comme il y a toujours des questions sur le pourquoi: j'ai besoin de créer des abstractions d'appels xmlrpc
, pour lesquelles des méthodes très simples comme myxmlrpc.instance,device.read
et similaires peuvent être créés. J'ai besoin de "simuler" cela pour imiter de tels appels à plusieurs points.
Vous devez appeler la classe parent __setattr__
méthode:
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)
En ce qui concerne la meilleure pratique, puisque vous prévoyez de l'utiliser via xml-rpc
Je pense que c'est probablement mieux de le faire à l'intérieur du _dispatch
méthode.
Un moyen rapide et sale est de simplement faire:
class My(object):
def __init__(self):
self.device = self
Ou vous pouvez modifier self.__dict__
De l'intérieur __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
Vous pouvez également utiliser objet.
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)
ou vous pouvez simplement utiliser @property:
class MyTest(object):
def __init__(self, x):
self.x = x
@property
def device(self):
return self