a < b < c是Python中的链式表达式,看起来它适用于定义了适当比较运算符的对象,但它不适用于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
Run Code Online (Sandbox Code Playgroud)
这打印:
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()
Run Code Online (Sandbox Code Playgroud)
0 < numlist < 3.5
Run Code Online (Sandbox Code Playgroud)
相当于:
(0 < numlist) and (numlist < 3.5)
Run Code Online (Sandbox Code Playgroud)
除了numlist只评估一次.
and两个结果之间的隐含导致错误
所以文档说:
形式上,如果 a, b, c, ..., y, z 是表达式,op1, op2, ..., opN 是比较运算符,则 a op1 b op2 c ... y opN z 等价于 a op1 b b op2 c 和 ... y opN z,不同之处在于每个表达式最多计算一次。
和
(但在这两种情况下,当发现 x < y 为假时,根本不会计算 z)。
对于标量
In [20]: x=5
In [21]: 0<x<10
Out[21]: True
In [22]: 0<x and x<10
Out[22]: True
Run Code Online (Sandbox Code Playgroud)
但是用数组
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()
Run Code Online (Sandbox Code Playgroud)
当在需要标量布尔值的上下文中使用 numpy 布尔值时,会出现此 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()
Run Code Online (Sandbox Code Playgroud)
它评估0<x,但甚至不评估x<10,因为它无法在or/and上下文中使用生成的布尔数组。numpy定义了|和&,但没有or定义 或and。
In [34]: (0<x) & x<10
Out[34]: array([ True, True, True], dtype=bool)
Run Code Online (Sandbox Code Playgroud)
当我们使用时,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)
Run Code Online (Sandbox Code Playgroud)
请注意,尝试将链接应用于列表甚至不会超过第一个<:
In [39]: 0 < [-1,5,11]
TypeError: unorderable types: int() < list()
Run Code Online (Sandbox Code Playgroud)
这组表达式表明该&运算符的优先级高于该<运算符:
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...
Run Code Online (Sandbox Code Playgroud)
因此,安全的版本是 (0 < x) & (x<10),确保所有内容都<在&.
这是证实快捷and评估的另一个示例:
In [53]: x=2
In [54]: 3<x<np.arange(4)
Out[54]: False
In [55]: 1<x<np.arange(4)
Out[55]: array([False, False, False, True])
Run Code Online (Sandbox Code Playgroud)
当3<xis 时False,它返回该值,而不进行进一步评估。
当它是 时True,它继续计算x<np.arange(4),返回一个 4 元素布尔值。
<或者使用一个根本不支持的列表:
In [56]: 3<x<[1,2,3]
Out[56]: False
In [57]: 1<x<[1,2,3]
Traceback (most recent call last):
File "<ipython-input-57-e7430e03ad55>", line 1, in <module>
1<x<[1,2,3]
TypeError: '<' not supported between instances of 'int' and 'list'
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
521 次 |
| 最近记录: |