79 votes

Opérateur d'affectation conditionnelle Python

Fait l'équivalent en Python de la fonction Ruby ||= ("définir la variable si la variable n'est pas définie") existe-t-il ?

Exemple en Ruby :

 variable_not_set ||= 'bla bla'
 variable_not_set == 'bla bla'

 variable_set = 'pi pi'
 variable_set ||= 'bla bla'
 variable_set == 'pi pi'

1 votes

Il ne l'active pas s'il n'est pas activé - il l'active si sa valeur actuelle est fausse ( false ou nil ). Il est vrai que cette distinction est plus importante dans les langages qui, par exemple, considèrent 0 et "" comme faux, mais il n'en reste pas moins que la distinction est plus importante dans les langages qui, par exemple, considèrent 0 et "" comme faux.

0 votes

Quel est le cas d'utilisation de cet opérateur ruby ?

1 votes

La façon de le faire serait d'utiliser un try except NameError comme indiqué par phihag, mais cela n'a pas tellement de sens en Python comme indiqué par tout le monde ici. En Ruby, c'est plus utile en raison de la façon dont les gens passent des blocs de code arbitraires à exécuter à l'intérieur d'une fonction. La fonction cible peut alors avoir besoin de définir une variable qui n'a pas été initialisée dans le bloc étranger qu'elle a exécuté. De tels cas n'existent pas en Python.

210voto

Keith Devens Points 456

Je suis surpris que personne n'ait proposé cette réponse. Elle n'est pas aussi "intégrée" que celle de Ruby ||= mais c'est à peu près équivalent et c'est toujours un one-liner :

foo = foo if 'foo' in locals() else 'default'

Bien sûr, locals() n'est qu'un dictionnaire, vous pouvez donc le faire :

foo = locals().get('foo', 'default')

3 votes

Pourquoi cette surprise ? Il se peut que les gens ne le sachent pas.

30voto

emish Points 739

J'utiliserais

x = 'default' if not x else x

Bien plus court que toutes les alternatives proposées ici, et allant droit au but. Il faut lire : "mettre x par défaut si x n'est pas mis sinon le garder comme x". Si vous avez besoin de None , 0 , False o "" pour être des valeurs valides, vous devrez modifier ce comportement, par exemple :

valid_vals = ("", 0, False) # We want None to be the only un-set value

x = 'default' if not x and x not in valid_vals else x

Ce genre de choses ne demande qu'à être transformé en une fonction que l'on peut utiliser partout facilement :

setval_if = lambda val: 'default' if not val and val not in valid_vals else val

à ce moment-là, vous pouvez l'utiliser comme :

>>> x = None # To set it to something not valid
>>> x = setval_if(x) # Using our special function is short and sweet now!
>>> print x # Let's check to make sure our None valued variable actually got set
'default'

Enfin, si la notation infixe de Ruby vous manque vraiment, vous pouvez surcharger ||=| (ou quelque chose de similaire) en suivant les conseils de ce gars : http://code.activestate.com/recipes/384122-infix-operators/

6 votes

Votre premier exemple ne fonctionne pas : >>> x = 'default' if not x else x Traceback (most recent call last) : Fichier "<stdin>", ligne 1, in <module> NameError : name 'x' is not defined

9 votes

Cette réponse est incorrecte et échouera si x n'existe pas. Puisque la question demande un moyen de tester l'existence, cette solution ne fonctionnera pas.

2 votes

Cette réponse résout le problème de l'"affectation conditionnelle" : définir une variable si elle n'a pas été définie. Bien sûr, tout ce qui se trouve à droite doit être défini, sinon vous obtiendrez une erreur (je l'ai pris comme un pseudo-code). x = "value1" if True else "value2" . en général. x = 'value1' if condition else 'value2'

16voto

phihag Points 89765

Non, c'est le remplaçant qui l'est :

try:
   v
except NameError:
   v = 'bla bla'

Cependant, le fait de vouloir utiliser cette construction est le signe d'un flux de code trop compliqué. Normalement, vous devriez faire ce qui suit :

try:
   v = complicated()
except ComplicatedError: # complicated failed
   v = 'fallback value'

et ne jamais être incertain si v est activé ou non. S'il s'agit d'une des nombreuses options qui peuvent être activées ou non, utilisez un dictionnaire et ses get qui autorise une valeur par défaut.

2 votes

0 votes

@delnan Je n'ai pas voulu faire d'hypothèses spécifiques sur la nature des complicated() . L'a ajouté.

0 votes

Vous êtes sûr ? @emish propose une solution beaucoup plus simple.

8voto

mainas Points 104

L'affectation conditionnelle existe dans Python 2.5 et les versions ultérieures - la syntaxe n'est pas très évidente et il est donc facile de la manquer. Voici comment procéder :

x = true_value if condition else false_value

Pour plus d'informations, consultez le site Documentation sur Python 2.5 .

0 votes

Ce n'est pas ce qui est demandé.

5voto

Jas Points 177

(je ne peux pas faire de commentaires, sinon je le ferais) Je pense que la suggestion de vérifier les locaux ci-dessus n'est pas tout à fait correcte. Elle devrait être la suivante :

foo = foo if 'foo' in locals() or 'foo' in globals() else 'default'

pour être correcte dans tous les contextes.

Cependant, malgré les votes positifs, je ne pense pas que cela soit une bonne analogie avec l'opérateur Ruby. En effet, l'opérateur Ruby permet plus qu'un simple nom à gauche :

foo[12] ||= something
foo.bar ||= something

La méthode des exceptions est probablement l'analogue le plus proche.

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