Journal L/D·es différents paradigmes de programmation en Python

Posté par  (Mastodon) . Licence CC By‑SA.
Étiquettes :
37
7
nov.
2019

Sommaire

Utilisateur de Python tendance Data Sciences pas doué ni réellement formé en programmation, j’ai toujours eu une sorte de complexe par rapport au fait que ce que j’écris en Python sont juste des scripts basiques qui n’utilisent pratiquement pas le caractère orienté objet de Python. Caractère qui me semblait être une des composantes fondamentales de l’identité de Python. Il semblerait qu’il n’est en fait pas non pythonic d’écrire selon d’autre paradigme de programmation que celui orienté objet. C’est même une des nombreuses qualités attribuées à Python. C’est ce que j’ai découvert en lisant l’article Perceiving Python programming paradigms de Jigyasa Grover.

Pour les actuellement 34 personnes ayant répondu lors d’un sondage de la plus haute scientificité : Je ne parle pas anglais ; ça veut dire quoi « if » dans ce code source Python ?!, voici en français de très très larges extraits traduits.

C’est parti :

Au début de chaque année, TIOBE annonce son Langage de programmation de l'année. Titre basé sur le nombre de recherches effectués sur des moteurs de recherche (notamment sur Google, Bing, Yahoo, Wikipedia, Amazon, YouTube, et Baidu) en 2018. Lorsque son dernier rapport annuel sur l'indice TIOBE est sorti, je n'ai pas été du tout surpris de voir Python remporter à nouveau ce titre. Allant dans le même sens que les conclusions de TIOBE, près de 90 000 développeurs ont participé à l'enquête annuelle de Stack Overflow sur les développeurs. Cette enquête est la plus vaste et la plus complète sur les personnes qui codent dans le monde entier. La principale conclusion à retenir des résultats de cette année était :

"Python, le langage de programmation à la croissance la plus rapide, a une fois de plus grimpé dans le classement des langages de programmation dans notre enquête, devançant Java cette année et se classant au deuxième rang des langages les plus populaires (derrière Rust). "

Depuis que j'ai commencé à programmer et à explorer différents langages de programmation, j'ai vu l'admiration pour Python monter en flèche. Depuis 2003, il a toujours été parmi les 10 langages de programmation les plus populaires. Comme l'indique le rapport de TIOBE :

"C'est le premier langage de programmation le plus enseigné dans les universités de nos jours, il est numéro un dans le domaine statistique, numéro un pour l'IA, numéro un dans le scripting et numéro un dans l’écriture de tests système. En outre, Python est également leader dans la programmation web et le calcul scientifique (pour ne citer que quelques autres domaines). En résumé, Python est partout."

Il y a plusieurs raisons à l'ascension rapide de Python, sa floraison et sa domination dans de multiples domaines, y compris le développement Web, le calcul scientifique, les tests, la science des données, l'apprentissage machine, et ceterae. Les raisons en sont notamment sa lisibilité et sa maintenabilité, la structure modulaire, dynamique et portable, la programmation flexible, son apprentissage facile et les supports d'apprentissage, les structures de données conviviales, la productivité et la vitesse qu’il permet, et, plus important encore, le support communautaire. La diversité des applications de Python est le résultat de ses caractéristiques combinées, qui lui donnent un avantage sur les autres langages.

Mais à mon avis, la simplicité relative de sa syntaxe et la flexibilité stupéfiante qu'elle offre aux développeurs venant d’autres langages l'emporte. Très peu de langages peuvent égaler la capacité de Python à se conformer au style de codage d'un développeur plutôt que de le forcer à coder d'une manière particulière. Python permet aux développeurs seniors d'utiliser le style qui leur semble le mieux adapté pour résoudre un problème particulier.

En travaillant avec Python, vous êtes comme un charmeur de serpent. Vous pouvez profiter de la promesse de Python d'offrir aux développeurs un environnement non contraignant pour coder dans le style le mieux adapté à une situation particulière et de rendre le code plus lisible, testable et cohérent.

Les paradigmes de programmation de Python

Python supporte quatre grands paradigmes de programmation : impératif, fonctionnel, procédural et orienté objet. Que vous soyez d'accord ou pas pour dire qu'ils sont valables ou même utiles, Python s'efforce de rendre les quatre disponibles et opérationnels. Avant de nous plonger dans la détermination de quel paradigme de programmation est le plus approprié pour des cas d'utilisation spécifiques, c'est un bon moment pour les passer en revue rapidement.

La programmation impérative

La programmation impérative utilise le caractère impératif du langage naturel pour exprimer les instructions. Il exécute les commandes étape par étape, comme une série de commandes verbales. Suivant l'approche "comment résoudre", il apporte des changements directs à l'état du programme ; c'est pourquoi il est aussi appelé modèle de programmation dynamique. En utilisant la programmation impérative, vous pouvez rapidement écrire du code très simple mais élégant, et c'est super pratique pour les tâches qui impliquent une manipulation de données. En raison de sa stratégie d'exécution relativement plus lente et séquentielle, il ne peut pas être utilisé pour des calculs complexes ou parallèles.

La programmation fonctionnelle

La programmation fonctionnelle considère un programme de calcul comme l'évaluation de fonctions mathématiques basées sur le calcul lambda. Le calcul lambda est un système formel en logique mathématique pour exprimer le calcul basé sur l'abstraction de fonction et l'application utilisant la liaison et la substitution de variables. Il suit l'approche de la "solution à apporter", c'est-à-dire qu'il exprime la logique sans décrire son flux de contrôle, d'où il est aussi classé dans le paradigme de programmation déclarative.

La programmation procédurale

La programmation procédurale est un cas particulier de programmation impérative dans lequel les énoncés sont structurés en procédures (aussi appelées sous-programmes ou fonctions). La composition du programme est plutôt un appel de procédure où les programmes peuvent résider n’importe où dans l'univers alors que l'exécution est séquentielle, devenant ainsi un goulot d'étranglement pour l'utilisation des ressources. Le paradigme de programmation procédurale facilite la pratique d'une bonne conception de programme et permet de réutiliser les modules sous la forme de bibliothèques de code.

Cette forme de développement modulaire est un style de développement très ancien. Les différents modules d'un programme peuvent n’avoir aucune relation les uns avec les autres et peuvent être situés à des endroits différents. Mais la multiplicité de modules crée des difficultés pour de nombreux développeurs, car cela conduit non seulement à la duplication de la logique mais aussi à beaucoup de frais généraux en termes de trouver et de faire les bons appels.

La programmation orientée objet

La programmation orientée objet considère des entités de base comme des objets dont l'instance peut contenir à la fois des données et les méthodes correspondantes pour modifier ces données. Les différents principes de la conception orientée objet aident à la réutilisation du code, au masquage des données, etc., mais c'est une bête complexe, et il n’est pas facile d’écrire dans ce paradigme.

Quel type de programmation choisir ?

Il est important de noter qu'il n'y a aucune comparaison entre les différents types de programmation. Puisque le logiciel n'est rien d'autre que la représentation d’un savoir, la réponse à la question : "Quelle est la meilleure façon de représenter mon problème ?" est de choisir un paradigme de programmation spécifique.

En termes simples, si votre problème implique une série de manipulations séquentielles simples, adopter une programmation impérative de la vieille école serait le moins coûteux en termes de temps et d'effort et vous donnerait les meilleurs résultats. Dans le cas de problèmes nécessitant des transformations mathématiques des valeurs, du filtrage de l'information ou de la cartographie, la programmation fonctionnelle peut s'avérer utile. Si le problème est structuré comme un ensemble d'objets interdépendants avec certains attributs qui peuvent changer avec le temps, en fonction de certaines conditions, la programmation orientée objet sera super utile. Bien entendu, une approche fondée sur des règles ne fonctionne pas ici, car le choix du paradigme de programmation dépend aussi fortement du type de données à traiter, des besoins dynamiques du système et de divers autres facteurs comme l'évolutivité.

Tendances récentes

L'analyse des derniers mots à la mode dans le monde IT peut aider à déterminer pourquoi certains paradigmes de programmation fonctionnent mieux que d'autres.

L'apprentissage machine utilise un mélange sain de programmation impérative et de programmation fonctionnelle avec un soupçon d'immuabilité. L'extraction et le prétraitement des caractéristiques sont mieux abordées sur de manière fonctionnelle, car elles nécessitent un traitement mathématique des données et parce que les mappages, les réductions et les filtrations peuvent être effectuées en parallèle sans trop dépendre les unes des autres. L'estimation des modèles d'apprentissage machine est mieux abordée par la programmation impérative à l'ancienne, car l'optimisation de la valeur des fonctions (a.k.a. l'état du programme) doit être mise à jour à chaque itération et nécessite donc une exécution séquentielle à plusieurs endroits de l'algorithme. Dans ce cas, la programmation impérative est plus rapide que la programmation fonctionnelle. Cela évite également de créer des copies de tout après chaque étape ; au lieu de cela, elle se contente de mettre à jour les caractères de remplissage des valeurs précédentes.

L'apprentissage en profondeur peut être bien exécuté d'une manière fonctionnelle, car les modèles d'apprentissage en profondeur sont des modèles composés. L'ensemble du processus optimise un ensemble de fonctions composées, les poids sont immuables et sans état, et les mises à jour peuvent être appliquées dans n'importe quel ordre tant que les entrées correspondantes sont calculées. L'utilisation de la programmation fonctionnelle permet la simultanéité et le parallélisme sans frais et facilite également le travail avec de grands modèles distribués. Il existe également certains paradigmes personnalisés où la programmation fonctionnelle est entrelacée avec la théorie de l'information pour éviter le surajustement dans les modèles statistiques.

La manipulation des données peut être abordée aussi bien avec une programmation fonctionnelle qu’avec une programmation orientée objet. Dans la programmation fonctionnelle, tout est immuable, les algorithmes sont exprimés de manière succincte, et il y a une correspondance native des motifs, mais la formulation de la commande de type expression mathématique est un art. L'approche de la programmation orientée objet permet d'obtenir des boucles récursives et itératives et une structure basée sur les classes qui facilite la mise à l'échelle de données plus volumineuses et de nouvelles fonctions. L'inconvénient est que les algorithmes et la logique du code ne sont pas exprimés d'une manière lisible. Bien que les deux paradigmes ont en général un garbage collector automatique et peuvent accéder aux bases de données et les manipuler facilement, le choix de l'un ou l'autre dépend fortement des connaissances du programmeur.

Plats à emporter

Il y a une forte probabilité que deux développeurs soient en désaccord sur le meilleur style de codage pour n'importe quelle situation et aient des arguments valables à l'appui de leur opinion. La chose étonnante à propos de Python est qu'il vous permet de choisir le paradigme de programmation qui fonctionne le mieux pour vous dans une situation donnée.

Une tâche peut toujours être divisée en sous-tâches où chaque petite partie est codée dans un paradigme complètement différent. Le style mix-and-match fonctionne parfaitement tant que les packages utilisés sont minimes, que les entrées et sorties sont clairement définies et que la complexité est modérée. Il n'y a aucune règle qui dit que vous ne pouvez pas combiner les styles selon vos besoins. Python ne s'arrête pas au milieu de l'interprétation de votre application et affiche une erreur de style lorsque vous mélangez les styles.

Parce qu'il n'existe pas de guide parfait pour choisir un style de codage correct pour un cas d'utilisation donné, la meilleure suggestion est d'essayer plusieurs paradigmes en pesant le pour et le contre jusqu'à ce que vous trouviez celui qui mène à une solution simple mais efficace. Il y aura des moments au cours de cette expérimentation où vous verrez qu'au lieu d'utiliser un style unique, une combinaison de paradigmes de programmation fonctionne mieux. Au cours de ce processus, il est également fortement recommandé de documenter les exigences et les essais des différents styles pour les partager avec la communauté et obtenir des commentaires. Les commentaires et les suggestions aideront au développement ainsi que vos coéquipiers et tous les futurs développeurs qui rejoindront l'équipe.

  • # Dépêche ?

    Posté par  . Évalué à 5.

    J'ai été obligé de vérifier que j'étais bien en train de lire un journal et pas une dépêche. Bravo, c'est vraiment très bien écrit et très intéressant.

    • [^] # Re: Dépêche ?

      Posté par  (Mastodon) . Évalué à 2.

      Sans vouloir minimiser les mérites du rédacteur de ce journal, ce n'est qu'une traduction imparfaite et incomplète :-)
      Sinon, je suis très content de voir que je ne suis pas le seul à trouver ce texte intéressant.

      Surtout, ne pas tout prendre au sérieux !

      • [^] # Re: Dépêche ?

        Posté par  (site web personnel, Mastodon) . Évalué à 4.

        Je l'ai trouvé très intéressant et agréable à lire aussi. Un grand merci.

        « Tak ne veut pas quʼon pense à lui, il veut quʼon pense », Terry Pratchett, Déraillé.

      • [^] # Re: Dépêche ?

        Posté par  . Évalué à 3.

        Ah, purée, j'avais pas vu que c'était une traduction. Eh bien c'est très bien traduit dans ce cas.

        • [^] # Re: Dépêche ?

          Posté par  . Évalué à 1. Dernière modification le 08 novembre 2019 à 16:55.

          merci pour la traduction, mais il y a un truc que je n'ai pas compris, tu dis :

          le caractère orienté objet de Python […] me semblait être une des composantes fondamentales de l’identité de Python. Il semblerait qu’il n’est en fait pas non pythonic d’écrire selon d’autre paradigme de programmation que celui orienté objet

          et tu dis que tu as découvert cela en lisant un article qui dit (me semble-t-il) le contraire :

          Python supporte quatre grands paradigmes de programmation : impératif, fonctionnel, procédural et orienté objet.

          cet article ne semble aucunement soutenir qu'il faut absolument faire de l'orienté objet avec python, c'est même le contraire, on a le choix.

          du coup je me dis que j'ai dû mal comprendre ton propos

          edit: zut j'ai pas répondu au bon endroit, mais c'est bien sûr à tisaac que je m'adressais

          • [^] # Re: Dépêche ?

            Posté par  . Évalué à 6.

            Il y a une double négation que tu as dû louper : "Il semblerait qu’il n’est en fait pas non pythonic d'écrire selon d'autre[s] paradigmes"

            Autrement dit, c'est pythonique d'écrire dans d'autres paradigmes.

            :-)

            • [^] # Re: Dépêche ?

              Posté par  . Évalué à 1.

              Merci, effectivement, j'ai lu trop vite, désolé

  • # Modération : erreur de formatage du texte

    Posté par  (Mastodon) . Évalué à 7.

    J'ai fait une petite faute en termes de formatage.

    Quel type de programmation choisir ?
    devrait être un intertitre (niveau H2, je crois).

    Si une modératrice, un modérateur ou tout autre h·être, chêne, bouleau,… assurant la modération pouvait corriger mon oubli, je lui en serais très reconnaissant.

    Surtout, ne pas tout prendre au sérieux !

  • # Pandas/Dask et programmation fonctionnelle

    Posté par  . Évalué à 4.

    Bon article qui m'a fait pensé que lorsque je suis passé de Pandas à Dask pour pouvoir gérer de plus grands datasets, je me suis heurter à un petit problème de conception. Lorsque j'ai écrit mon code pour Pandas, je l'avais fait sous forme impérative/procédurale en gardant un paquet de variables temporaires. Le problème en passant à Dask est que le calcul ne se fait qu'à la fin sur le .compute(). Et ça ma causé pas mal de soucis car j'avais besoin de faire des .compute() un peu partout dans mon code, ce qui enlève tout l’intérêt de Dask.

    C'est pour ça que lorsqu'on utilise des packages comme Dask, il faut écrire en procédural mais penser en fonctionnel et ça, ça demande une gymnastique mentale a laquelle je n'étais pas habitué.

    As tu eu des cas comme ça dans ton expérience de programmation python ?

    Sinon, dernière petite question: 'Apprentissage en profondeur', je ne connaissais pas cette traduction. C'est effectivement répertorié dans les quelques glossaires que je connais (DataFranca , Termium). Est ce que c'est beaucoup utilisé comme terme ?

    • [^] # Re: Pandas/Dask et programmation fonctionnelle

      Posté par  (Mastodon) . Évalué à 2.

      Concernant la traduction de deep learning, je ne sais pas si c'est très utilisé. Professionnellement, je n'ai pas l'habitude de traduire ce genre de termes et de les laisser en anglais (machine learning, deep learning,…). Ici, je trouvais amusant de faire une traduction plutôt littérale du texte voire même parfois absurde (ma traduction de Takeaway en Plats à emporter est très discutable mais me faisait bien rire). Cela sonne donc parfois particulier et cela m'amuse mais d'un point de vue plus sérieux, c'est aussi une occasion de réfléchir à ce que dise en fait ces termes.

      Je crois qu'on n'a pas encore rencontré le problème que tu soulèves mais je crains que si cela nous arrivait, vu que mon collègue et moi sommes un peu barbares, on mettrait des .compute() partout en se disant que finalement cela ne sert pas à grand chose Dask et que l'on mettrait du temps à tilter sur le fait que notre manière d'aborder les choses doit être un peu modifiée.

      Quand tu parles de plus grand datasets, tu peux donner une idée de la taille ? Histoire de nous donner une idée de quand il est intéressant de passer à Dask.

      Surtout, ne pas tout prendre au sérieux !

      • [^] # Re: Pandas/Dask et programmation fonctionnelle

        Posté par  . Évalué à 1.

        Je comprends pour la traduction :)

        En fait, l'intégration de Dask m'a fait me poser des questions sur l'optimisation du code avec Pandas. L'origine est qu'un collègue est venu me voir en disant que le datasets ne rentrait pas en mémoire avec pandas. J'avoue que je n'ai pas vérifié son code et mon premier réflexe a été de lui dire : "Utilise Dask'. À l'époque on avait qu'un petit serveur de calcul avec 16Go de RAM, et plusieurs utilisateurs en même temps à faire apprendre des modèles, pour un dataset d'environ 7-8Go. On a donc utilisé Dask et ça a marché un temps jusqu'à avoir le vrai serveur de calcul avec 64Go de RAM. A ce moment Dask est devenu inutile.

        Puis, je suis tombé sur ça : https://www.dataquest.io/blog/pandas-big-data/ Et là ma vision a changé. En fait, on aurait surement pas eu besoin de Dask mais d'un peu d'optimisation avec Pandas. Donc, mon expérience avec Dask est mitigée pour l'instant mais je pense que j'aurais l'occasion de tester plus tard avec des plus gros datasets.

        Donc pour répondre à ta question : ça dépend de la machine que tu utilises :)

        Julien

        • [^] # Re: Pandas/Dask et programmation fonctionnelle

          Posté par  (Mastodon) . Évalué à 1.

          Merci pour ton retour d'expérience et pour le lien. Je crois que Dask va attendre. En tout cas, en cas de problème, on verra d'abord s'il n'y a pas moyen d'optimiser notre utilisation des dataframes de Pandas.

          Surtout, ne pas tout prendre au sérieux !

  • # Lambda calcul

    Posté par  (site web personnel) . Évalué à 2.

    La programmation fonctionnelle considère un programme de calcul comme l'évaluation de fonctions mathématiques basées sur le calcul lambda. Le calcul lambda est un système formel en logique mathématique pour exprimer le calcul basé sur l'abstraction de fonction et l'application utilisant la liaison et la substitution de variables. Il suit l'approche de la "solution à apporter", c'est-à-dire qu'il exprime la logique sans décrire son flux de contrôle, d'où il est aussi classé dans le paradigme de programmation déclarative.

    J'ai pas souvenir d'avoir entendu "calcul lambda". Même la page Wikipedia liée dit "Lambda calcul".
    Aussi, je ne pense pas que ça utilise nécessairement la substitution de variables, si on utilise la notation de Bruijn, spécifiquement vu qu'on manipule tous les termes d'une classe d'alpha-equivalence via une représentation canonique.

    • [^] # Re: Lambda calcul

      Posté par  (Mastodon) . Évalué à 2.

      Tout à fait, j'aurais du écrire lambda-calcul.

      Il y a visiblement eu un bogue dans mon cerveau parce que je me suis posé la question, j'ai fais des recherches sur internet, j'ai consulté la page Wikipédia. J'ai du mal à comprendre pourquoi au final je l'ai mis dans le mauvais ordre.

      Je vais relire le code faisant fonctionner mon cerveau pour retrouver le bogue. En espérant que le code soit en Python et donc lisible :-)

      Surtout, ne pas tout prendre au sérieux !

  • # Pour ma part je ne suis pas d'accord avec certains des points mentionnés.

    Posté par  . Évalué à 5.

    Les raisons en sont notamment sa lisibilité et sa maintenabilité, la structure modulaire, dynamique et portable, la programmation flexible, son apprentissage facile et les supports d'apprentissage, les structures de données conviviales, la productivité et la vitesse qu’il permet, et, plus important encore, le support communautaire.

    Parler de code lisible en python, bof pourquoi pas, mais concernant la maintenabilité, je ne suis absolument pas d'accord. A mon avis la seule raison pour laquelle python est si utilisé est qu'il est très facile de coder un truc qui marchote sans avoir une très grande connaissance du langage (en plus de tous les modules dispo qui machent beaucoup le travail). C'est effectivement le point fort de python.

    Très peu de langages peuvent égaler la capacité de Python à se conformer au style de codage d'un développeur plutôt que de le forcer à coder d'une manière particulière.

    Ca par contre je trouve que c'est un mensonge digne d'un commercial :). Ce que je reproche à Python, c'est justement une certaine rigidité qui t'oblige à faire "de la bonne façon" (pythonic comme tu dis plus haut). Bien souvent, quand je développe en Python, je suis obligé de faire des trucs plus ou moins tordus que je fais de façon plus simple et concise en ruby. L'absece de switch/case par exemple est problématique de mon point de vue: un enchainement de if/else if, emn plus d'être rébarbatif, n'est pas très élégant et ne répond pas au même besoin: et si on veut simuler un switch/case, il faut contourner et on se retrouve avec un probramme qui n'est plus orcément très lisible ( je n'utilise pas souvent cette structure, mais il y a des cas, notamment quand on parse des données, ou c'est bien plus lisible et plus pratique que le reste. Un switch/case ne permettant de n'appeler qu'une fonction/méthode me suffirait …

    Vous pouvez profiter de la promesse de Python d'offrir aux développeurs un environnement non contraignant pour coder dans le style le mieux adapté à une situation particulière et de rendre le code plus lisible, testable et cohérent.

    Je trouve au contraire que Le changement de paradigme au fil de l'eau (surtout dans une fonction/méthode de plusieurs dieaines de lignes (comme c'est courants chez beaucoup de "développeurs" python ) nuit à la lisibilité du code. Pour ma part je m'efforce de faire des fonctions courtes, et i je dois faire appel par exemple à un paradigme fonctionnel dans du code plutôt objet, j'essai de faire une abstraction et de l'encapsuler dans une méthode qui décrit clairement ce que je fais (les list comprehension sont un peu difficile à déchiffrer, même quand on en a l'habitude).

    Il n'y a aucune règle qui dit que vous ne pouvez pas combiner les styles selon vos besoins

    La lisibilité ? Rappel: on ne code pas pour la machine, mais on code pour que les autres puissent relire …

  • # Complexe l'objet ?

    Posté par  (site web personnel) . Évalué à 4.

    mais c'est une bête complexe, et il n’est pas facile d’écrire dans ce paradigme.

    C'est une autre manière de voir les choses et c'est parfois moins complexe.

    Quelle est la différence entre un objet et une variable ?

    presque rien … en Perl une variable devient un objet si le concepteur la bénie …
    ex : bless $var;

    En poo tu crées des objets qui interagissent entre eux, ensuite tu lance la machine … c'est tout

    Ah et dernier point sur la programmation : n'oubliez jamais ces 2 mots :

    Fréquence et volume

    A quelle fréquence mon programme doit il s'éxécuter : 1 fois , 1 fois / mois, 1 fois / seconde
    Et quelle est le volume de données à traiter ?

    Si vous vous posez ces 2 questions AVANT de parler d'algorithme cela peut vous aider …

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.