Maison >développement back-end >Tutoriel Python >Qu'est-ce qu'une fonction de rappel ?

Qu'est-ce qu'une fonction de rappel ?

零下一度
零下一度original
2017-06-28 16:16:371058parcourir

Qu'est-ce qu'une fonction de rappel ?


Faisons un petit détour pour répondre à cette question.

La programmation est divisée en deux catégories : la programmation système et la programmation d'applications. En termes simples, la soi-disant programmation système consiste à écrire des bibliothèques ; et la programmation d'applications consiste à utiliser diverses bibliothèques écrites pour écrire des programmes avec certaines fonctions, c'est-à-dire des applications. Les programmeurs système laisseront certaines interfaces, à savoir l'API (interface de programmation d'application, interface de programmation d'application), aux bibliothèques qu'ils écrivent pour être utilisées par les programmeurs d'applications. Ainsi, dans le diagramme de la couche d'abstraction, la bibliothèque se trouve sous l'application.

Lorsque le programme est en cours d'exécution, dans des circonstances normales, le programme d'application appelle souvent des fonctions pré-préparées dans la bibliothèque via l'API. Cependant, certaines fonctions de la bibliothèque nécessitent que l'application lui transmette d'abord une fonction, afin qu'elle puisse être appelée au moment approprié pour terminer la tâche cible. La fonction transmise et appelée ultérieurement est appelée fonction de rappel.

Par exemple, un hôtel propose un service de réveil, mais demande aux clients de décider comment se réveiller. Vous pouvez appeler la chambre d'amis, envoyer un serveur frapper à la porte ou demander qu'on vous verse de l'eau sur la tête si vous avez tellement sommeil que vous avez peur de retarder les choses. Ici, le comportement de « réveil » est assuré par l'hôtel, ce qui équivaut à une fonction de bibliothèque, mais la méthode de réveil est décidée par le passager et communiquée à l'hôtel, ce qui est une fonction de rappel. L'action du passager indiquant à l'hôtel comment le réveiller, c'est-à-dire l'action de passer la fonction de rappel dans la fonction bibliothèque, est appelée pour enregistrer une fonction de rappel. Comme le montre la figure ci-dessous (source de l'image : Wikipédia) :


Comme vous pouvez le voir, la fonction de rappel se trouve généralement sur la même couche d'abstraction que l'application (car quel type de fonction de rappel est transmis dans est déterminé au niveau de l'application) . Le rappel devient un processus dans lequel la couche supérieure appelle la couche inférieure, et la couche inférieure appelle ensuite la couche supérieure. (Je pense) Cela devrait être la première application des rappels, et la raison pour laquelle ils sont nommés ainsi.

Avantages du mécanisme de rappel

Comme le montre l'exemple ci-dessus, le mécanisme de rappel offre une grande flexibilité. Veuillez noter qu'à partir de maintenant, nous appelons les fonctions de bibliothèque dans le diagramme des fonctions intermédiaires, car les rappels ne sont pas uniquement utilisés entre l'application et la bibliothèque. Chaque fois que vous souhaitez une flexibilité similaire à la situation ci-dessus, vous pouvez profiter des rappels.

Comment cette flexibilité est-elle obtenue ? À première vue, les rappels semblent n'être que des appels entre fonctions, mais si vous y réfléchissez bien, vous pouvez trouver une différence clé entre les deux : dans les rappels, nous utilisons une certaine méthode pour transmettre la fonction de rappel dans la fonction intermédiaire comme un paramètre. On peut comprendre que la fonction intermédiaire est incomplète avant qu'une fonction de rappel ne soit transmise. En d'autres termes, le programme peut décider et modifier le comportement des fonctions intermédiaires en enregistrant différentes fonctions de rappel au moment de l'exécution. C'est beaucoup plus flexible que de simples appels de fonction. Veuillez regarder l'exemple simple suivant de rappel écrit en Python :

`even.py`
#回调函数1#生成一个2k形式的偶数def double(x):    return x * 2    #回调函数2#生成一个4k形式的偶数def quadruple(x):    return x * 4
`callback_demo.py`
from even import *#中间函数#接受一个生成偶数的函数作为参数#返回一个奇数def getOddNumber(k, getEvenNumber):    return 1 + getEvenNumber(k)    #起始函数,这里是程序的主函数def main():        k = 1    #当需要生成一个2k+1形式的奇数时    i = getOddNumber(k, double)    print(i)    #当需要一个4k+1形式的奇数时    i = getOddNumber(k, quadruple)    print(i)    #当需要一个8k+1形式的奇数时    i = getOddNumber(k, lambda x: x * 8)    print(i)    if __name__ == "__main__":    main()


Exécutez `callback_demp.py`, le résultat est le suivant :

3
5
9


Dans le code ci-dessus, différentes fonctions de rappel sont transmises à `getOddNumber`, et leurs performances sont également différentes. C'est l'avantage du mécanisme de rappel. Il convient de mentionner que la troisième fonction de rappel ci-dessus est une fonction anonyme.

Le tiers qui est facilement ignoré

D'après la discussion ci-dessus, nous pouvons voir que la fonction intermédiaire et la fonction de rappel sont deux parties nécessaires du rappel, mais les gens ignorent souvent la troisième importante rôle dans le rappel , qui est l'appelant de la fonction intermédiaire. Dans la plupart des cas, cet appelant peut être assimilé à la fonction principale du programme, mais afin d'exprimer la différence, je l'appelle ici la fonction de démarrage (comme indiqué dans les commentaires dans le code ci-dessus).

La raison pour laquelle j'insiste particulièrement sur ce tiers est parce que j'ai eu l'impression, en lisant des articles pertinents en ligne, que beaucoup de gens le comprennent simplement comme un échange d'appels entre deux individus. Par exemple, lorsque de nombreuses pages Web chinoises expliquent « callback », elles mentionnent cette phrase : « Si vous m'appelez, je vous rappellerai ». Je n'ai pas trouvé la source anglaise de cette phrase. Personnellement, je suppose que beaucoup de gens considèrent la fonction initiale et la fonction de rappel comme une seule. Il y a probablement deux raisons : premièrement, le nom « rappel » peut être trompeur ; deuxièmement, quel type de fonction de rappel est transmis à la fonction intermédiaire ? déterminé dans la fonction de démarrage. En fait, le rappel n'est pas l'interaction entre « vous et moi », mais le lien tripartite d'ABC. Avec ce concept clair, il est moins susceptible de provoquer des confusions et des erreurs lors de l'implémentation des rappels dans votre propre code.

De plus, il existe en réalité deux types de rappels : les rappels bloquants et les rappels différés. La différence entre les deux est que dans les rappels bloquants, la fonction de rappel doit se produire avant le retour de la fonction initiale, tandis que dans les rappels retardés, la fonction de rappel peut être appelée après le retour de la fonction initiale ; Nous n’allons pas discuter ici plus en profondeur de ces deux probabilités. La raison pour laquelle elles sont mentionnées est d’illustrer l’importance de mettre l’accent sur la fonction de départ. De nombreux articles sur Internet, lorsqu'ils mentionnent ces deux concepts, disent simplement que les rappels bloquants se produisent avant le retour de la fonction d'appel principale, mais ne précisent pas si la fonction d'appel principale est la fonction de départ ou la fonction intermédiaire, ce qui rend inévitablement les gens confus, donc voici une explication spéciale. Notez également que les exemples de cet article bloquent les rappels. Les rappels différés impliquent généralement du multi-threading, je ne l'ai pas encore bien compris, donc je n'en dirai pas plus ici.

Permettez-moi de résumer ici. Normalement, nous écrivons une fonction, qui utilise diverses fonctions API dans le système, puis appelons la fonction que nous avons écrite en cas de besoin ; maintenant, la situation est inversée, nous écrivons d'abord une fonction, qui le fait ; n'appelons pas l'API système, puis nous appelons la fonction déjà écrite via l'API système, de sorte que la fonction que nous écrivons devienne la fonction de rappel.


Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn