【问题标题】:Test if all values are in an iterable in a pythonic way以pythonic方式测试所有值是否都在可迭代中
【发布时间】:2015-07-17 20:56:47
【问题描述】:

我目前正在这样做:

if x in a and y in a and z in a and q in a and r in a and s in a:
    print b

有没有更 Pythonic 的方式来表达这个if 语句?

【问题讨论】:

    标签: python if-statement


    【解决方案1】:

    使用all 函数可以以简洁紧凑的方式编写:

    if all(i in a for i in (x, y, z, q, r, s)):
        print b
    

    即使对象不可散列或a 对象有一些有趣的__contains__ 方法,这段代码的作用也应该与您的示例几乎完全相同。 all 函数也具有与原始问题中and 的链相似的short-circuit 行为。在一个元组(或一个列表)中收集所有要测试的对象将保证测试的执行顺序与原始问题中的相同。如果你使用一套,顺序可能是随机的。

    【讨论】:

    • 吹毛求疵:这完全等同于 OP 代码,即使 all 是懒惰的。问题是元组(x, y, z, q, r, s) 是在运行任何迭代之前完全构建的,如果xy 等是表达式,其中一些可能会引发异常。在这种情况下,OP 的代码可以返回 False 并避免异常,而此代码将始终引发异常。
    • “一些有趣的__contains__ 方法”——所以我们到达了鸭式打字的棘手角落。提问者说“在可迭代中”,但如果 a 实现 __contains__ 那么对于提问者的代码,a 是否可迭代甚至都无关紧要......
    • @Bakuriu,但它们不是表达式。它们是变量——假设 OP 正在编写 Python,而不是元 Python。
    • @PaulDraper 如果代码不完整,我总是假设“meta-python”。我只是想指出,对于未来的读者来说,两者之间存在一个小的语义差异。
    • 如果 Python 有一个 .contains() 方法和一个 if_all 语句,这种事情会更好。我认为条件会更好地阅读为if all (a.__contains__(i) for i in [x, y, z, q, r, s]):,或者如果您更喜欢避免使用.__contains__,然后使用operator.contains:if all (contains(a, i) for i in [x, y, z, q, r, s]):
    【解决方案2】:

    另一种方法是使用子集:

    if {x, y, z, q, r, s}.issubset(a):
        print(b)
    

    REPL 示例:

    >>> {0, 1, 2}.issubset([0, 1, 2, 3])
    True
    >>> {0, 1, 2}.issubset([1, 2, 3])
    False
    

    这种方法的一个注意事项是所有xyz 等都必须是可散列的。

    【讨论】:

      【解决方案3】:
      if all(v in a for v in {x, y, z, q, r, s}):
          print(b)
      

      【讨论】:

        【解决方案4】:

        转换为集合,或者:

        if len({x, y, z, q, r, s} - set(a)) == 0:
            print b
        

        t = {x, y, z, q, r, s}
        if t & set(a) == t:
            print b
        

        【讨论】:

          猜你喜欢
          • 2019-08-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-04-19
          • 2013-08-20
          • 1970-01-01
          • 2012-11-07
          • 1970-01-01
          相关资源
          最近更新 更多