2015-02-11 30 views
10

這不是太大的問題的好奇心。爲什麼在numpy.core.numeric._typelessdata 2個np.int64s(爲什麼不numpy.int64 numpy.int64?)

在我的64位Linux解釋我可以執行

In [10]: np.int64 == np.int64 
Out[10]: True 

In [11]: np.int64 is np.int64 
Out[11]: True 

太好了,正是我所期望的。 但是我發現numpy.core.numeric模塊

In [19]: from numpy.core.numeric import _typelessdata 

In [20]: _typelessdata 
Out[20]: [numpy.int64, numpy.float64, numpy.complex128, numpy.int64] 

古怪的這種怪異的財產爲什麼numpy.int64在那裏兩次?讓我們調查。

In [23]: _typelessdata[0] is _typelessdata[-1] 
Out[23]: False 
In [24]: _typelessdata[0] == _typelessdata[-1] 
Out[24]: False 
In [25]: id(_typelessdata[-1]) 
Out[25]: 139990931572128 
In [26]: id(_typelessdata[0]) 
Out[26]: 139990931572544 
In [27]: _typelessdata[-1] 
Out[27]: numpy.int64 
In [28]: _typelessdata[0] 
Out[28]: numpy.int64 

哇他們是不同的。這裏發生了什麼?爲什麼有兩個np.int64?

回答

4

Here是其中內numeric.py構造_typelessdata行:整數簽署

_typelessdata = [int_, float_, complex_] 
if issubclass(intc, int): 
    _typelessdata.append(intc) 

if issubclass(longlong, int): 
    _typelessdata.append(longlong) 

intc是C兼容的(32位),和int是一個本機Python 整數,它可以是32位或64位取決於平臺。

  • 在32位系統的本機Python int類型也是32位,所以 issubclass(intc, int)回報Trueintc被附加到_typelessdata, 這最終看起來像這樣:

    [numpy.int32, numpy.float64, numpy.complex128, numpy.int32] 
    

    注意_typelessdata[-1] is numpy.intc ,而不是numpy.int32

  • 在64位系統,int是64位,因此issubclass(longlong, int)返回Truelonglong被附加到_typelessdata,導致:

    [numpy.int64, numpy.float64, numpy.complex128, numpy.int64] 
    

    在這種情況下,如喬指出,(_typelessdata[-1] is numpy.longlong) == True


更大的問題是,爲什麼_typelessdata內容設置這樣。 我能找到在實際使用_typelessdata 的numpy的來源只有一個地方是this line定義範圍內的np.array_repr 在同一個文件:

skipdtype = (arr.dtype.type in _typelessdata) and arr.size > 0 

_typelessdata的目的是爲了確保np.array_repr正確打印字符串表示其dtype恰好與(平臺相關)本機Python整數類型相同的數組的表示。

例如,一個32位的系統上,其中int是32位:

In [1]: np.array_repr(np.intc([1])) 
Out[1]: 'array([1])' 

In [2]: np.array_repr(np.longlong([1])) 
Out[2]: 'array([1], dtype=int64)' 

而一個64位的系統,其中int是在64位:

In [1]: np.array_repr(np.intc([1])) 
Out[1]: 'array([1], dtype=int32)' 

In [2]: np.array_repr(np.longlong([1])) 
Out[2]: 'array([1])' 

arr.dtype.type in _typelessdata檢查在上述確保線打印dtype會跳過適當的平臺相關本機整數dtypes

+0

所以我遇到這個問題的原因是因爲我一直希望打印出我的numpy字符串的dtype。我無法找到它的標誌,所以我最終稍微修改了array_repr來採取'force_dtype = False標誌'。然後我改變了檢查'如果skipdtype而不是force_dtype:'。是否有原因爲什麼本地類型不應該在字符串表示中?在我的系統上,int64與longlong是否真的不同?爲什麼是repr(np.longlong)=「」開頭? – Erotemic 2015-02-11 20:28:22

+0

我猜想,從包含本機類型的數組的字符串表示中省略'dtype'可能只是一種與本機Python標量表示方式一致的樣式選擇。我想不出你的系統上的'np.int64'和'np.longlong'之間有什麼重要區別,但是正如Joe所說的,在另一個系統上,C編譯器可能會將long long定義爲比64bits更寬的東西,所以這兩種類型可能並不總是完全可以互換的。 – 2015-02-11 20:43:35

+0

推測,'repr(np.longlong)==「」'反映了(至少在你的系統上)這兩種類型實際上是相同的事實。 – 2015-02-11 20:46:51

1

我不知道全部的歷史背後,但第二int64實際上是numpy.longlong

In [1]: import numpy as np 

In [2]: from numpy.core.numeric import _typelessdata 

In [3]: _typelessdata 
Out[4]: [numpy.int64, numpy.float64, numpy.complex128, numpy.int64] 

In [5]: id(_typelessdata[-1]) == id(np.longlong) 
Out[5]: True 

numpy.longlong應該directly correspond to C's long long type。 C的long long被指定爲至少64位寬,但確切的定義由編譯器決定。

我的猜測是numpy.longlong卷取是在大多數系統的numpy.int64另一實例中,但是被允許爲不同的東西如果C編譯long long定義爲東西比64個比特寬。

+1

在32位系統上'_typelessdata == [numpy.int32,numpy.float64,numpy.complex128,numpy.int32]',所以最後一個元素絕對不對應'numpy.longlong' – 2015-02-11 18:05:36

+0

@ali_m - 這就是這是'_typeless_data'構造方式的巧合。請參閱:https://github.com/numpy/numpy/blob/master/numpy/core/numeric.py#L1655在32位系統上,最後一項是'np.intc','np.longlong'不包含在該列表中。 – 2015-02-11 18:11:50