检查多个变量是否不为None的最有效方法是什么?


79

如果我有这样的构造:

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..."

python中检查所有变量是否都设置为有用值的首选语法是什么?是我写的还是其他更好的方法?

这与以下问题不同: 在Python中不是None测试...我正在寻找检查许多条件是否为None的首选方法。我输入的选项似乎很长,而且不是Python语言。



我正在检查四个变量,并且还以为您发布的显而易见的解决方案不是pythonic。我很遗憾不得不从缺乏答案的结论中得出结论,似乎没有一种“更聪明”的方式。
wedi

3
@schwobaseggl:不,这不是重复的,因为问题不在于如何检查“无”。这是关于如何在检查多个变量时使它“看起来更pythonic”,而不是为了纠正丹尼尔·罗斯曼提出的解决方案而过多。
wedi

Answers:


83

您的操作方式没有错。

如果您有很多变量,可以将它们放在列表中并使用all

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

107

确实可以做得简单得多

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

更新:

正如slashCoder正确说明的那样,上面的代码隐式地执行a == None,b == None等。等于运算符可以重载,并且没有None可以等于None。您可能会说这永远不会发生。好吧,直到它做到为止,它不会。因此,为了安全起见,如果要检查所有对象都不为“无”,则可以使用此方法

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

它稍慢一些,但表现力较差,但仍然很短。


4
是! 而且速度也快十倍!(根据timeit
-Praind

3
问题在于,inandnot in运算符对集合的每个元素进行相等性检查,PEP8建议不要这样做。
slashCoder

2
请注意,这是Yoda条件(en.wikipedia.org/wiki/Yoda_conditions),必须谨慎使用。
Chandrahas Aroori

1
@Chandrahas Aroori:嗯。请务必谨慎!
serge.v

7

我知道这是一个老问题,但我想补充一个我认为更好的答案。

如果所有必须检查的元素都是可哈希的,则可以使用集合而不是列表或元组。

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

这比其他答案中的方法快得多。

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

此方法的另一个优点是,即使有人定义了__eq__始终返回的类的方法,它也可以为您提供正确的答案True。(当然,如果他们将__hash__方法定义为return hash(None),则此方法将不起作用。但是,任何人都不应这样做,因为它会破坏定义哈希的目的。)

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)

为什么dict比list和tuple快?
zheyuanWang

1
@zheyuanWang要检查列表中是否存在某个项目,请将该项目与列表中的每个元素进行比较。那是O(n)。但是,在集合的情况下,Python会简单地计算项目的哈希值,并检查集合是否具有用于所述哈希值的有效条目。这是O(1)
tfpf

4

写一个单独的答案,因为当添加为注释时我不知道如何格式化代码。

Eternal_N00B的解决方案与Daniel Roseman的解决方案不同。考虑例如:

>>>全部([False]中的v并非v)
真正
>>>全部([假])
假

3

对于业务代表提出的具体情况

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

足够了。

all([a, b, c])

如果缺少任何参数,则求值为False。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.