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

后端 未结 5 1566
名媛妹妹
名媛妹妹 2021-01-30 19:48

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 an         


        
相关标签:
5条回答
  • 2021-01-30 19:55

    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]):
    
    0 讨论(0)
  • 2021-01-30 19:58

    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.

    0 讨论(0)
  • 2021-01-30 20:01

    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.

    0 讨论(0)
  • 2021-01-30 20:02

    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.

    >>> import timeit
    >>> timeit.timeit("all(v is not None for v in [1, 84, 'String', (6, 'Tuple'), 3])")
    1.7880705000000034
    >>> timeit.timeit("None not in [1, 84, 'String', (6, 'Tuple'), 3]")
    0.35424169999998867
    >>> timeit.timeit("None not in (1, 84, 'String', (6, 'Tuple'), 3)")
    0.3454340999999772
    >>> timeit.timeit("None not in {1, 84, 'String', (6, 'Tuple'), 3}")
    0.09577370000002361
    

    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 my_int(int):
        def __init__(self, parent):
            super().__init__()
    
        def __eq__(self, other):
            return True
    
        def __hash__(self):
            return hash(super())
    
    print(all(v is not None for v in [1, my_int(6), 2])) # True (correct)
    print(None not in [1, my_int(6), 2])                 # False (wrong)
    print(None not in (1, my_int(6), 2))                 # False (wrong)
    print(None not in {1, my_int(6), 2})                 # True (correct)
    
    0 讨论(0)
  • 2021-01-30 20:18

    Writing a separate answer as I do not know how to format code when added as a comment.

    Eternal_N00B's solution is not same as Daniel Roseman's solution. Consider for example:

    >>> all(v is not None for v in [False])
    True
    >>> all([False])
    False
    
    0 讨论(0)
提交回复
热议问题