a < b < c
是Python中的chained expression,看起来它适用于定义了适当比较运算符的对象,但它不适用于numpy数组。为什么呢?
import numpy as np
class ContrarianContainer(object):
def __init__(self, x):
self.x = x
def __le__(self, y):
return not self.x <= y
def __lt__(self, y):
return not self.x < y
def __ge__(self, y):
return not self.x >= y
def __gt__(self, y):
return not self.x > y
def __eq__(self, y):
return not self.x == y
def __ne__(self, y):
return not self.x != y
numlist = np.array([1,2,3,4])
for n in numlist:
print 0 < n < 3.5
for n in numlist:
print 0 > ContrarianContainer(n) > 3.5
print 0 < numlist < 3.5
打印:
True
True
True
False
True
True
True
False
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-187-277da7750148> in <module>()
4 for n in numlist:
5 print 0 < n < 3.5
----> 6 print 0 < numlist < 3.5
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
答案 0 :(得分:6)
0 < numlist < 3.5
相当于:
(0 < numlist) and (numlist < 3.5)
除了numlist
仅评估一次。
两个结果之间的隐式and
导致错误
答案 1 :(得分:3)
所以文档说:
形式上,如果a,b,c,...,y,z是表达式而op1,op2,...,opN是比较运算符,那么op1 b op2 c ... y opN z相当于a op1 b和b op2 c和... y opN z,除了每个表达式最多被评估一次。
和
(但在两种情况下,当发现x&lt; y为假时,根本不评估z。)
标量
In [20]: x=5
In [21]: 0<x<10
Out[21]: True
In [22]: 0<x and x<10
Out[22]: True
但是有一个数组
In [24]: x=np.array([4,5,6])
In [25]: 0<x and x<10
...
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
当在需要标量布尔值的上下文中使用numpy boolean时,会出现此ValueError。
In [26]: (0<x)
Out[26]: array([ True, True, True], dtype=bool)
In [30]: np.array([True, False]) or True
...
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
In [33]: if np.array([True, False]): print('yes')
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
它评估0<x
,但甚至不评估x<10
,因为它不能在or/and
上下文中使用生成的布尔数组。 numpy
已定义|
和&
,但未定义or
或and
。
In [34]: (0<x) & x<10
Out[34]: array([ True, True, True], dtype=bool)
当我们使用0 < x <10
时,我们隐含地期望评估标量链式表达式的矢量化版本。
In [35]: f = np.vectorize(lambda x: 0<x<10, otypes=[bool])
In [36]: f(x)
Out[36]: array([ True, True, True], dtype=bool)
In [37]: f([-1,5,11])
Out[37]: array([False, True, False], dtype=bool)
请注意,尝试将链接应用于列表甚至不会超过第一个<
:
In [39]: 0 < [-1,5,11]
TypeError: unorderable types: int() < list()
这组表达式表明&
运算符优先于<
运算符:
In [44]: 0 < x & x<10
ValueError ...
In [45]: (0 < x) & x<10
Out[45]: array([ True, True, True], dtype=bool)
In [46]: 0 < x & (x<10)
Out[46]: array([False, True, False], dtype=bool)
In [47]: 0 < (x & x)<10
ValueError...
所以安全版本为(0 < x) & (x<10)
,确保在<
之前评估所有&
。