La fonction de décoration doit renvoyer une fonction car tout ce qu'elle renvoie sera lié au nom de la fonction d'origine. Il est donc plutôt déroutant que l'objet retourné ne soit pas une fonction (ou un autre appelable, comme un constructeur de classe, ou une instance de classe appelable).
Généralement, la fonction retournée doit avoir une signature de fonction compatible avec la fonction d'origine, mais je suppose que c'est correct si la fonction retournée prend aussi des arguments supplémentaires. De même, le type de retour de la fonction renvoyée doit être compatible avec celui de la fonction d'origine.
Une fonction décorée est un peu comme une sous-classe de la fonction d'origine, et il est donc logique d'adhérer au Liskov substitution principle.
La fonction de décoration pourrait avoir des effets secondaires: par exemple, il pourrait modifier certains globaux. Cela peut être utile, par exemple à des fins de journalisation; OTOH, les fonctions devraient généralement éviter d'avoir des effets secondaires. FWIW, certains décorateurs de fonctions standard renvoient des appelables non-fonction, le plus commun étant probablement @classmethod
.
Il n'y a rien de particulièrement magique à propos des décorateurs. Comme Jared Goguen mentionne dans un commentaire,
@decorator
def some_function(args):
#etc
est identique à
def some_function(args):
#etc
some_function = decorator(some_function)
La deuxième forme est un peu plus long, mais plus puissant, puisque vous pouvez choisir de lier la fonction renvoyée à un autre nom , si tu veux. Certaines choses qui peuvent être facilement accomplies en utilisant la syntaxe plus longue peuvent être difficiles sinon carrément impossibles à faire en utilisant la syntaxe @
.
Le cas le plus courant consiste à renvoyer une nouvelle fonction (un wrapper) utilise la fonction passée, qui n'est pas une version modifiée de la fonction passée. –
@AlexHall Fonction modifiée, je veux dire, une fonction qui utilise la fonction transmise, dans tous les cas. – overexchange
OK, je voulais juste clarifier parce que parfois un décorateur peut simplement définir des attributs sur la fonction transmise et ensuite le renvoyer, ce que je pensais que vous vouliez dire par une version modifiée. –