Python的所有函数如何工作?


225

我想明白是怎么any()all() Python内置函数的工作方式。

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

d是一个defaultdict(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?


4
any(iterable):第一次遇到Truthy对象时返回true,否则返回false。all(iterable):第一次遇到虚假对象时返回flase,否则返回true。
shadow0359 '17

Answers:


374

你可以粗略地认为anyall作为系列的逻辑orand分别运营。

任何

anyTrue至少一个元素是Truthy 时将返回。阅读有关真值测试的信息。

所有

allTrue仅在所有元素都将返回时都是真。

真相表

+-----------------------------------------+---------+---------+
|                                         |   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:像这样在官方文档中说明了空的可迭代情况

any

True如果iterable的任何元素为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))是一个生成器表达式,True如果1和9中的当前数字是6的倍数,则返回。anymultiples_of_6it进行迭代,并在满足6时找到True值,因此它立即返回True,其余的multiples_of_6不进行迭代。那就是我们打印时看到的list(multiples_of_6)的结果78并且9

这个聪明的东西在 这个答案中


有了基本的了解,如果我们看一下您的代码,您就会

any(x) and not all(x)

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

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

@anyone:如果除了在返回空列表时返回True的情况下,我需要使用所有其他内容,我们该怎么办?我不明白如果列表为空则给出True的逻辑背后……意味着all([])== True
JavaSa

1
@JavaSa您可以显式检查列表是否为空。我相信类似的东西bool(data) and all(...)应该起作用。
thefourtheye

43

Python anyall函数如何工作?

anyall获取iterables并返回(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

如果iterables为空,则any返回False,然后all返回True

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

我当时正在向学生演示all和演示any。他们大多对空可迭代对象的返回值感到困惑。用这种方式进行解释导致许多灯泡打开。

捷径行为

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

(请注意,列表文字本身并不是惰性计算的-您可以使用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),然后True如果元素都不为,则返回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

any工作方式是检查元素是否为True(因此它可以返回True), then it returnsFalse if 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!

我认为,如果您牢记捷径,您将直观地了解它们的工作方式,而不必引用真值表。

all和的证据any捷径:

首先,创建一个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;
}

1
注意:这与数学谓词一致:“全部”和“存在”。困惑可能是“ FOR ALL”和“ FOR ANY”在其他上下文中是同义词... en.wikipedia.org/wiki/List_of_logic_symbols
mcoolive

1
@ thanos.a位于Python/bltinmodule.c-我将其添加到上面。
亚伦·霍尔

13

我知道这很旧,但是我认为在代码中显示这些功能看起来会有所帮助。这确实说明了逻辑,比文本或表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的创建者)首次提出添加any()and时all(),他只是通过准确地发布上述代码片段来解释它们。


9

您要查询的代码来自此处给出的答案。目的是解决比较多个位数组(即1和的集合)的问题0

anyall当您可以依赖值的“真实性”(即布尔值上下文中的值)时,此选项很有用。1是True,0是False,答案利用了一个便利。5也恰好是True,因此当您将其混入可能的输入中时...好。不起作用

您可以改为执行以下操作:

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

它缺乏先前答案的美感(我真的很喜欢的外观any(x) and not all(x)),但是可以完成工作。


科尔伯特的影响力正在达到CS / CE:en.wikipedia.org/wiki/Truthiness?我们在说模糊逻辑吗?:D
Geof Sawaya

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


1

这个概念很简单:

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 

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