Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
745 views
in Technique[技术] by (71.8m points)

python - Comparison with boolean numpy arrays VS PEP8 E712

PEP8 E712 requires that "comparison to True should be if cond is True: or if cond:".

But if I follow this PEP8 I get different/wrong results. Why?

In [1]: from pylab import *

In [2]: a = array([True, True, False])

In [3]: where(a == True)
Out[3]: (array([0, 1]),)
# correct results with PEP violation

In [4]: where(a is True)
Out[4]: (array([], dtype=int64),)
# wrong results without PEP violation

In [5]: where(a)
Out[5]: (array([0, 1]),)
# correct results without PEP violation, but not as clear as the first two imho. "Where what?"
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Numpy's 'True' is not the same 'True' as Python's 'True' and therefor is fails:

>>> import numpy as np
>>> a = np.array([True, True, False])
>>> a[:]
array([ True,  True, False], dtype=bool)
>>> a[0]
True
>>> a[0]==True
True
>>> a[0] is True
False
>>> type(a[0])
<type 'numpy.bool_'>
>>> type(True)
<type 'bool'>

Also, specifically, PEP 8 says DONT use 'is' or '==' for Booleans:

Don't compare boolean values to True or False using ==:

Yes:   if greeting:
No:    if greeting == True:
Worse: if greeting is True:

An empty numpy array does test falsey just as an empty Python list or empty dict does:

>>> [bool(x) for x in [[],{},np.array([])]]
[False, False, False] 

Unlike Python, a numpy array of a single falsey element does test falsey:

>>> [bool(x) for x in [[False],[0],{0:False},np.array([False]), np.array([0])]]
[True, True, True, False, False]

But you cannot use that logic with a numpy array with more than one element:

>>> bool(np.array([0,0]))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

So the 'spirit' of PEP 8 with Numpy is probably to only test each element's truthiness:

>>> np.where(np.array([0,0]))
(array([], dtype=int64),)
>>> np.where(np.array([0,1]))
(array([1]),)

Or use any:

>>> np.array([0,0]).any()
False
>>> np.array([0,1]).any()
True

And be aware that this is not what you expect:

>>> bool(np.where(np.array([0,0])))
True

Since np.where is returning a nonempty tuple.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...