2015-02-11 5 views
10

Dies ist nicht so ein Problem wie eine Kuriosität.Warum gibt es zwei np.int64s in numpy.core.numeric._typelessdata (Warum ist numpy.int64 nicht numpy.int64?)

In meinem Dolmetscher auf 64-Bit-Linux kann ich

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

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

Große ausführen, was nur ich erwarten würde. Allerdings fand ich diese seltsame Eigenschaft des numpy.core.numeric Modul

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

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

Sonderbare warum numpy.int64 dort doppelt so groß ist? Lass uns untersuchen.

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 

Whoah sind sie unterschiedlich. Was geht hier vor sich? Warum gibt es zwei np.int64's?

Antwort

4

Here sind die Linien in dem _typelessdata innerhalb numeric.py aufgebaut ist:

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

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

intc ist ein C-kompatibel (32 Bit) Ganzzahl mit Vorzeichen und int ist eine native Python ganze Zahl ist, die entweder 32-Bit oder 64-Bit sein kann, abhängig von der Plattform.

  • Auf einem 32-Bit-System die native Typ Python int ist auch 32bit, so issubclass(intc, int) kehrt True und intc-_typelessdata, angehängt wird , die wie folgt aussehen endet:

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

    Beachten Sie, dass _typelessdata[-1] is numpy.intc , nicht numpy.int32.

  • Auf einem 64-Bit-System, int ist 64bit, und deshalb issubclass(longlong, int) kehrt True und ein longlong-_typelessdata angefügt wird, was zu:

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

    In diesem Fall, wie Joe darauf hingewiesen, (_typelessdata[-1] is numpy.longlong) == True.


Die größere Frage ist, warum der Inhalt _typelessdata wie folgt festgelegt werden. Der einzige Ort, den ich in der numpy Quelle finden könnte, wo _typelessdata wird tatsächlich verwendet wird, ist this line innerhalb der Definition für np.array_repr in der gleichen Datei:

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

Der Zweck _typelessdata ist, um sicherzustellen, dass np.array_repr korrekt die Zeichenfolge druckt Darstellung von Arrays, deren dtype identisch mit dem (plattformabhängigen) nativen Python-Integertyp ist.

beispielsweise auf einem 32-Bit-System, in dem int ist 32Bit:

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

während bei einem 64-Bit-System, wo int ist 64Bit:

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

Die arr.dtype.type in _typelessdata Prüfung in der Zeile oberhalb, sicher Das Drucken der dtype wird für die entsprechende plattformabhängige native Ganzzahl dtypes übersprungen.

+0

Der Grund, warum ich darauf gestoßen bin, ist, weil ich immer wollte, dass der dtype für meine numply Strings ausgedruckt wird. Ich konnte kein Flag dafür finden, also habe ich array_repr etwas modifiziert, um ein 'force_dtype = False Flag' zu erhalten. Und dann habe ich den Check auf 'if skipdtype und nicht force_dtype:' geändert. Gibt es einen Grund, warum systemeigene Typen nicht in der Zeichenfolgendarstellung enthalten sein sollten? Ist ein Int64 wirklich anders als ein LongLong auf meinem System? Auch warum ist repr (np.longlong) = "" um mit zu beginnen? – Erotemic

+0

Ich denke, dass das Auslassen des 'dtype' aus der Zeichenfolgendarstellung von Arrays, die native Typen enthielten, wahrscheinlich nur eine stilistische Option war, um konsistent mit der Darstellung nativer Python-Skalare zu sein. Ich kann mir keine wichtigen Unterschiede zwischen einem 'np.int64' und einem' np.longlong' auf Ihrem System vorstellen, aber wie Joe erwähnte, könnte der C-Compiler auf einem anderen System ein 'long long' als etwas breiteres als 64Bits definieren , also sind die beiden Typen nicht immer unbedingt austauschbar. –

+0

Vermutlich gibt 'repr (np.longlong) == "" 'die Tatsache wieder, dass (zumindest auf Ihrem System) diese beiden Typen effektiv gleich sind. –

1

Ich weiß nicht die vollständige Geschichte dahinter, aber die zweite int64 ist eigentlich 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 soll directly correspond to C's long long type. C's long long ist spezifiziert, um mindestens 64 Bits breit zu sein, aber die genaue Definition ist dem Compiler überlassen.

Meine Vermutung ist, dass numpy.longlong Winde eine andere Instanz numpy.int64 auf den meisten Systemen ist, aber erlaubt ist, etwas anderes zu sein, wenn der C-Compiler long long als etwas breiter als 64 Bits definiert.

+1

Auf einem 32-Bit-System '_typelessdata == [numpy.int32, numpy.float64, numpy.complex128, numpy.int32]', so das letzte Element entspricht definitiv nicht auf 'numpy.longlong' –

+0

@ali_m - Das ist ein Zufall der Art, wie '_typeless_data' konstruiert wird. Siehe: https://github.com/numpy/numpy/blob/master/numpy/core/numeric.py#L1655 Auf einem 32-Bit-System lautet das letzte Element "np.intc" und "np.longlong" ist nicht in dieser Liste enthalten. –

Verwandte Themen