4
votes

Puis-je supprimer la double évaluation tout en conservant l'expression lambda

foo = lambda(x): v if (v = bar(x)) > 10 else 0

1 commentaires

Vous pouvez stocker foo (x) dans une variable tmp et l'utiliser dans votre code.


5 Réponses :


4
votes

Preevaluate:

lambda x: next(res if res > 10 else 0 for res in (bar(x), ))

Ici, vous pouvez voir quelles sont les similitudes avec votre code:

lambda (x): foo(x) if foo(x) > 10 else 0 == (lambda(x): x if x > 10 else 0)(foo(x))

Ce que vous cherchez n'est pas possible à moins vous créez une sorte d'objet d'état mutable ou une autre astuce étrange.

La réponse @Alakazam est délicate et intelligente, utilisez-la à vos risques et périls. Il peut être préférable d'utiliser les itérateurs et next pour éviter une liste intermédiaire supplémentaire:

foo    = lambda(x): x if x > 10 else 0
result = foo(bar(x))

Ici vous avez le exemple en direct


0 commentaires

0
votes

Vous ne voudrez peut-être faire cela que si votre fonction est très longue à exécuter, sinon cela ne vous dérangera pas de l'exécuter deux fois. Vous ne pouvez pas utiliser la compréhension de liste .

foo = lambda x: [res if res> 10 else 0 for res in [bar (x)]] [0]


2 commentaires

c'est mieux je pense: lambda x: next (res if res> 10 else 0 for res in (bar (x),)) , La raison en est que vous évitez l'allocation de mémoire intermédiaire


@Netwave Je ne pense pas que le malloc intermédiaire soit pertinent, même si cela dépend de la fonction, vous n'économisez pas beaucoup de mémoire.



3
votes

Oui, vous pouvez éviter une double évaluation dans un lambda. Mais c'est vraiment moche et vous devriez l'éviter. Voici à quoi cela ressemble:

def foo(x):
    b = bar(x)
    return b if b > 10 else 0

Est-ce facile à lire et à comprendre? Non, absolument pas. Je ne vais pas l'expliquer; voyez si vous pouvez le comprendre. Ce n'est clairement pas une bonne solution, alors que devriez-vous faire à la place? Vous devriez utiliser une fonction réelle au lieu d'un lambda.

foo = lambda x: next(b if b > 10 else 0 for b in [bar(x)])

C'est beaucoup plus facile à lire et nettement meilleur.


0 commentaires

0
votes

Peut aussi bien définir une autre fonction:

def bar(x):
    # some expensive calculation
    <snip>

def bar_threshold(x,t):
    y = bar(x)
    return y if y>t else 0

foo = lambda x: bar_threshold(x,10)

(ou redéfinir la barre, si vous vous trouvez en train de l'utiliser uniquement avec le seuil)


0 commentaires

0
votes

J'ai essayé de créer une fonction décorateur / wrapper ...

foo(10)

puis

foo(2)

puis j'essaye ... .:

foo = lambda x: bar(x)

donne-moi le résultat:

@funcdec
def bar(x):
    return x * 2

retourne 0 et

def funcdec(func):
    def inner(x):
        if func(x) > 10:
           return func(x)
        else:
           return 0

renvoie 20


0 commentaires