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.