Python 的 any 和 all 函数如何工作?
- 2024-11-29 08:41:00
- admin 原创
- 189
问题描述:
我试图了解any()
Pythonall()
内置函数的工作原理。
我正在尝试比较元组,以便如果任何值不同,它将返回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
。
解决方案 1:
您可以粗略地将any
和分别视为all
一系列逻辑or
与and
运算符。
任何
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:官方文档中对空可迭代对象的情况进行了解释,如下所示
any
True
如果可迭代对象中的任何元素为真,则返回。如果可迭代对象为空,则返回False
由于没有任何元素为真,因此False
在这种情况下它会返回。
all
True
如果可迭代对象的所有元素都为真(或可迭代对象为空),则返回。
由于没有任何元素为假,因此True
在这种情况下它会返回。
注2:
关于any
and 的另一件重要的事情all
是,一旦知道结果,它就会立即执行。优点是不需要消耗整个可迭代对象。例如,
>>> 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 的倍数。any
迭代 ,multiples_of_6
当它遇到 时6
,它会找到一个真值,因此它会立即返回True
,其余的multiples_of_6
不会被迭代。这就是我们在打印 时看到的,即 和list(multiples_of_6)
的结果。7
`8`9
这个优秀的东西在这个答案中运用得非常巧妙。
有了这个基本理解,如果我们看一下你的代码,你就会发现
any(x) and not all(x)
这确保了至少一个值是真值,但不是全部。这就是它返回的原因[False, False, False]
。如果你真的想检查两个数字是否不同,
print [x[0] != x[1] for x in zip(*d['Drd2'])]
解决方案 2:
Python
any
和all
函数如何工作?
any
并获取可迭代对象,如果任何或所有元素(分别)是,all
则返回。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
返回False
,并all
返回True
。
>>> any([]), all([])
(False, True)
今天我在课堂上向学生们演示了all
这any
一点。他们大多对空可迭代对象的返回值感到困惑。这样解释让他们顿时豁然开朗。
快捷行为
它们any
和all
都寻找允许它们停止评估的条件。我给出的第一个例子要求它们评估整个列表中每个元素的布尔值。
(请注意,列表文字本身并不是惰性求值的 - 您可以使用迭代器来获得它- 但这只是为了说明目的。)
以下是 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
则返回。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 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!
我认为,如果您记住快捷行为,您将直观地了解它们的工作原理,而无需参考真值表。
证据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;
}
解决方案 3:
我知道这已经过时了,但我认为展示这些函数在代码中的样子可能会有所帮助。这确实说明了逻辑,在我看来比文本或表格更好。实际上,它们是用 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()
和all()
时,他通过发布上述代码片段来解释它们。
解决方案 4:
您所询问的代码来自我在此处给出的答案。它旨在解决比较多个位数组(即1
和的集合)的问题0
。
any
`all当你可以依赖值的“真实性”时,它们很有用 - 即它们在布尔上下文中的值。1 是 ,0
True是
False,这个答案利用了这种便利。5 恰好也是
True`,所以当你将它混合到你的可能输入中时……好吧。不起作用。
你可以做这样的事情:
[len(set(x)) > 1 for x in zip(*d['Drd2'])]
它缺乏前一个答案的美感(我真的很喜欢它的外观any(x) and not all(x)
),但它完成了工作。
解决方案 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:
这个概念很简单:
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
解决方案 8:
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)对于条件(是素食主义者;x == 素食主义者)的计算结果为 True,则所有语句都将计算为 True。
更多示例在这里: https: //www.alpharithms.com/python-all-function-223809/
解决方案 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 .
解决方案 10:
我认为评估条件的逻辑有些奇怪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]))
扫码咨询,免费领取项目管理大礼包!