Maison >développement back-end >Tutoriel Python >Analysons ensemble la programmation fonctionnelle Python
Cet article vous apporte des connaissances pertinentes sur python, qui introduit principalement des problèmes liés à la programmation fonctionnelle, c'est-à-dire que dans le paradigme impératif, les tâches sont accomplies en fournissant à l'ordinateur une série d'instructions puis en les exécutant. .
Apprentissage recommandé : Tutoriel d'apprentissage Python
Dans cet article, vous apprendrez ce qu'est le paradigme fonctionnel et comment utiliser Python pour la programmation fonctionnelle. Vous découvrirez également la compréhension de listes et d’autres formes de compréhension.
Dans le paradigme impératif, une tâche est accomplie en donnant à l'ordinateur une séquence d'instructions puis en les exécutant. Lors de l'exécution de ces instructions, certains états peuvent être modifiés. Par exemple, supposons que vous définissiez initialement A sur 5, puis que vous modifiiez la valeur de A. A ce moment, vous changez l'état de A dans le sens de la valeur interne de la variable.
Dans le paradigme fonctionnel, vous ne dites pas à l'ordinateur quoi faire mais vous lui dites ce que c'est. Par exemple, quel est le plus grand diviseur commun des nombres, quel est le produit de 1 par n, etc.
Par conséquent, les variables ne peuvent pas changer. Une fois que vous avez défini une variable, elle le reste pour toujours (notez que dans les langages purement fonctionnels, ce ne sont pas des variables). La programmation fonctionnelle n’a donc aucun effet secondaire. Un effet secondaire se produit lorsqu'une fonction modifie autre chose qu'elle-même. Regardons quelques exemples de code Python typique :
La sortie de ce code est 5. Dans le paradigme fonctionnel, la mutation des variables est un grand non-non, et avoir des fonctions qui affectent des choses en dehors de leur portée est également un grand non-non. La seule chose qu’une fonction peut faire est de calculer quelque chose et de le renvoyer en conséquence.
Maintenant, vous pensez peut-être : « Pas de variables, pas d'effets secondaires ? Pourquoi est-ce bon ? » C'est une bonne question, je suis sûr que la plupart des gens sont confus à ce sujet.
Si une fonction est appelée deux fois avec les mêmes paramètres, elle est garantie de renvoyer le même résultat. Si vous avez étudié les fonctions mathématiques, vous en connaîtrez les avantages. C’est ce qu’on appelle la transparence référentielle. Étant donné que les fonctions n'ont aucun effet secondaire, si vous créez un programme qui calcule quelque chose, vous pouvez accélérer le programme. Si func(2) renvoie 3 à chaque fois que nous l'appelons, nous pouvons le stocker dans une table, ce qui empêche le programme d'exécuter la même fonction à plusieurs reprises.
Normalement, en programmation fonctionnelle, nous n'utilisons pas de boucles. Nous utilisons la récursion. La récursivité est un concept mathématique qui signifie généralement « s'appeler ». Utilisez une fonction récursive qui s'appelle à plusieurs reprises comme sous-fonction. Voici un bon exemple de fonctions récursives en Python :
Certains langages de programmation sont également paresseux. Cela signifie qu'ils ne calculent ni ne font quoi que ce soit avant la dernière seconde. Si vous écrivez du code pour faire 2 + 2, le programme fonctionnel ne le calculera que lorsque vous aurez réellement besoin d'utiliser le résultat. Nous explorerons bientôt la paresse en Python.
Pour comprendre, regardons d'abord ce qu'est l'itération. Généralement, les objets qui peuvent être itérés sont des listes ou des tableaux, mais Python propose de nombreux types différents qui peuvent être itérés. Vous pouvez même créer vos propres objets qui peuvent être itérés en implémentant des méthodes magiques. Les méthodes magiques sont comme une API qui aide vos objets à devenir plus pythoniques. Vous devez implémenter 2 méthodes magiques pour rendre un objet itérable :
La première méthode magique "__iter__" (note : double trait de soulignement ici) renvoie l'objet itérable, elle est généralement utilisée au début d'une boucle. "__next__" renvoie l'objet suivant.
Entrons rapidement dans un terminal et appelons le code ci-dessus :
L'exécution imprimera
En Python, un itérateur est un objet avec uniquement la méthode magique __iter__. Cela signifie que vous pouvez accéder aux emplacements au sein d'un objet, mais vous ne pouvez pas traverser l'objet. Certains objets auront la méthode magique __next__ au lieu de la méthode magique __iter__, comme les collections (abordées plus loin dans cet article). Pour cet article, nous supposerons que tout ce que nous touchons est un objet itérable.
Maintenant que nous savons ce qu'est un objet itérable, revenons à la fonction map. La fonction map nous permet d'appliquer une fonction à chaque élément de l'itérable. Map nécessite 2 entrées, qui sont la fonction à appliquer et l'objet itérable.
Supposons que nous ayons une liste de nombres comme celle-ci :
Nous voulons mettre chaque nombre au carré, nous pouvons écrire le code suivant :
Les fonctions fonctionnelles en Python sont paresseuses. Si nous n'utilisons pas "list", la fonction stockera la définition d'itérable au lieu de la liste elle-même. Nous devons explicitement dire à Python de « transformer cela en une liste » que nous pouvons utiliser.
C'est un peu étrange de passer soudainement d'une évaluation non paresseuse à une évaluation paresseuse en Python. Si vous pensez davantage d’une manière fonctionnelle plutôt que d’une manière impérative, vous finirez par vous y habituer.
Maintenant, écrire une fonction normale comme "square(num)" est sympa mais pas correct. Doit-on définir une fonction complète pour l'utiliser dans map ? Eh bien, nous pouvons définir une fonction dans map en utilisant la fonction lambda (anonyme).
Une expression lambda est une fonction avec une seule ligne. Par exemple, cette expression lambda met au carré un nombre donné :
Lançons-la :
Cela ne ressemble-t-il pas à une fonction ?
Eh bien, c'est un peu déroutant, mais explicable. Nous attribuons quelque chose à la variable "carré". Qu'en est-il de celui-ci :
indique à Python qu'il s'agit d'une fonction lambda et que l'entrée s'appelle x. Tout ce qui se trouve après les deux points correspond à ce que vous faites avec l'entrée et renvoie automatiquement le résultat.
Pour simplifier notre programme carré à une seule ligne de code, nous pouvons faire ceci :
Donc, dans l'expression lambda, tous les paramètres sont à gauche et les choses que vous voulez faire avec eux sont à droite . C'est un peu compliqué. Mais la vérité est qu’il est assez amusant d’écrire du code que seuls d’autres programmeurs fonctionnels peuvent lire. De plus, c'est plutôt cool de prendre une fonction et de la transformer en une ligne de code.
Reduce est une fonction qui transforme l'itération en une seule chose. En règle générale, vous utilisez la fonction de réduction pour effectuer des calculs sur une liste afin de la réduire à un nombre. Réduire ressemble à ceci :
Nous utilisons souvent des expressions lambda comme fonctions.
Le produit d'une liste est la multiplication de chaque nombre individuel. Pour ce faire, vous écririez du code comme ceci :
Mais en utilisant réduire, vous pouvez écrire comme ceci :
Obtenez la même fonctionnalité, le code est plus court, et en cas d'utilisation de programmation fonctionnelle, il est plus soigné. (Remarque : la fonction de réduction n'est plus une fonction intégrée dans Python3 et doit être importée depuis le module functools)
La fonction de filtre utilise une méthode itérable et filtre tout ce dont vous n'avez pas besoin dans l'itérable.
Habituellement, le filtre nécessite une fonction et une liste. Il applique une fonction à chaque élément de la liste et ne fait rien si la fonction renvoie True. Si False est renvoyé, l’élément est supprimé de la liste.
La syntaxe est la suivante :
Regardons un petit exemple Sans filtre nous écririons :
En utilisant le filtre, nous pouvons écrire comme ceci :
Python est un langage. qui se développe et se popularise constamment, est toujours mis à jour. Lors des études, il est recommandé de trouver des partenaires d'étude pour étudier et discuter ensemble pour de meilleurs résultats. Si vous souhaitez apprendre Python, vous êtes invités à rejoindre le groupe d'échange d'apprentissage Python (627012464) pour superviser et apprendre ensemble. Il contient des outils de développement, de nombreuses informations utiles et des informations techniques à partager !
Les fonctions d'ordre supérieur peuvent prendre des fonctions comme paramètres et renvoyer des fonctions. Un exemple très simple est le suivant :
Le deuxième exemple de retour d'une fonction :
J'ai dit au début que les langages de programmation fonctionnels purs n'ont pas de variables. Les fonctions d’ordre supérieur facilitent cela.
Toutes les fonctions de Python sont des citoyens de première classe. Un citoyen de premier ordre est défini comme ayant une ou plusieurs des caractéristiques suivantes :
Créé au moment de l'exécution
Asigné une variable ou un élément dans une structure de données
Passé comme argument à une fonction
Renvoyé comme résultat d'une fonction
Toutes les fonctions de Python peuvent être utilisées comme fonctions d'ordre supérieur.
L'application partielle (également connue sous le nom de fermeture) est un peu bizarre, mais très cool. Vous pouvez appeler une fonction sans fournir tous les paramètres requis. Voyons cela dans un exemple. Nous voulons créer une fonction qui prend 2 arguments, une base et un exposant, et renvoie la base élevée à la puissance comme ceci :
Maintenant, nous voulons une fonction carrée dédiée qui calcule en utilisant la fonction puissance Mettre au carré un nombre :
Cela fonctionne, mais que se passe-t-il si nous voulons une fonction cube ? Ou que diriez-vous de trouver la fonction de la quatrième puissance ? Pouvons-nous continuer à écrire à leur sujet ? Eh bien, vous pouvez. Mais les programmeurs sont paresseux. Si vous répétez la même chose encore et encore, c'est le signe qu'il existe un moyen plus rapide d'accélérer les choses qui vous empêchera de la répéter. Nous pouvons utiliser des fermetures ici. Regardons un exemple de la fonction carré utilisant des fermetures :
N'est-ce pas cool ! Nous pouvons appeler une fonction qui nécessite 2 paramètres avec 1 seul paramètre.
Nous pouvons également utiliser une boucle pour générer une fonction de puissance qui implémente les puissances du cube jusqu'à 1000.
Vous avez peut-être remarqué que beaucoup de choses que nous voulons faire en programmation fonctionnelle tournent autour de listes. À l'exception des fonctions de réduction et des fermetures, toutes les fonctions que vous voyez génèrent des listes. Guido (le père de Python) n'aimait pas les expressions fonctionnelles en Python car Python avait déjà sa propre façon de générer des listes.
Si vous écrivez "importer ceci" dans l'environnement interactif de Python, vous obtiendrez :
C'est le Zen de Python. C'est un poème sur ce que signifie être pythonique. La partie que nous voulons aborder est la suivante :
Il devrait y avoir une - et de préférence une seule - manière évidente de le faire (il faut essayer d'en trouver une, de préférence une seule solution évidente)
en Python, la carte et le filtre peuvent effectuer le travail. mêmes opérations que les compréhensions de listes (discutées ci-dessous). Cela enfreint l'une des règles du Zen de Python, donc ces parties de la programmation fonctionnelle ne sont pas considérées comme « pythoniques ».
Un autre sujet est Lambda. En Python, une fonction lambda est une fonction normale. Lambda est un sucre syntaxique. Ces deux affirmations sont équivalentes.
Une fonction normale peut faire tout ce qu'une fonction lambda peut faire, mais elle ne peut pas fonctionner dans l'autre sens. Les fonctions Lambda ne peuvent pas faire tout ce que les fonctions normales peuvent faire.
C'est un bref argument pour expliquer pourquoi la programmation fonctionnelle ne s'intègre pas bien dans l'écosystème Python global. Vous avez peut-être remarqué que j'ai mentionné plus tôt la compréhension des listes et nous en discuterons maintenant.
Plus tôt, j'ai mentionné que tout ce que vous pouvez faire avec une carte ou un filtre, vous pouvez utiliser des compréhensions de liste. La compréhension de liste est un moyen de générer des listes en Python. La syntaxe est la suivante :
Mettons au carré chaque nombre de la liste, par exemple :
Nous pouvons voir comment appliquer la fonction à chaque élément de la liste. Comment appliquer le filtre ? Regardez le code précédent :
Nous pouvons le convertir en une compréhension de liste, comme ceci :
Répertorie les instructions de support comme if. Vous n'avez plus besoin d'appliquer un million de fonctions à quelque chose pour obtenir ce que vous voulez. En fait, si vous souhaitez essayer de générer une sorte de liste, il semble plus simple et plus simple d'utiliser une compréhension de liste. Et si nous voulions mettre au carré chaque nombre inférieur à 0 dans la liste ? Avec lambda, map et filter vous écririez :
Cela semble très long et compliqué. Avec les compréhensions de listes, c'est juste :
Les compréhensions de listes ne fonctionnent qu'avec des listes. map et filter conviennent à tout objet itérable, alors à quoi ça sert ? Vous pouvez utiliser n'importe quelle déduction sur n'importe quel objet itérable que vous rencontrez.
Vous pouvez créer une dérivation pour n'importe quel objet itérable.
Tout objet itérable peut être généré par dérivation. À partir de Python 2.7, vous pouvez même générer des dictionnaires (hashmaps).
S'il est itérable, vous pouvez le générer. Regardons la dernière série d'exemples.
set est une liste d'éléments dans laquelle aucun élément n'est répété deux fois.
Les éléments de l'ensemble n'ont aucun ordre.
Vous remarquerez peut-être que set a les mêmes accolades que dict. Python est très intelligent. Selon que vous fournissez une valeur pour le dict, il saura si vous écrivez une déduction de dict ou une déduction définie.
Apprentissage recommandé : Tutoriel Python
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!