J'essaye de construire un système où une classe de base est utilisée pour tous les autres objets. Chaque objet de base a un dictionnaire _fields
en interne où les implémentations de la classe de base peuvent stocker leurs informations.La combinaison de __setattr__ et __getattr__ provoque une boucle infinie
implémentation de la classe de base est assez simple:
class A(object):
def __init__(self, fields=dict()):
self._fields = fields
Une implémentation de la classe peut définir le champ dans l'appel __init__
à son super()
. Ce que je voudrais ajouter, c'est que les champs sont accessibles en tant que propriétés sans avoir à ajouter le décorateur @property
à un tas de fonctions. J'ai outrepassée le __getattr__
à cet effet dans la classe de base comme ceci:
class A(object):
def __init__(self, fields=dict()):
self._fields = fields
def __getattr__(self, name):
if hasattr(self, name):
return object.__getattribute__(self, name)
elif name in self._fields:
return self._fields.get(name)
else:
raise AttributeError
maintenant une implémentation de cette classe peut fonctionner comme ceci:
class A_impl(A):
def __init__(self):
super(A_impl, self).__init__(
fields=dict(
val_1="foo",
val_2="",
val_3="bar",
)
)
En ce qui créant une mise en œuvre de cette classe donne vous les options pour le faire:
test = A_imp()
print test.val_1
print test.val_2
print test.val_3
qui retourne
foo
bar
Je peux même passer outre ce via @property
décorateurs, changer la classe comme ceci:
class A_impl(A):
def __init__(self):
super(A_impl, self).__init__(
fields=dict(
val_1="foo",
val_2="",
val_3="bar",
)
)
@property
def val_1(self):
return self._fields.get('val_1') + "_getter"
Ce qui me permet de manipuler les données pour le retour. Le seul problème est que si je veux pouvoir régler l'une de ces variables de champ, je dois implémenter les fonctions du seteur des descripteur qui m'oblige également à faire le descripteur de propriété qui crée beaucoup de travail en double (ie je dois définir descripteurs pour tous mes champs qui est ce que je veux éviter ici.
I mis en œuvre la fonction __setattr__
pour la classe de base pour résoudre le problème où si je mets en œuvre manuellement une fonction setter descripteur il doit être choisi sur la valeur par défaut qui est self._field[name] = value
La classe de base ressemble maintenant à ceci (similaire au __getattr__
):
class A(object):
def __init__(self, fields=dict()):
self._fields = fields
def __getattr__(self, name):
if hasattr(self, name):
return object.__getattribute__(self, name)
elif name in self._fields:
return self._fields.get(name)
else:
raise AttributeError
def __setattr__(self, name, value):
if hasattr(self, name):
object.__setattr__(self, name, value)
elif name in self._fields:
self._fields[name] = value
else:
raise AttributeError
Maintenant, si je lance le même test de code à nouveau:
test = A_imp()
print test.val_1
print test.val_2
print test.val_3
Il se instantanément bloqué dans une boucle infinie, il commence au __setattr__
mais saute dans le __getattr__
juste après et maintient en boucle que. J'ai lu beaucoup de questions sur stackoverflow pour cela et je ne pouvais pas le comprendre, c'est pourquoi je construis ce cas de test pour le comprendre. J'espère que quelqu'un est capable de clarifier cela pour moi et m'aider à résoudre le problème.
Ce 'hasattr' est inutile. – o11c