2016-06-08 98 views
3

爲什麼,在Python/numpy的:蟒蛇NumPy的奇怪的布爾運算的行爲

from numpy import asarray 
bools=asarray([False,True]) 

print(bools) 
[False True] 

print(1*bools, 0+bools, 0-bools) # False, True are valued as 0, 1 
[0 1] [0 1] [ 0 -1] 

print(-2*bools, -bools*2)   # !? expected same result! :-/ 
[0 -2] [2 0] 

print(-bools)      # this is the reason! 
[True False] 

我認爲這是奇怪的是-bools返回logical_not(bools),因爲在所有其他情況下的行爲是「算術」,而不是「邏輯」 。

一個誰想要使用布爾數組作爲一個0/1面具(或「特色功能」)被強制使用某種方式漸開線表達式,如(0-bools)(-1)*bools,並且可以很容易招致成的bug,如果他忘了這個。

爲什麼會這樣,而且這將是獲得所期望的行爲最好的可以接受的方式? (旁當然評論)

+1

我不明白爲什麼有人會使用一組布爾值作爲掩碼,而不是(0,1),這更直觀,但我確實看到了一個觀點。什麼是期望的行爲雖然做-2 *假? –

+0

+在Python中一切都是合乎邏輯的。如「blabla」爲True(因此有點布爾)和一個字符串在同一時間。 –

+0

@ Ev.Kounis,當我想通過下面的代碼寫出一個延遲的指數衰減時,我偶然發現了它:delExpDecay = lambda t,d,a,tau:a * exp( - (t lurix66

回答

2

它的所有操作指令和數據類型。

>>> import numpy as np 
>>> B = np.array([0, 1], dtype=np.bool) 
>>> B 
array([False, True], dtype=bool) 

對於numpy,布爾數組被視爲該布爾數組。應用於它們的每個操作都將首先嚐試維護數據類型。也就是說方式:

>>> -B 
array([ True, False], dtype=bool) 

>>> ~B 
array([ True, False], dtype=bool) 

這是等價的,返回其元素的逐元素否定。但請注意,使用-B會引發警告,因爲該功能已棄用。

當您使用了諸如:

>>> B + 1 
array([1, 2]) 

B1首先引擎蓋相同的數據類型下鑄造。在數據類型促銷中,boolean陣列總是被鑄造爲numeric陣列。在上述情況下,B澆鑄到int,因爲其是相似的:

>>> B.astype(int) + 1 
array([1, 2]) 

在您的例子:

>>> -B * 2 
array([2, 0]) 

首先陣列B由操作者-否定,然後乘以2。期望的行爲可以通過顯式的數據變換被採用,或添加括號以確保正確操作順序:

>>> -(B * 2) 
array([ 0, -2]) 

>>> -B.astype(int) * 2 
array([ 0, -2]) 

注意B.astype(int)可以沒有數據拷貝由B.view(np.int8)取代,如布爾值由characters表示並且因此具有8位,因此可以將數據視爲整數而不需要將其轉換爲.view方法。

>>> B.view(np.int8) 
array([0, 1], dtype=int8) 

因此,簡而言之,B.view(np.int8)B.astype(yourtype)將始終ensurs即B[0,1]數字數組。

+0

謝謝您的全面解釋,特別是關於代字符〜的說明。如果我們有一個波形符號運算符,爲什麼要使用一元減號「-'作爲重複項?我更願意認爲它更符合邏輯,因爲它們在像'0 + B'或'0-B'這樣的操作中,一元加+和一元減'-'產生算術轉換。 (另見我對上述自己的問題的評論) – lurix66

+0

@ lurix66這只是一個設計決定,顯然他們對此表示遺憾,因爲它被棄用,將來會被刪除。當使用'-'作爲二元運算符'0-B'或'B-0'時,它可以正常工作(如你所期望的),問題是當你使用'-'作爲一元運算符'-B'時,被翻譯爲'-1 * B',如數值數組,它被翻譯爲'〜B'(或'not B')。同樣,在numpy決定停止支持'-'一元運算符作爲否定運算符之前,我們不能做任何事情,所以我們將不得不等待,或者同時更加小心:P –

0

numpy的陣列是同質-所有元素對於給定陣列相同的類型,並且該陣列對象存儲那是什麼類型。當您使用TrueFalse一個數組,它是bool類型的數組和經營者的行爲陣列本身上。這並不奇怪,你會得到邏輯否定發生在對正常的bool邏輯否定的情況下。當您將數組用於整數運算時,它們將轉換爲1和0。在你所有的例子中,那些更爲異常的情況,也就是說,它的行爲不應該依賴於良好的代碼。

正如評論所說,如果你想要做的數學0和1的陣列,它更好地只是讓0和1組成的數組。然而,根據你想要對他們做什麼,你可能會更好地服務於像numpy.where()這樣的功能。

+0

(請參閱我對以前的問題的評論),如果簡單,我認爲其中一個內襯很有價值。對於我來說,使用'numpy.where()'看起來不那麼簡單,而不是使用布爾值掩碼值爲1的普通明顯等價值,其中True和0爲False。 – lurix66