Python conditional assignment operator

Question:

Does a Python equivalent to the Ruby ||= operator (“set the variable if the variable is not set”) exist?

Example in Ruby :

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

 variable_set = 'pi pi'
 variable_set ||= 'bla bla'
 variable_set == 'pi pi'
Asked By: Hartator

||

Answers:

No, the replacement is:

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

However, wanting to use this construct is a sign of overly complicated code flow. Usually, you’d do the following:

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

and never be unsure whether v is set or not. If it’s one of many options that can either be set or not, use a dictionary and its get method which allows a default value.

Answered By: phihag

No, not knowing which variables are defined is a bug, not a feature in Python.

Use dicts instead:

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

d['key'] = 2
d.setdefault('key', 1)
d['key'] == 2
Answered By: Jochen Ritzel

I am not sure I understand the question properly here … Trying to “read” the value of an “undefined” variable name will trigger a NameError. (see here, that Python has “names”, not variables…).

== EDIT ==

As pointed out in the comments by delnan, the code below is not robust and will break in numerous situations …

Nevertheless, if your variable “exists”, but has some sort of dummy value, like None, the following would work :

>>> my_possibly_None_value = None
>>> myval = my_possibly_None_value or 5
>>> myval
5
>>> my_possibly_None_value = 12
>>> myval = my_possibly_None_value or 5
>>> myval
12
>>> 

(see this paragraph about Truth Values)

Answered By: tsimbalar

I usually do this the following way:

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

I’m surprised no one offered this answer. It’s not as “built-in” as Ruby’s ||= but it’s basically equivalent and still a one-liner:

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

Of course, locals() is just a dictionary, so you can do:

foo = locals().get('foo', 'default')
Answered By: Keith Devens

I would use

x = 'default' if not x else x

Much shorter than all of your alternatives suggested here, and straight to the point. Read, “set x to ‘default’ if x is not set otherwise keep it as x.” If you need None, 0, False, or "" to be valid values however, you will need to change this behavior, for instance:

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

This sort of thing is also just begging to be turned into a function you can use everywhere easily:

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

at which point, you can use it as:

>>> 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'

Finally, if you are really missing your Ruby infix notation, you could overload ||=| (or something similar) by following this guy’s hack: http://code.activestate.com/recipes/384122-infix-operators/

Answered By: emish

There is conditional assignment in Python 2.5 and later – the syntax is not very obvious hence it’s easy to miss. Here’s how you do it:

x = true_value if condition else false_value

For further reference, check out the Python 2.5 docs.

Answered By: mainas

(can’t comment or I would just do that) I believe the suggestion to check locals above is not quite right. It should be:

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

to be correct in all contexts.

However, despite its upvotes, I don’t think even that is a good analog to the Ruby operator. Since the Ruby operator allows more than just a simple name on the left:

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

The exception method is probably closest analog.

Answered By: Jas

I think what you are looking for, if you are looking for something in a dictionary, is the setdefault method:

(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)

The important thing to note in my example is that the setdefault method changes the dictionary if and only if the key that the setdefault method refers to is not present.

Answered By: Jeff Silverman

I do this… just sharing in case it’s useful for the OP or anyone else…

def iff(value, default):
    return default if not value else value

Usage:

z = iff(x,y) # z = x if and only if x is not null otherwise y
Answered By: chad steele
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.