Licence CC BY-NC-ND
Thierry Parmentelat & Arnaud Legout
attributs et __getattr__#
On vous demande d’écrire une classe
Echoqui répond à toutes les méthodes dont le nom fait 3 lettres
et qui dans ce cas retourne le nom de la méthode concaténé 3 fois
>>> echo = Echo()
>>> echo.foo()
'foofoofoo'
>>> echo.bar()
'barbarbar'
>>> echo.six()
'sixsixsix''
Indices#
une seule méthode
__getattr__suffitelle doit renvoyer une méthode
ou lever l’exception AttributeError
class Echo:
def __getattr__(self, attrname):
if len(attrname) == 3:
# on pourrait écrire tripler()
# mais pour inspecter ce qui nous est vraiment passé
def tripler(*args, **kwds):
# print("incoming", args, kwds)
return attrname * 3
return tripler
else:
raise AttributeError(f"No such method {attrname} length = {len(attrname)} != 3")
echo = Echo()
echo.foo()
'foofoofoo'
echo.bar()
'barbarbar'
try:
echo.foobar()
except AttributeError as e:
print("OOPS", e)
OOPS No such method foobar length = 6 != 3
Deuxième partie#
on veut maintenant une classe Proxy
qu’on crée à partir d’une instance de
Echoet d’une blacklist (une liste de mots de 3 lettres)
et qui répond là encore à toutes les méthodes
dont le nom fait 3 lettres
en sous-traitant à son instance de
Echosauf pour les méthodes dans la blacklist
Indices#
très similaire au précédent
attention à bien appeler la méthode de
echoune fois que vous l’avez localisée
>>> blacklist = [ 'six', 'two', 'four']
>>> echo2 = BlacklistEcho(blacklist)
>>> echo2.foo()
'foofoofoo'
>>> echo2.six()
... raise AttributeError
class BlacklistEcho(Echo):
def __init__(self, blacklist):
super().__init__()
self.blacklist = blacklist
def __getattr__(self, attrname):
if attrname in self.blacklist:
raise AttributeError("blacklisted method {attrname}")
return super().__getattr__(attrname)
blacklist = [ 'six', 'two', 'four']
echo2 = BlacklistEcho(blacklist)
echo2.foo()
'foofoofoo'
try:
echo2.six()
except AttributeError as e:
print("OOPS", e)
OOPS blacklisted method {attrname}
try:
echo2.foobar()
except AttributeError as e:
print("OOPS", e)
OOPS No such method foobar length = 6 != 3