python的任何和所有函数是如何工作的?

我试图理解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 ?


参见检查条件是否适用于列表中的任何元素的python方法,以获得any的实际用法。

353078 次浏览

你正在问的问题代码来自我的答案在这里。它旨在解决比较多个位数组的问题——即10的集合。

anyall是有用的,当你可以依靠&;值-即它们在布尔上下文中的值。1是True, 0是False,这是答案利用的便利。5恰好也是True,所以当你把它混合到可能的输入中…好。是行不通的。

你可以这样做:

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

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

你可以粗略地把anyall分别看作一系列逻辑上的orand操作符。

任何

至少一个元素为true时,any将返回True。阅读真值检验。

所有

只有当所有元素为true时,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:空可迭代的情况在官方文档中有解释,如下所示

any

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

由于没有一个元素为真,因此在本例中返回False

all

如果可迭代对象的所有元素都为真(或者iterable为空),则返回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值,因此它立即返回True,而multiples_of_6的其余部分不迭代。这就是我们在输出list(multiples_of_6)时看到的结果,78True0的结果。

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


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

any(x) and not all(x)

它确保至少有一个值是真值,但不是所有值。这就是为什么它返回[False, False, False]。如果你真的想检验这两个数字是否不一样,

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

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都在寻找允许它们停止求值的条件。我给出的第一个例子要求他们为整个列表中的每个元素求布尔值。

(注意,列表文字不是它自己被惰性求值——你可以用迭代器来得到——但这只是为了说明目的。)

这里是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检查元素是否为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

让我们看看来源来确认上面的说法。

下面是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;
}
>>> any([False, False, False])
False
>>> any([False, True, False])
True
>>> all([False, True, True])
False
>>> all([True, True, True])
True
s = "eFdss"
s = list(s)
all(i.islower() for i in s )   # FALSE
any(i.islower() for i in s )   # TRUE

我知道这是旧的,但我认为它可能有助于显示这些函数在代码中的样子。这确实说明了逻辑,比文本或表格更好。实际上,它们是用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的创造者)首先建议添加__ABC0和all()时,他只是通过发布上面的代码片段来解释它们。

概念很简单:

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

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)则all语句的值为True。

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

我认为在any()计算条件的逻辑中有一些奇怪的地方。Python文档(这里也有报道)说,至少有一个条件应该计算为True,但它没有告诉所有条件都被计算!

例如,我在下面的代码中挣扎,因为我认为any()不评估所有条件:

def compare(list_a, list_b):
if any([list_a is None, list_b is None, len(list_a) == 0, len(list_b) == 0]):
return 'no comparison'
else:
return 'need comparison'
    

print(compare(list_a=None, list_b=[1, 2, 3]))
上面的代码引发一个异常,因为any仍然计算len(list_a) == 0。 在这种情况下,any()使用的逻辑是非常危险的,因为我预计只计算第一个条件

在这种情况下必须使用以下代码:

def compare(list_a, list_b):
if list_a is None or list_b is None or len(list_a) == 0 or len(list_b) == 0:
return 'no comparison'
else:
return 'need comparison'
    

print(compare(list_a=None, list_b=[1, 2, 3]))