2009-04-21 33 views
49

當然,0D數組是標量,但Numpy似乎並不這麼認爲......我錯過了什麼,或者我只是誤解了這個概念?爲什麼Numpy中的0d數組不考慮標量?

>>> foo = numpy.array(1.11111111111, numpy.float64) 
>>> numpy.ndim(foo) 
0 
>>> numpy.isscalar(foo) 
False 
>>> foo.item() 
1.11111111111 

回答

95

人們不應該太想它。對個人的精神健康和長壽來說,最終會更好。

與Numpy標量類型的好奇情況是由於沒有優雅和一致的方式將1x1矩陣降級爲標量類型的事實。即使在數學上它們是相同的東西,它們是由非常不同的代碼處理的。

如果你一直在做任何數量的科學代碼,最終你會希望諸如max(a)之類的東西在各種規模的矩陣上工作,甚至是標量。在數學上,這是一個非常合理的預期。然而,對於程序員來說,這意味着無論Numpy中的任何呈現標量都應該具有.shape和.ndim屬性,所以至少ufuncs不必對Numpy中21種可能的標量類型的輸入進行顯式類型檢查。

在另一方面,他們也應該與現有的Python庫,做標量型顯式的類型檢查工作。這是一個兩難的問題,因爲一個Numpy ndarray在被縮減爲一個標量時不得不單獨改變它的類型,並且如果沒有對所有訪問進行檢查,就無法知道它是否發生了。實際上,通過標量類型標準,這條路線可能會稍微慢一些。

Numpy開發人員的解決方案是從它們自己的scalary類型繼承ndarray和Python標量,以便所有標量也具有.shape,.ndim,.T等等.1x1矩陣仍然存在,但如果你知道你會處理一個標量,它的使用將會受到阻礙。雖然這在理論上應該做工精細,偶爾你仍然可以看到一些地方,他們錯過了與油漆滾筒的,醜陋內臟暴露給大家看:

>>> from numpy import * 
>>> a = array(1) 
>>> b = int_(1) 
>>> a.ndim 
0 
>>> b.ndim 
0 
>>> a[...] 
array(1) 
>>> a[()] 
1 
>>> b[...] 
array(1) 
>>> b[()] 
1 

確實沒有理由a[...]a[()]應返回不同的東西,但它確實如此。有建議可以改變這種情況,但看起來他們忘記完成1x1陣列的工作。

一個潛在的更大的,可能不可解決的問題是,Numpy標量是不可變的。因此,將一個標量「噴」到一個ndarray中,數學上來說,將一個數組摺疊成一個標量的伴隨操作是一個PITA來實現的。你不能真正長出numpy的標量,它不能被定義被丟在一個ndarray,即使newaxis神祕的作品就可以了:

>>> b[0,1,2,3] = 1 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: 'numpy.int32' object does not support item assignment 
>>> b[newaxis] 
array([1]) 

在Matlab中,越來越多標量的大小是一個完全可以接受的和愚笨操作。在Numpy中,你必須在任何地方堅持使用a = array(a)認爲你可以從標量開始並以數組結束。我明白爲什麼Numpy必須以這種方式與Python打好關係,但這並沒有改變許多新的切換器對此感到困惑的事實。有些人明確表示會爲這種行爲而掙扎,並最終堅持不懈,而其他一些遠離其他人的人通常會留下一些深邃無神的精神疤痕,而這些精神疤痕常常困擾着他們最無辜的夢想。這對所有人來說都是一個醜陋的情況。

+21

+1爲哲學介紹:-) – 2011-05-19 09:51:48

4

你有一點點不同創建標量數組:

>>> x = numpy.float64(1.111) 
>>> x 
1.111 
>>> numpy.isscalar(x) 
True 
>>> numpy.ndim(x) 
0 

它看起來像scalars in numpy可能是從你可以從純數學的角度來有點不同的概念。我猜你正在考慮用標量算法嗎?

相關問題