web-dev-qa-db-fra.com

Compression de l'instruction `x if x else y` dans Python

Je connais très bien l'approche d'opérateur ternaire de Python:

value = foo if something else bar

Ma question est très simple: sans affectation préalable, existe-t-il de toute façon de référencer le terme évalué dans (if ...) de l'un des opérandes de retour (... if ou else ...)?

La motivation ici est que parfois j'utilise des expressions dans if ... c'est exactement ce que j'aimerais avoir comme résultat de l'opération ternaire; arrive cependant que, pour les petites expressions, il n'y a pas de problème à le répéter, mais pour les expressions un peu plus longues, cela devient quelque peu désagréable. Prenez ceci comme exemple:

value = info.findNext("b") if info.findNext("b") else "Oompa Loompa"
25
Rubens

Il n'y a aucun moyen de le faire, et c'est intentionnel. Le ternaire if n'est censé être utilisé que pour les cas triviaux.

Si vous souhaitez utiliser le résultat d'un calcul deux fois, mettez-le dans une variable temporaire:

value = info.findNext("b")
value = value if value else "Oompa Loompa"

Une fois que vous faites cela, il devient clair que vous faites quelque chose de stupide, et en fait, la façon Pythonique d'écrire ceci est:

value = info.findNext("b")
if not value:
    value = "Oompa Loompa"

Et c'est en fait 5 moins frappes que votre tentative initiale.

Si vous vraiment voulez enregistrer les frappes, vous pouvez à la place faire ceci:

value = info.findNext("b") or "Oompa Loompa"

Mais cela est découragé par de nombreux guides de style et par le BDFL.

Si vous ne faites cela qu'une seule fois, il vaut mieux être plus explicite. Si vous le faites une demi-douzaine de fois, il est trivial — et bien mieux — de faire en sorte que findNext prenne une valeur par défaut facultative au lieu de None, comme tous ceux intégrés et stdlib les fonctions:

def findNext(self, needle, defvalue=None):
    # same code as before, but instead of return None or falling off the end,
    # just return defvalue.

Ensuite, vous pouvez le faire:

value = info.findNext("b", "Oompa Loompa")
30
abarnert

N'utilisez pas if ... else du tout. Profitez plutôt des opérateurs de coalescence de Python.

value = info.findNext("b") or "Oompa Loompa"
21