Question: comment faire pour générer un évenement de chargement après l’initialisation d’une classe, de manière générique ?
Sur cette simple question, prenons un example :
class A(object):
def __init__(self):
print 'init A'
class B(A):
def __init__(self):
print 'init B'
super(B, self).__init__()
print 'fin init B'
B()
Le programme affiche successivement :
init B
init A
fin init B
Le but est d’exécuter une fonction, à la fin de init B. Pour cela, on peut faire appel au décorateur python.
Voilà de quoi j’ai rêvé cette nuit (mmh…) :
def decorate_onload(f):
def my_init(*args, **kwargs):
inst = args[0]
if hasattr(inst, '__decorate_onload__'):
return f(*args, **kwargs)
inst.__setattr__('__decorate_onload__', True)
f(*args, **kwargs)
print 'launch on_load!'
return my_init
class A(object):
@decorate_onload
def __init__(self):
print 'init A'
class B(A):
@decorate_onload
def __init__(self):
print 'init B'
super(B, self).__init__()
print 'fin init B'
class C(B):
@decorate_onload
def __init__(self):
print 'init C'
super(C, self).__init__()
print 'fin init C'
C()
Et ce code magique affiche… :
init C
init B
init A
fin init B
fin init C
launch on_load!
Le print ‘on_load’, est bien appellé seulement quand l’intégralité du widget a terminé de charger !
Comment ca marche ? C’est tout simple :
def decorate_onload(f):
def my_init(*args, **kwargs):
inst = args[0]
Ici, on définit un nouveau décorateur, et on récupère l’instance de la classe en cours d’initialisation
if hasattr(inst, '__decorate_onload__'):
return f(*args, **kwargs)
L’instance de la classe est unique. Si la fonction de chargement est déjà hooker par un init, on ne fait rien.
inst.__setattr__('__decorate_onload__', True)
Sinon, on indique que l’on gère le onload. Cela sera valable au tout premier appel du décorateur sur l’instance => il sera toujours executé par le init de plus haut niveau.
f(*args, **kwargs)
print 'launch on_load!'
return my_init
On exécute le init normalement, et on affiche ‘on_load’. C’est ici que l’on peut remplacer par un appel de fonction sur l’instance de l’object.
Simple, encore fallait-il le trouver.