37 votes

Utilisez-vous Python principalement pour ses caractéristiques fonctionnelles ou orientées objet ?

Je vois ce qui semble être une majorité de développeurs Python sur StackOverflow approuver l'utilisation d'outils fonctionnels concis comme les lambdas, les maps, les filtres, etc., tandis que d'autres disent que leur code est plus clair et plus facile à maintenir s'ils ne les utilisent pas. Quelle est votre préférence ?

De même, si vous êtes un programmeur fonctionnel pur et dur ou un adepte de l'OO, quelles autres pratiques de programmation spécifiques utilisez-vous qui, selon vous, sont les meilleures pour votre style ?

Merci d'avance pour vos avis !

67voto

Mike Graham Points 22480

J'utilise principalement Python en utilisant les styles orienté objet et procédural. En fait, Python n'est pas particulièrement bien adapté à la programmation fonctionnelle.

Beaucoup de gens pensent qu'ils écrivent du code Python fonctionnel en utilisant beaucoup de lambda , map , filter y reduce mais c'est un peu trop simplifié. La caractéristique principale de la programmation fonctionnelle est l'absence d'état ou d'effets secondaires. Les éléments importants d'un style fonctionnel sont les fonctions pures, les algorithmes récursifs et les fonctions de première classe.

Voici mes réflexions sur la programmation fonctionnelle et Python :

  • Les fonctions pures sont excellentes. Je fais de mon mieux pour que mes fonctions au niveau du module soient pures.

    • Les fonctions pures peuvent être testées. Comme elles ne dépendent pas d'un état extérieur, elles sont beaucoup plus faciles à tester.
    • Les fonctions pures sont capables de supporter d'autres optimisations, telles que la mémorisation et la parallélisation triviale.
  • La programmation par classe peut être pure. Si vous voulez un équivalent aux fonctions pures en utilisant les classes Python (ce qui est parfois mais pas toujours ce que vous voulez),

    • Rendez vos instances immuables. En particulier, cela signifie principalement que vos méthodes doivent toujours renvoyer de nouvelles instances de votre classe plutôt que de modifier l'instance actuelle.
    • Utilisez l'injection de dépendances plutôt que de récupérer des éléments (comme le module importé) dans la portée globale.
    • Ce n'est peut-être pas toujours ce que vous voulez.
  • N'essayez pas d'éviter l'État en bloc. Ce n'est pas une stratégie raisonnable en Python. Par exemple, utilisez some_list.append(foo) plutôt que new_list = some_list + [foo] le premier étant plus idiomatique et plus efficace. (En effet, une tonne de solutions "fonctionnelles" que je vois les gens utiliser en Python sont sous-optimales d'un point de vue algorithmique par rapport à des solutions tout aussi simples ou plus simples qui ne sont pas fonctionnelles ou qui sont tout aussi fonctionnelles mais n'utilisent pas les outils d'apparence fonctionnelle).

  • Tirer les meilleurs enseignements de la programmation fonctionnelle, par exemple un état mutable est dangereux. Demandez-vous, Est-ce que je veux vraiment changer ce X ou est-ce que je veux un nouveau X ?

    • Le traitement d'une liste est l'une des situations les plus courantes. J'utiliserais

      foo = [bar(item.baz()) for item in foo]

      plutôt que

      for index, _ in enumerate(foo):
          foo[index] = bar(foo[index].baz())

      et des trucs comme ça. Cela évite les bugs déroutants où le même objet liste est stocké ailleurs et ne doit pas être modifié. (Si cela devrait être modifié, il y a de fortes chances que vous ayez une erreur de conception. Faire muter une liste que vous avez référencée à plusieurs endroits n'est pas un bon moyen de partager l'état).

  • N'utilisez pas map et ses amis gratuitement. Il n'y a rien de plus fonctionnel que de faire cela.

    • map / filter son no plus fonctionnelle que les compréhensions de listes. Les compréhensions de listes ont été empruntées à Haskell, un langage fonctionnel pur. map et surtout filter peut être plus difficile à comprendre qu'une liste de compréhension. Je n'utiliserais jamais map ou filter avec un lambda mais je pourrais le faire si j'avais une fonction qui existait déjà ; j'utilise map un peu décent.
    • Il en va de même pour itertools.imap / ifilter par rapport aux expressions du générateur. (Ces choses sont quelque peu paresseuses, ce qui est une excellente chose que nous pouvons emprunter au monde fonctionnel).
    • N'utilisez pas map y filter pour les effets secondaires. Je vois cela avec map qui produit du code difficile à comprendre, des listes inutiles, et qui n'est décidément pas fonctionnel (bien que les gens pensent qu'il doit l'être à cause de l'option map .) Utilisez simplement une boucle for.
    • reduce est source de confusion, sauf dans des cas très simples. Python dispose de boucles for et il n'y a aucun mal à les utiliser.
  • N'utilisez pas d'algorithmes récursifs. Il s'agit d'une partie de la programmation fonctionnelle que Python ne supporte pas bien. CPython (et je pense tous les autres Python) ne supporte pas l'optimisation des appels de queue. Utilisez plutôt l'itération.

  • N'utilisez que lambda lorsque vous définissez des fonctions à la volée. Les fonctions anonymes ne sont pas meilleures que les fonctions nommées, ces dernières étant souvent plus robustes, plus faciles à maintenir et mieux documentées.

25voto

J'utilise les fonctionnalités du langage qui permettent de faire le travail avec le code le plus court et le plus propre possible. Si cela signifie que je dois mélanger les deux, ce que je fais assez souvent, alors c'est ce qui est fait.

10voto

Jochen Ritzel Points 42916

Je suis à la fois un fervent programmeur de la POO et un programmeur fonctionnel et ces styles fonctionnent très bien ensemble, principalement parce qu'ils sont complètement orthogonaux. Il existe de nombreux langages fonctionnels orientés objet, et Python en fait partie.

Ainsi, la décomposition d'une application en classes est très utile lors de la conception d'un système. Lorsque vous effectuez la mise en œuvre réelle, la FP aide à écrire un code correct.

Je trouve également très offensant que vous laissiez entendre que la programmation fonctionnelle signifie simplement "utiliser des plis partout". C'est probablement la plus grande et la pire des idées fausses sur la PF. Beaucoup de choses ont été écrites sur ce sujet, donc je dirai simplement que la grande chose à propos de la PF est l'idée de combiner des fonctions simples (,correctes et réutilisables) dans de nouvelles fonctions de plus en plus complexes. De cette façon, il est assez difficile d'écrire un code "presque correct" - soit l'ensemble fait exactement ce que vous voulez, soit il se casse complètement.

La PF en Python tourne principalement autour de l'écriture de générateurs et de leurs parents (compréhensions de listes) et des choses dans la section itertools module. Les appels explicites à map/filter/reduce sont tout simplement inutiles.

6voto

sth Points 91594

Python n'offre que des fonctionnalités marginales de programmation fonctionnelle. Je serais donc surpris que beaucoup de gens l'utilisent spécialement pour cela. Par exemple, il n'y a pas de moyen standard de faire de la composition de fonctions et la fonction reduce() a été déprécié en faveur des boucles explicites.

Aussi, je ne pense pas que map() ou filter() sont généralement approuvées. A l'inverse, les compréhensions de listes semblent être préférées.

5voto

tstenner Points 3881

La plupart des réponses sur StackOverflow sont des réponses courtes et concises, et les aspects fonctionnels de python facilitent l'écriture de ce type de réponses.

Les fonctionnalités OO de Python ne sont tout simplement pas nécessaires dans les réponses de 10 à 20 lignes, c'est pourquoi on ne les voit pas souvent ici.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X