web-dev-qa-db-fra.com

Opérateur d'affectation conditionnelle Python

Existe-t-il un équivalent Python de l'opérateur Ruby ||= ("définir la variable si la variable n'est pas définie")?

Exemple en rubis:

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

 variable_set = 'pi pi'
 variable_set ||= 'bla bla'
 variable_set == 'pi pi'
38
Hartator

Non, le remplacement est:

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

Cependant, vouloir utiliser cette construction est un signe de flux de code trop compliqué. Habituellement, vous feriez ce qui suit:

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

et ne jamais savoir si v est défini ou non. S'il s'agit d'une des nombreuses options pouvant être définies ou non, utilisez un dictionnaire et sa méthode get qui autorise une valeur par défaut.

16
phihag

Je suis surpris que personne ne propose cette réponse. Ce n'est pas aussi "intégré" que le ||= de Ruby mais c'est fondamentalement équivalent et reste un one-liner:

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

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

foo = locals().get('foo', 'default')
112
Keith Devens

J'utiliserais 

x = 'default' if not x else x

Beaucoup plus court que toutes vos alternatives suggérées ici, et droit au but. Lisez, "définissez x par défaut si x n'est pas défini, sinon conservez-le comme x." Si vous avez besoin que None, 0, False ou "" soient des valeurs valides, vous devrez toutefois 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 chose ne demande qu’à être transformé en une fonction que vous pouvez utiliser partout facilement: 

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

à quel point, 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, s'il vous manque vraiment la notation Ruby Infix, vous pouvez surcharger ||=| (ou quelque chose de similaire) en suivant le hack de ce type: http://code.activestate.com/recipes/384122-infix-operators/

11
emish

Non, ne pas savoir quelles variables sont définies est un bug, pas une fonctionnalité de Python. 

Utilisez des dict à la place:

d = {}
d.setdefault('key', 1)
d['key'] == 1

d['key'] = 2
d.setdefault('key', 1)
d['key'] == 2
4
Jochen Ritzel

(je ne peux pas faire de commentaire ou je voudrais simplement faire cela) Je pense que la suggestion de vérifier les sections locales ci-dessus n'est pas tout à fait correcte. CA devrait etre:

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

être correct dans tous les contextes. 

Cependant, malgré ses votes positifs, je ne pense même pas que ce soit un bon analogue à l'opérateur Ruby. Puisque l'opérateur Ruby permet plus qu'un simple nom à gauche:

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

La méthode d'exception est probablement l'analogue le plus proche.

2
Jas

Je le fais habituellement de la manière suivante:

def set_if_not_exists(obj,attr,value):
 if not hasattr(obj,attr): setattr(obj,attr,value)
1
Dog eat cat world

Je pense que ce que vous recherchez, si vous cherchez quelque chose dans un dictionnaire, est la méthode setdefault:

(Pdb) we=dict()
(Pdb) we.setdefault('e',14)
14
(Pdb) we['e']
14
(Pdb) we['r']="p"
(Pdb) we.setdefault('r','jeff')
'p'
(Pdb) we['r']
'p'
(Pdb) we[e]
*** NameError: name 'e' is not defined
(Pdb) we['e']
14
(Pdb) we['q2']

*** KeyError: 'q2' (Pdb)

La chose importante à noter dans mon exemple est que la méthode setdefault modifie le dictionnaire si et seulement si la clé à laquelle la méthode setdefault fait référence n'est pas présente.

0
user1928764

Il existe une affectation conditionnelle dans Python 2.5 et les versions ultérieures - la syntaxe n’est pas très évidente et est donc facile à manquer. Voici comment vous le faites:

x = true_value if condition else false_value

Pour plus de référence, consultez le Python 2.5 docs .

0
mainas