Maison >développement back-end >Tutoriel Python >Explication détaillée des générateurs en Python
Avec la génération de liste, on peut créer directement une liste. Cependant, en raison de contraintes de mémoire, la capacité de la liste est définitivement limitée. De plus, créer une liste contenant 1 million d'éléments prend non seulement beaucoup d'espace de stockage, mais si nous n'avons besoin d'accéder qu'aux premiers éléments, l'espace occupé par la plupart des éléments suivants sera gaspillé. Ainsi, si les éléments de la liste peuvent être calculés selon un certain algorithme, pouvons-nous calculer en continu les éléments suivants pendant la boucle ? Cela élimine le besoin de créer une liste complète, économisant ainsi beaucoup d’espace. En Python, ce mécanisme de bouclage et de calcul à la fois s'appelle un générateur : générateur.
Il existe de nombreuses façons de créer un générateur. La première méthode est très simple, il suffit de changer le [ ] d'une génération de liste en ( )
La différence entre créer L et G est uniquement le [ ] et ( ), L est une liste et G est un générateur. On peut imprimer directement chaque élément de L, mais comment imprimer chaque élément de G ? Si vous souhaitez les imprimer un par un, vous pouvez obtenir la prochaine valeur de retour du générateur via la fonction next() :
Le générateur enregistre l'algorithme, et chaque fois que next( est appelé G), calculez la valeur de l'élément suivant de G jusqu'à ce que le dernier élément soit calculé. Lorsqu'il n'y a plus d'éléments, une exception StopIteration est levée. Bien sûr, ce type d'appel continu à next() est vraiment anormal. La bonne méthode consiste à utiliser une boucle for, car le générateur est également un objet itérable. Ainsi, après avoir créé un générateur, nous n'appelons pratiquement jamais next(), mais nous le parcourons dans une boucle for et nous n'avons pas besoin de nous soucier de l'exception StopIteration.
le générateur est très puissant. Si l'algorithme de calcul est relativement complexe et ne peut pas être implémenté à l'aide d'une boucle for similaire à la génération de liste, il peut également être implémenté à l'aide d'une fonction.
Par exemple, dans la célèbre séquence de Fibonacci, à l'exception du premier et du deuxième nombres, n'importe quel nombre peut être obtenu en additionnant les deux premiers nombres :
1, 1, 2, 3, 5 , 8, 13, 21, 34, ...
La séquence de Fibonacci ne peut pas être écrite en utilisant la génération de liste, mais il est facile de l'imprimer à l'aide d'une fonction :
En regardant attentivement, vous pouvez voir que la fonction fib est réellement définie. Après avoir compris les règles de calcul de la séquence de Fibonacci, vous peut partir du premier élément et calculer les éléments suivants. Cette logique est en fait très similaire au générateur.
En d'autres termes, la fonction ci-dessus n'est qu'à un pas du générateur. Pour transformer la fonction fib en générateur, changez simplement print(b) pour rendement b :
Mais lors de l'appel du générateur à l'aide d'une boucle for, j'ai constaté que je ne pouvais pas obtenir la valeur de retour de l'instruction return du générateur. Si vous souhaitez obtenir la valeur de retour, vous devez capturer l'erreur StopIteration. La valeur de retour est incluse dans la valeur de StopIteration :
Exemple : lors de l'exécution de rendement, la fonction gen est temporairement enregistrée et renvoie la valeur de i ; temp reçoit la prochaine fois que c.send("python"), la valeur envoyée par send, c .next() est équivalent à c.send(Aucun)
Utiliser la fonction suivante
Utiliser la méthode __next__()
Utiliser send
Résultat d'exécution :
Simuler implémentation multitâche Un : Coroutine
Résumé
Generator est une fonction qui mémorise la position dans le corps de la fonction lors de son dernier retour. Le deuxième (ou nième) appel à une fonction génératrice saute au milieu de la fonction, laissant toutes les variables locales inchangées par rapport à l'appel précédent.
Un générateur "se souvient" non seulement de l'état de ses données ; un générateur "se souvient" également de sa position dans une construction de contrôle de flux (en programmation impérative, cette construction n'est pas seulement une valeur de données).
Caractéristiques du générateur :
1. Économiser de la mémoire
2 Lors de l'itération jusqu'à l'appel suivant, les paramètres utilisés sont tous conservés la première fois, c'est-à-dire. pour dire, les paramètres de tous les appels de fonction sont conservés lorsqu'ils sont appelés pour la première fois, plutôt que nouvellement créés
L'itération est utilisée pour accéder aux éléments de collection d'une manière. Un itérateur est un objet qui mémorise la position d'un parcours. L'objet itérateur commence à accéder à partir du premier élément de la collection jusqu'à ce que tous les éléments aient été accédés. Les itérateurs ne peuvent qu'avancer et non reculer.
Les types de données qui agissent directement sur les boucles for sont les suivants :
Un type est constitué des types de données de collection, tels que list, tuple, dict , set, str, etc.;
La première catégorie est le générateur, y compris le générateur et la fonction génératrice avec rendement.
Ces objets qui peuvent être directement utilisés dans les boucles for sont collectivement appelés objets itérables : Iterable.
Vous pouvez utiliser isinstance() pour déterminer si un objet est un objet itérable :
Le générateur peut non seulement agir sur la boucle for, mais peut aussi être appelé en continu par la fonction next() et renvoyer la valeur suivante, jusqu'à ce que finalement une erreur StopIteration est générée pour indiquer qu'il ne peut pas continuer à revenir à la valeur suivante.
Un objet qui peut être appelé par la fonction next() et renvoie continuellement la valeur suivante est appelé un itérateur : Itérateur.
Générateur Ils sont tous des objets Iterator, mais bien que list, dict et str soient itérables, ils ne sont pas des itérateurs.
Pour convertir list, dict, str et autres Iterables en Iterator, vous pouvez utiliser la fonction iter() :
Résumé
·Tous les objets pouvant être utilisés dans les boucles for sont de type Iterable
·Tous les objets pouvant être utilisés dans la fonction next() sont de type Iterator
·Les types de données de collection tels que list, dict, str, etc. sont Iterable mais pas Iterator, mais vous pouvez obtenir un objet Iterator via la fonction iter().
·Le but est de réduire le contenu occupé lors de l'utilisation des collections.
1. Référence de la fonction
Dans cet exemple, la ligne de fonction et les variables a et b forment une fermeture. Lors de la création de la fermeture, nous précisons les valeurs de ces deux variables via les paramètres a et b de line_conf. De cette manière, nous déterminons la forme finale de la fonction (y = x + 1 et y = 4x + 5). Il suffit de transformer les paramètres a et b pour obtenir différentes fonctions d'expression en ligne droite. De là, nous pouvons voir que les fermetures ont également pour effet d’améliorer la réutilisabilité du code.
S'il n'y a pas de fermeture, nous devons spécifier a, b, x chaque fois que nous créons une fonction de ligne droite. De cette façon, nous devons transmettre plus de paramètres, ce qui réduit également la portabilité du code
Si vous rencontrez des problèmes pendant le processus d'apprentissage ou si vous souhaitez obtenir des ressources d'apprentissage, vous êtes invités à rejoindre le groupe d'échange d'apprentissage
626062078, on apprend Python ensemble !
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!