I noted this syntax listed as a gotchya but with no explanation as to why:
def func(x=None):
#good
if x == None:
x = []
#bad
x = x or []
In what ways can this be a gotchya?
I noted this syntax listed as a gotchya but with no explanation as to why:
def func(x=None):
#good
if x == None:
x = []
#bad
x = x or []
In what ways can this be a gotchya?
In this particular case, it’s bad because an empty list evaluates to false. If you mutate the list, then the results won’t be as expected
def func(x=None):
x = x or []
x.append('hello')
mylist = []
func(mylist)
print mylist[0] # doesn't work
Since you want to check to see if the caller passed None
or not, you should just say that explicitly and not try to be clever. Objects like []
, ()
, {}
, 0
, and False
evaluate to false, as can any user-defined object that wants to — checking for falsehood really catches too many false positives.
(Also: Using is None
instead of == None
can be faster and more reliable.)
x or []
will return an empty list if bool(x)
is false. None
is false, but zeros (ints, longs, floats, etc) and empty collections ([]
, {}
, ""
, etc) are also false. So this isn't catching None
, it's catching falsy object - which isn't equivalent to x == None
and most likely not what you want (empty collections are perfectly valid input for many algorithms).
Oh, and while we're at it: That should be x is None
- is
is the semantically correct (and propably faster) choice for testing identity. ==
can be overwritten by x, and you can't be sure if it won't consider None
equal to itself or even break on it.
I think the best idiom to check for any python singleton is:
if x is None:
x = []
The reason is that some objects like ORM objects in django or sqlalchemy, for example, are lazy (they will not call the database until the latest possible time). Using the other options to check for None may trigger evaluation of an expensive operation.