Python 的 any 和 all 函数是如何工作的?

新手上路,请多包涵

我试图了解 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 的实际用法,请参阅 检查条件是否适用于列表的任何元素的 Pythonic 方法

原文由 O.rka 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 395
2 个回答

您可以粗略地认为 anyall 是一系列逻辑运算符 orand

任何

any 将返回 True至少有一个元素 是 Truthy 时。阅读 真值测试。

全部

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]

Here, (not (i % 6) for i in range(1, 10)) is a generator expression which returns True if the current number within 1 and 9 is a multiple of 6. any iterates the multiples_of_6 当它遇到 6 时,它找到一个 Truthy 值,所以它立即返回 True ,其余的 multiples_of_6 不会被迭代。这就是我们在打印 list(multiples_of_6) 时看到的结果,即 789 的结果。

这个优秀的东西在 这个答案 中被非常巧妙地使用了。


有了这个基本的了解,如果我们看一下你的代码,你就知道了

any(x) and not all(x)

这确保了至少其中一个值是真实的,但不是全部。这就是为什么它返回 [False, False, False] 。如果您真的想检查两个数字是否不相同,

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

原文由 thefourtheye 发布,翻译遵循 CC BY-SA 4.0 许可协议

Python 的 anyall 函数如何工作?

any and all take iterables and return True if any and all (respectively) of the elements are 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

If the iterables are empty, any returns False , and all returns True .

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

我今天在课堂上为学生演示了 allany 。他们大多对空可迭代对象的返回值感到困惑。以这种方式解释它会导致很多灯泡亮起。

捷径行为

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

(请注意,列表文字 本身并不是 延迟计算的——您可以使用 Iterator 获得它——但这只是为了说明目的。)

这是 any 和 all 的 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 checks for elements to be False (so it can return False ), then it returns True if none of them were False

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

The way any works is that it checks for elements to be True (so it can return True), then it returns False if none of them were True`.

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

来源

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

这是 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;
}

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

原文由 Russia Must Remove Putin 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
logo
Stack Overflow 翻译
子站问答
访问
宣传栏