2013-03-01 4 views
6

PEP8 E712 richiede che "il confronto con True sia if cond is True: o if cond:".Confronto con array numerici booleani VS PEP8 E712

Ma se seguo questo PEP8 ottengo risultati diversi/errati. Perché?

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?" 
+0

Dove trovi questo PEP8 E712? – mgilson

+2

Questo è un output diagnostico specifico mediante lo strumento 'pep8': https://github.com/jcrocholl/pep8/blob/master/pep8.py#L900. Notare che è sbagliato in questo caso perché 'a is True' non è una cosa significativa da fare con un array. – nneonneo

+0

@mgilson Puoi anche cercare python 'linter'. La maggior parte/alcuni IDE hanno plugin per fare il controllo pep8 del tuo codice. – Framester

risposta

2

Questo consiglio vale solo per if dichiarazioni di test per il "truthiness" di un valore. numpy è una bestia diversa.

>>> a = np.array([True, False]) 
>>> a == True 
array([ True, False], dtype=bool) 
>>> a is True 
False 

noti che a is True è sempre False perché a è un array, non una booleana is fa un semplice test uguaglianza riferimento (soltanto True is True; None is not True per esempio).

6

di Numpy 'True' non è la stessa 'True' come di Python 'True' e per questo is fallisce:

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

Inoltre, nello specifico, PEP 8 dice DONT uso 'si' o '==' per booleani:

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

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

un array NumPy vuoto fa prova falsey come una lista Python vuoto o dict vuoto fa:

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

A differenza di Python, un allineamento NumPy di ​​un singolo elemento Falsey fa prova Falsey:

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

Ma non è possibile utilizzare la logica con un array di NumPy con più di un elemento:

>>> 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() 

Così il ' lo spirito' di PEP 8 con Numpy è probabilmente per testare solo truthiness di ogni elemento:

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

Oppure utilizzare any:

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

ed essere consapevoli che questo non è quello che ci si aspetta:

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

Dal np.where sta tornando una tupla non vuota.