Voyons quelques exemples simples des deux __getattr__
et __getattribute__
des méthodes magiques.
__getattr__
Python appellera __getattr__
chaque fois que vous demandez un attribut qui n'a pas encore été défini. Dans l'exemple suivant, ma classe Comte n'a pas __getattr__
méthode. Maintenant, dans main, lorsque j'essaie d'accéder aux deux obj1.mymin
et obj1.mymax
attributs tout fonctionne bien. Mais lorsque j'essaie d'accéder à obj1.mycurrent
Python me donne AttributeError: 'Count' object has no attribute 'mycurrent'
class Count():
def __init__(self,mymin,mymax):
self.mymin=mymin
self.mymax=mymax
obj1 = Count(1,10)
print(obj1.mymin)
print(obj1.mymax)
print(obj1.mycurrent) --> AttributeError: 'Count' object has no attribute 'mycurrent'
Maintenant, ma classe Comte a __getattr__
méthode. Maintenant, lorsque j'essaie d'accéder à obj1.mycurrent
python me renvoie ce que j'ai mis en œuvre dans mon __getattr__
méthode. Dans mon exemple, chaque fois que j'essaie d'appeler un attribut qui n'existe pas, python crée cet attribut et lui attribue la valeur entière 0.
class Count:
def __init__(self,mymin,mymax):
self.mymin=mymin
self.mymax=mymax
def __getattr__(self, item):
self.__dict__[item]=0
return 0
obj1 = Count(1,10)
print(obj1.mymin)
print(obj1.mymax)
print(obj1.mycurrent1)
__getattribute__
Voyons maintenant le __getattribute__
méthode. Si vous avez __getattribute__
dans votre classe, python invoque cette méthode pour chaque attribut, qu'il existe ou non. Alors pourquoi avons-nous besoin de __getattribute__
méthode ? Une bonne raison est que vous pouvez empêcher l'accès aux attributs et les rendre plus sûrs, comme le montre l'exemple suivant.
Chaque fois que quelqu'un essaie d'accéder à mes attributs qui commencent par la sous-chaîne "cur Leçons de python AttributeError
exception. Sinon, il renvoie cet attribut.
class Count:
def __init__(self,mymin,mymax):
self.mymin=mymin
self.mymax=mymax
self.current=None
def __getattribute__(self, item):
if item.startswith('cur'):
raise AttributeError
return object.__getattribute__(self,item)
# or you can use ---return super().__getattribute__(item)
obj1 = Count(1,10)
print(obj1.mymin)
print(obj1.mymax)
print(obj1.current)
Important : Afin d'éviter une récursion infinie dans le programme __getattribute__
sa mise en œuvre doit toujours appeler la méthode de la classe de base portant le même nom pour accéder à tous les attributs dont elle a besoin. Par exemple : object.__getattribute__(self, name)
ou super().__getattribute__(item)
et non self.__dict__[item]
IMPORTANT
Si votre classe contient à la fois getattr et obtenir l'attribut méthodes magiques alors __getattribute__
est appelé en premier. Mais si __getattribute__
soulève AttributeError
l'exception sera ignorée et __getattr__
sera invoquée. Voir l'exemple suivant :
class Count(object):
def __init__(self,mymin,mymax):
self.mymin=mymin
self.mymax=mymax
self.current=None
def __getattr__(self, item):
self.__dict__[item]=0
return 0
def __getattribute__(self, item):
if item.startswith('cur'):
raise AttributeError
return object.__getattribute__(self,item)
# or you can use ---return super().__getattribute__(item)
# note this class subclass object
obj1 = Count(1,10)
print(obj1.mymin)
print(obj1.mymax)
print(obj1.current)
2 votes
Duplicata possible de Comprendre la différence entre __getattr__ et __getattribute__
12 votes
@Trilarion pourtant cette question mentionne une réponse d'ici...