【问题标题】:How do Python's any and all functions work?Python 的 any 和 all 函数是如何工作的?
【发布时间】:2013-10-23 17:53:27
【问题描述】:

我试图了解any()all() Python 内置函数的工作原理。

我正在尝试比较元组,以便如果任何值不同,它将返回True,如果它们都相同,它将返回False。在这种情况下,他们如何返回 [False, False, False]?

ddefaultdict(list)

print d['Drd2']
# [[1, 5, 0], [1, 6, 0]]
print list(zip(*d['Drd2']))
# [(1, 1), (5, 6), (0, 0)]
print [any(x) and not all(x) for x in zip(*d['Drd2'])]
# [False, False, False]

据我所知,这应该输出

# [False, True, False]

因为(1,1)相同,(5,6)不同,(0,0)相同。

为什么所有元组的评估结果都为 False?

【问题讨论】:

  • any(iterable) :在第一次遇到 Truthy 对象时返回 true,否则返回 false。 all(iterable):在第一次遇到 falsy 对象时返回 flase,否则返回 true。

标签: python


【解决方案1】:

您可以大致将anyall 分别视为一系列逻辑orand 运算符。

任何

any 将在至少有一个元素 为 Truthy 时返回 True。阅读Truth Value Testing.

全部

all 将仅在 所有元素 都为真时返回 True

真值表

+-----------------------------------------+---------+---------+
|                                         |   any   |   all   |
+-----------------------------------------+---------+---------+
| All Truthy values                       |  True   |  True   |
+-----------------------------------------+---------+---------+
| All Falsy values                        |  False  |  False  |
+-----------------------------------------+---------+---------+
| One Truthy value (all others are Falsy) |  True   |  False  |
+-----------------------------------------+---------+---------+
| One Falsy value (all others are Truthy) |  True   |  False  |
+-----------------------------------------+---------+---------+
| Empty Iterable                          |  False  |  True   |
+-----------------------------------------+---------+---------+

注1:空的iterable case在官方文档中有解释,是这样的

any

如果可迭代的任何元素为真,则返回True如果iterable为空,返回False

由于没有一个元素是真的,在这种情况下它返回False

all

如果可迭代对象的所有元素都为真(或可迭代对象为空),则返回True

由于没有一个元素是假的,在这种情况下它返回True


注2:

关于anyall 的另一件重要的事情是,它会在他们知道结果的那一刻使执行短路。优点是,不需要消耗整个可迭代对象。例如,

>>> multiples_of_6 = (not (i % 6) for i in range(1, 10))
>>> any(multiples_of_6)
True
>>> list(multiples_of_6)
[False, False, False]

这里,(not (i % 6) for i in range(1, 10)) 是一个生成器表达式,如果 1 和 9 中的当前数字是 6 的倍数,则返回 Trueany 迭代 multiples_of_6,当它遇到 6 时,它会找到一个真实值,因此它立即返回True,而multiples_of_6 的其余部分不会被迭代。这就是我们在打印 list(multiples_of_6) 时看到的,789 的结果。

这个好东西在this answer中用的很巧妙。


有了这个基本的了解,如果我们看看你的代码,你就会明白

any(x) and not all(x)

这确保至少有一个值是真实的,但不是全部。这就是它返回[False, False, False] 的原因。如果你真的想检查两个数字是否不相同,

print [x[0] != x[1] for x in zip(*d['Drd2'])]

【讨论】:

  • @anyone:如果我需要使用所有,但它为空列表返回 True 的情况是不可接受的,我们该怎么办?如果列表为空,我不明白给出 True 背后的逻辑......意思是 all([]) == True
  • @JavaSa 您可以明确检查列表是否为空。我相信像bool(data) and all(...) 这样的东西应该可以工作。
  • @JavaSa 你可以这样看:any 默认返回False,除非找到真值; all 默认返回 True,除非它找到一个虚假值。检查列表 x 是否为空就像 if(x) 一样简单,因为空列表是虚假的
【解决方案2】:

Python 的 anyall 函数如何工作?

anyall 采用可迭代对象并返回 True,如果任何和所有(分别)元素是 True

>>> any([0, 0.0, False, (), '0']), all([1, 0.0001, True, (False,)])
(True, True)            #   ^^^-- truthy non-empty string
>>> any([0, 0.0, False, (), '']), all([1, 0.0001, True, (False,), {}])
(False, False)                                                #   ^^-- falsey

如果可迭代对象为空,any 返回Falseall 返回True

>>> any([]), all([])
(False, True)

我今天在课堂上为学生演示allany。他们大多对空迭代的返回值感到困惑。这么解释导致很多灯泡都亮了。

捷径行为

anyall 都在寻找允许他们停止评估的条件。我给出的第一个示例要求他们评估整个列表中每个元素的布尔值。

(请注意,列表文字 本身并不是 懒惰评估的 - 你可以使用 Iterator 得到它 - 但这仅用于说明目的。)

这是任何和所有的 Python 实现:

def any(iterable):
    for i in iterable:
        if i:
            return True
    return False # for an empty iterable, any returns False!

def all(iterable):
    for i in iterable:
        if not i:
            return False
    return True  # for an empty iterable, all returns True!

当然,真正的实现是用 C 语言编写的,并且性能要好得多,但是您可以替换上面的内容,并在此(或任何其他)答案中的代码中获得相同的结果。

all

all 检查元素是否为False(因此它可以返回False),然后如果它们都不是False,则返回True

>>> all([1, 2, 3, 4])                 # has to test to the end!
True
>>> all([0, 1, 2, 3, 4])              # 0 is False in a boolean context!
False  # ^--stops here!
>>> all([])
True   # gets to end, so True!

any

any 的工作方式是检查元素是否为True(因此它可以返回True), then it returnsFalseif none of them wereTrue`。

>>> any([0, 0.0, '', (), [], {}])     # has to test to the end!
False
>>> any([1, 0, 0.0, '', (), [], {}])  # 1 is True in a boolean context!
True   # ^--stops here!
>>> any([])
False   # gets to end, so False!

我认为,如果您牢记捷径行为,您将直观地了解它们的工作原理,而无需参考真值表。

allany 捷径的证据:

首先,创建一个noisy_iterator:

def noisy_iterator(iterable):
    for i in iterable:
        print('yielding ' + repr(i))
        yield i

现在让我们使用我们的示例来嘈杂地遍历列表:

>>> all(noisy_iterator([1, 2, 3, 4]))
yielding 1
yielding 2
yielding 3
yielding 4
True
>>> all(noisy_iterator([0, 1, 2, 3, 4]))
yielding 0
False

我们可以看到all 在第一次 False 布尔检查时停止。

any 在第一次 True 布尔检查时停止:

>>> any(noisy_iterator([0, 0.0, '', (), [], {}]))
yielding 0
yielding 0.0
yielding ''
yielding ()
yielding []
yielding {}
False
>>> any(noisy_iterator([1, 0, 0.0, '', (), [], {}]))
yielding 1
True

来源

让我们看一下来源以确认上述内容。

这是source for any

static PyObject *
builtin_any(PyObject *module, PyObject *iterable)
{
    PyObject *it, *item;
    PyObject *(*iternext)(PyObject *);
    int cmp;

    it = PyObject_GetIter(iterable);
    if (it == NULL)
        return NULL;
    iternext = *Py_TYPE(it)->tp_iternext;

    for (;;) {
        item = iternext(it);
        if (item == NULL)
            break;
        cmp = PyObject_IsTrue(item);
        Py_DECREF(item);
        if (cmp < 0) {
            Py_DECREF(it);
            return NULL;
        }
        if (cmp > 0) {
            Py_DECREF(it);
            Py_RETURN_TRUE;
        }
    }
    Py_DECREF(it);
    if (PyErr_Occurred()) {
        if (PyErr_ExceptionMatches(PyExc_StopIteration))
            PyErr_Clear();
        else
            return NULL;
    }
    Py_RETURN_FALSE;
}

这是source for all

static PyObject *
builtin_all(PyObject *module, PyObject *iterable)
{
    PyObject *it, *item;
    PyObject *(*iternext)(PyObject *);
    int cmp;

    it = PyObject_GetIter(iterable);
    if (it == NULL)
        return NULL;
    iternext = *Py_TYPE(it)->tp_iternext;

    for (;;) {
        item = iternext(it);
        if (item == NULL)
            break;
        cmp = PyObject_IsTrue(item);
        Py_DECREF(item);
        if (cmp < 0) {
            Py_DECREF(it);
            return NULL;
        }
        if (cmp == 0) {
            Py_DECREF(it);
            Py_RETURN_FALSE;
        }
    }
    Py_DECREF(it);
    if (PyErr_Occurred()) {
        if (PyErr_ExceptionMatches(PyExc_StopIteration))
            PyErr_Clear();
        else
            return NULL;
    }
    Py_RETURN_TRUE;
}

【讨论】:

  • 注意:这与数学谓词一致:“for all”和“it exists”。混淆可能是“FOR ALL”和“FOR ANY”在其他上下文中是同义词......en.wikipedia.org/wiki/List_of_logic_symbols
  • @thanos.a 它在Python/bltinmodule.c - 我把它加到上面了。
【解决方案3】:

我知道这是旧的,但我认为在代码中显示这些函数的样子可能会有所帮助。这确实说明了逻辑,比文本或表格 IMO 更好。实际上,它们是用 C 而不是纯 Python 实现的,但它们是等价的。

def any(iterable):
    for item in iterable:
        if item:
            return True
    return False

def all(iterable):
    for item in iterable:
        if not item:
            return False
    return True

特别是,您可以看到空迭代的结果只是自然结果,而不是特殊情况。您还可以看到短路行为;实际上,如果 发生短路,工作量会更大。

当 Guido van Rossum(Python 的创建者)first proposed adding any() and all() 时,他只是通过发布上面的 sn-ps 代码来解释它们。

【讨论】:

    【解决方案4】:

    您所询问的代码来自我给出的here 的回答。它旨在解决比较多个位数组的问题 - 即 10 的集合。

    anyall 在您可以依赖值的“真实性”时很有用 - 即它们在布尔上下文中的值。 1 是True,0 是False,这个答案利用了便利性。 5 恰好也是True,所以当你把它混合到你可能的输入中时......好吧。没用。

    你可以这样做:

    [len(set(x)) > 1 for x in zip(*d['Drd2'])]
    

    它缺乏上一个答案的美感(我真的喜欢any(x) and not all(x) 的外观),但它完成了工作。

    【讨论】:

    • Colbert 的影响力正在达到 CS/CE:en.wikipedia.org/wiki/Truthiness ?我们在谈论模糊逻辑吗? :D
    • 当值不同时,当 OP 要求 True 时,集合的长度应该是 2,而不是 1。
    • @wombatonfire 哈哈,很好。我已经调整了我 7 岁的答案:)
    • 好的答案不会老化 :) 一套不错的方法。
    【解决方案5】:
    >>> any([False, False, False])
    False
    >>> any([False, True, False])
    True
    >>> all([False, True, True])
    False
    >>> all([True, True, True])
    True
    

    【讨论】:

      【解决方案6】:
      s = "eFdss"
      s = list(s)
      all(i.islower() for i in s )   # FALSE
      any(i.islower() for i in s )   # TRUE
      

      【讨论】:

        【解决方案7】:

        all() 函数用于检查集合中的每个成员是否为真。例如,all() 函数可用于更简洁地对以下形式的语句进行条件化:

        if all entre's are vegan this is a vegan restaurant
        

        在代码中:

        restaurant_is_vegan = all(x is vegan for x in menu)
        

        如果菜单(迭代器)上的每个项目 (x) 对于条件 (is vegan; x == vegan) 的计算结果为 True,则 all 语句的计算结果为 True。

        更多示例:https://www.alpharithms.com/python-all-function-223809/

        【讨论】:

          【解决方案8】:

          概念很简单:

          M =[(1, 1), (5, 6), (0, 0)]
          
          1) print([any(x) for x in M])
          [True, True, False] #only the last tuple does not have any true element
          
          2) print([all(x) for x in M])
          [True, True, False] #all elements of the last tuple are not true
          
          3) print([not all(x) for x in M])
          [False, False, True] #NOT operator applied to 2)
          
          4) print([any(x)  and not all(x) for x in M])
          [False, False, False] #AND operator applied to 1) and 3)
          # if we had M =[(1, 1), (5, 6), (1, 0)], we could get [False, False, True]  in 4)
          # because the last tuple satisfies both conditions: any of its elements is TRUE 
          #and not all elements are TRUE 
          

          【讨论】:

            【解决方案9】:
            list = [1,1,1,0]
            print(any(list)) # will return True because there is  1 or True exists
            print(all(list)) # will return False because there is a 0 or False exists
            return all(a % i for i in range(3, int(a ** 0.5) + 1)) # when number is divisible it will return False else return True but the whole statement is False .
            

            【讨论】:

              猜你喜欢
              • 2013-05-06
              • 2014-07-03
              • 2020-10-18
              • 2013-09-09
              • 1970-01-01
              • 2018-11-29
              • 2017-04-18
              相关资源
              最近更新 更多