What is the most pythonic way to check if multiple variables are not None?

Question:

If I have a construct like this:

def foo():
    a=None
    b=None
    c=None

    #...loop over a config file or command line options...

    if a is not None and b is not None and c is not None:
        doSomething(a,b,c)
    else:
        print "A config parameter is missing..."

What is the preferred syntax in python to check if all variables are set to useful values? Is it as I have written, or another better way?

This is different from this question:
not None test in Python … I am looking for the preferred method for checking if many conditions are not None. The option I have typed seems very long and non-pythonic.

Asked By: Eyelash

||

Answers:

There’s nothing wrong with the way you’re doing it.

If you have a lot of variables, you could put them in a list and use all:

if all(v is not None for v in [A, B, C, D, E]):
Answered By: Daniel Roseman

It can be done much simpler, really

if None not in (a, b, c, d):
    pass

UPDATE:

As slashCoder has correctly remarked, the code above implicitly does a == None, b == None, etc. This practice is frowned upon. The equality operator can be overloaded and not None can become equal to None. You may say that it never happens. Well it does not, until it does. So, to be on the safe side, if you want to check that none of the objects are None you may use this approach

if not [x for x in (a, b, c, d) if x is None]:
    pass

It is a bit slower and less expressive, but it is still rather fast and short.

Answered By: serge.v

I know this is an old question, but I wanted to add an answer which I believe is better.

If all elements which have to be checked are hashable, you could use a set instead of a list or tuple.

>>> None not in {1, 84, 'String', (6, 'Tuple'), 3}

This is much faster than the methods in the other answers.

$ python3 -m timeit "all(v is not None for v in [1, 84, 'String', (6, 'Tuple'), 3])"
200000 loops, best of 5: 999 nsec per loop

$ python3 -m timeit "None not in [1, 84, 'String', (6, 'Tuple'), 3]"
2000000 loops, best of 5: 184 nsec per loop

$ python3 -m timeit "None not in (1, 84, 'String', (6, 'Tuple'), 3)"
2000000 loops, best of 5: 184 nsec per loop

python3 -m timeit "None not in {1, 84, 'String', (6, 'Tuple'), 3}"
5000000 loops, best of 5: 48.6 nsec per loop

Another advantage of this method is that it gives you the correct answer even if someone defines the __eq__ method of a class to always return True. (Of course, if they define the __hash__ method to return hash(None), this method won’t work. But nobody should do that, because it would defeat the purpose of defining a hash.)

class Int(int):
    def __eq__(self, other):
        return True
    def __hash__(self):
        return hash(super())

print(all(v is not None for v in [1, Int(6), 2])) # True (correct)
print(None not in [1, Int(6), 2])                 # False (wrong)
print(None not in (1, Int(6), 2))                 # False (wrong)
print(None not in {1, Int(6), 2})                 # True (correct)
Answered By: tfpf

EDIT:
As noted by Mo2, this solution will fail if any variable is set to 0 and 0 is considered a ‘useful’ value.

For the specific case presented by the OP

if not all([a, b, c])

will be enough.

all([a, b, c])

evaluates to False if any parameter is missing.

Answered By: papok
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.