Voici une légère altération du code présenté par Sam dans son article pattern observer en utilisant les décorateurs:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
def evenement(nom):
# on assure que la liste des events et callabcks est initialisae
evenement.abonnements = getattr(evenement, 'abonnements', {})
# définition du décorateur lui-même
def decorateur(func):
# on ajoute la fonction comme callback pour cet event
evenement.abonnements.setdefault(nom, []).append(func)
# et on retourne la fonction telle qu'elle, sans la modifier
return func
return decorateur
# on ajoute un moyen d'appeler tous les callbacks pour un event
evenement.trigger = lambda e: [f(e) for f in evenement.abonnements[e]]
# a chaque fois qu'on met le decorateur
# la fonction est liae à un événement
@evenement('evenement1')
@evenement('evenement2')
def reagir_a_evenement(evenement):
# la fonction doit acccepter l'evenement en paramètre
print("Oh, evenement '%s' a eu lieu" % evenement)
@evenement('evenement1')
def moi_aussi(evenement):
print("Cool, moi aussi j'ai reagit a l'evenement '%s'" % evenement)
# ici on déclenche l'événement sans raison
# mais dans du vrai code on le déclenche à la suite
# d'une action réelle
evenement.trigger('evenement1')
evenement.trigger('evenement2')
J’ai juste déplacé trigger après le décorateur et du coup à l’exécution j’ai:
AttributeError: 'function' object has no attribute 'trigger'
Pourquoi ce déplacement casse tout ?