4 votes

Programmation fonctionnelle en python et conditionnels

J'essaie d'écrire une fonction python d'une manière fonctionnelle. Le problème est que je ne sais pas comment transformer un conditionnel if en un style fonctionnel. J'ai deux variables : A y C que je veux vérifier pour les conditions suivantes :

def function():
    if(A==0): return 0
    elif(C!=0): return 0
    elif(A > 4): return 0
    else: someOtherFunction()

J'ai regardé le court-circuitage lambda mais je n'ai pas réussi à le faire fonctionner.

Je vous remercie d'avance pour votre aide !

9voto

unutbu Points 222216

De la lien que vous avez posté :

La PF décourage ou interdit carrément les déclarations, et travaille plutôt avec l'évaluation d'expressions

Ainsi, au lieu de if -vous pouvez utiliser un expression conditionnelle :

def function():
    return (0 if ((A == 0) or (C != 0) or (A > 4)) else
            someOtherFunction())

ou, (particulièrement utile s'il y a beaucoup de différents ) :

def function():
    return (0 if A == 0 else
            0 if C != 0 else
            0 if A > 4 else
            someOtherFunction())

Au fait, l'article lié propose

(<cond1> and func1()) or (<cond2> and func2()) or (func3())

comme un équivalent en court-circuit à

if <cond1>:   func1()
elif <cond2>: func2()
else:         func3()

Le problème est qu'ils ne sont pas équivalents ! L'expression booléenne ne renvoie pas la bonne valeur lorsque <cond1> est Truish mais func1() est faussé (par exemple False o 0 o None ). (Ou de la même manière lorsque <cond2> est Truish mais func2 est faussaire).

(<cond1> and func1())

est écrit avec l'intention d'évaluer à func1() quand <cond1> est Truish, mais lorsque func1() est faussé, (<cond1> and func1()) évalue à False l'expression entière est donc ignorée et Python continue à évaluer (<cond2> and func2()) au lieu de court-circuiter.

Voici donc un peu d'histoire intéressante. En 2005, Raymond Hettinger a trouvé un bug similaire difficile à trouver dans type(z)==types.ComplexType and z.real or z quand z = (0+4j) parce que z.real est faussé. Motivée par le désir de nous épargner des bugs similaires, l'idée d'utiliser une syntaxe moins sujette aux erreurs (expressions conditionnelles) est né.

4voto

Óscar López Points 97105

Il n'y a rien de non-"style fonctionnel" dans votre code actuel ! qui a dit que les conditionnels sont no fonctionnel de toute façon ? Pratiquement tous les langages fonctionnels disposent d'un opérateur conditionnel d'une sorte ou d'une autre, par exemple la fonction cond forme spéciale en Lisp.

Je ne serais pas d'accord avec le code s'il utilisait l'opérateur d'affectation ou s'il modifiait l'état d'une manière ou d'une autre (par exemple, en ajoutant à une liste), mais en l'état, la fonction en question est déjà dans un "style fonctionnel" - il n'y a pas de changement d'état.

Vous vouliez peut-être dire quelque chose comme ça ?

return A != 0 and C == 0 and A <= 4 and someOtherFunction()

Ce qui précède donnera False si l'un ou l'autre A == 0 o C != 0 o A > 4 dans tous les autres cas, il renverra la valeur de l'appel à la fonction someOtherFunction() . Et d'ailleurs, False On peut supposer que l'évaluation est égale à 0 (par exemple, 42 + False == 42 ), de sorte que la sémantique dans le code de la question sera préservée du point de vue de l'appelant.

Remarquez que vous sortez les informations du lien de leur contexte. Il n'est absolument pas nécessaire d'utiliser un lambda pour cela, l'article ne fait qu'expliquer comment contourner une limitation inhérente à la technologie de l'UE. lambda en Python, c'est-à-dire que vous ne pouvez pas retourner des instructions à l'intérieur de (comme if-elif-else ) - seules les expressions sont autorisées, mais vous pouvez les simuler avec des opérateurs booléens. Dans le contexte d'un fonction par tous les moyens, utilisez les conditionnels.

2voto

Droogans Points 2098

Bien que Peter Norvig soit un homme vraiment génial, son site web est assez difficile à trouver.

Je me souviens avoir lu des articles sur Puis-je faire l'équivalent de (test ? result : alternative) en Python ? sur son site il y a quelque temps lors de recherches avant une conférence sur le Python fonctionnel.

Je ne vais pas vous faire pencher d'un côté ou de l'autre à la lumière de mes conclusions, mais vous devriez quand même aller lire la section sur les opérateurs conditionnels ternaires dans un style fonctionnel.

def if_(test, result, alternative=None):
    "If test is true, 'do' result, else alternative. 'Do' means call if callable."
    if test:
        if callable(result): result = result()
        return result
    else:
        if callable(alternative): alternative = alternative()
        return alternative

0voto

Ben Points 22160

Utilisez-le comme vous l'avez.

Python fait no disposent d'une syntaxe et de bibliothèques intégrées permettant de programmer facilement toutes les fonctions pour qu'elles renvoient directement une seule expression. Ce n'est pas la partie la plus importante du style fonctionnel de toute façon, la partie la plus importante est de s'assurer que vos fonctions maintiennent intégrité référentielle . En gros, cela signifie que lorsque vous leur fournissez les mêmes valeurs d'entrée, ils renvoient la même sortie.

Donc, quand j'essaie de programmer de manière fonctionnelle en Python, je fais no s'abstenir totalement d'utiliser les déclarations. J'utilise un bloc d'affectations de variables locales comme un équivalent de let ... in ... de Haskell. J'utilise une chaîne if/elif/else comme un équivalent d'une chaîne case de Haskell. Et souvent, il existe des types intégrés qui ne fournissent pas une interface adéquate pour créer de nouvelles versions "modifiées" d'eux plutôt que de les mettre à jour sur place, de sorte que vous devez mettre en œuvre de telles opérations avec une opération de copie explicite, puis en utilisant des mutations sur la nouvelle copie.

Python vous permet d'implémenter un style fonctionnel dessins et modèles directement. Vous pouvez facilement structurer votre programme comme un ensemble de fonctions qui transmettent explicitement l'état et n'ont pas d'effets secondaires. algorithmes de manière très similaire à ce que vous feriez dans un langage de programmation fonctionnel. Presque tous les langages de programmation prennent en charge la programmation fonctionnelle dans ce sens, si vous êtes prêt à supporter le texte passe-partout nécessaire pour simuler des fonctions de première classe. Depuis Python tiene des fonctions de première classe, vous n'avez même pas à vous soucier du texte passe-partout.

Mais Python ne va pas plus loin dans la prise en charge de la programmation fonctionnelle. Il ne prend pas vraiment en charge l'implémentation des fonctions en tant qu'expressions transparentes à référentiel unique. Mais cela n'a pas vraiment d'importance. Dans un langage qui n'impose pas ou ne suit pas la pureté, vous obtenez pratiquement tous les avantages de la programmation fonctionnelle en vous contentant de conception de votre programme comme un ensemble de fonctions transparentes sur le plan référentiel, et la façon dont vous mettez en œuvre ces fonctions n'a pas d'importance tant que l'objectif du programme n'est pas atteint. interface est maintenue transparente sur le plan référentiel.

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