【问题标题】:What is the most pythonic way to check if multiple variables are not None?检查多个变量是否不是None的最pythonic方法是什么?
【发布时间】:2017-02-21 07:20:02
【问题描述】:

如果我有这样的构造:

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 中检查所有变量是否都设置为有用值的首选语法是什么?是像我写的那样,还是其他更好的方法?

这与这个问题不同: not None test in Python ...我正在寻找检查许多条件是否不是无的首选方法。我输入的选项看起来很长而且不是pythonic。

【问题讨论】:

  • not None test in Python的可能重复
  • 我正在检查四个变量,并且认为您发布的明显解决方案不是很pythonic。我很遗憾不得不从缺乏答案中得出结论,似乎没有“更好”的方式。
  • @schwobaseggl:不,这不是重复的,因为问题不在于如何检查无。它是关于如何在检查多个变量时使其“看起来更 Pythonic”,但没有那么多变量来纠正 Daniel Roseman 提出的解决方案。
  • def all_is_not_None(*args): return all(x is not None for x in args)

标签: python


【解决方案1】:

真的可以简单得多

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

更新:

正如 slashCoder 正确指出的那样,上面的代码隐含地执行 a == None、b == None 等。这种做法是不受欢迎的。相等运算符可以重载,not None 可以等于 None。你可能会说它永远不会发生。好吧,它没有,直到它发生。所以,为了安全起见,如果你想检查没有一个对象是 None ,你可以使用这种方法

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

它有点慢,表达力较差,但它仍然相当快和短。

【讨论】:

  • 是的!而且速度也快了 10 倍! (据timeit
  • 这样做的问题是innot in 运算符对集合的每个元素进行相等性检查,在 PEP8 中建议不要这样做。
  • 请注意这是一个尤达条件(en.wikipedia.org/wiki/Yoda_conditions),必须谨慎使用。
  • @Chandrahas Aroori:嗯嗯。谨慎行事!
  • 在 Pandas/Dask 中产生:ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()related
【解决方案2】:

你的做法没有问题。

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

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

【讨论】:

    【解决方案3】:

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

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

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

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

    $ 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
    

    此方法的另一个优点是即使有人将类的__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 要检查一个项目是否存在于列表中,将该项目与列表的每个元素进行比较。那是O(n)。然而,在一个集合的情况下,Python 简单地计算项目的哈希,并检查该集合是否具有所述哈希的有效条目。这是O(1)
    【解决方案4】:

    针对 OP 提出的具体案例

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

    足够了。

    all([a, b, c])
    

    如果缺少任何参数,则评估为 False。

    【讨论】:

      【解决方案5】:

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

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

      >>> 全部(对于 [False] 中的 v,v 不是无) 真的 >>> 全部([假]) 错误的

      【讨论】:

        猜你喜欢
        • 2011-03-27
        • 1970-01-01
        • 2010-11-30
        • 1970-01-01
        • 1970-01-01
        • 2017-08-23
        • 1970-01-01
        • 2016-03-11
        • 1970-01-01
        相关资源
        最近更新 更多