2014-02-23 14 views
7

Funktioniert Python-integrierte Funktion int immer noch versuchen, den übergebenen Wert zu konvertieren, auch wenn der Wert bereits eine ganze Zahl ist?Python Int-Funktion Leistung

Konkreter: gibt es einen Leistungsunterschied zwischen int('42') und int(42) verursacht durch Umrechnungsalgorithmus?

+0

'int' literal ist eigentlich eine Zeichenfolge ohne Anführungszeichen. Diese Konvertierung wird während der Kompilierung durchgeführt (also während der ersten Verarbeitung des Quellcodes). Das 'int'-Objekt des Pythons muss in beiden Fällen konstruiert sein. Da Python keine Maschine 'int' verwendet, sollte die Komplexität in beiden Fällen ähnlich sein. – pepr

Antwort

5

Gemäß den comments in the source code,

Konvertieren einer Zahl oder Zeichenkette in einer ganzen Zahl oder 0 zurück, wenn keine Argumente gegeben sind. Wenn x eine Zahl ist, geben Sie x.__int__() zurück. Für Gleitkommazahlen schneidet dies in Richtung Null ab.

Wenn x keine Zahl ist, oder wenn Base gegeben ist, dann muß x eine Zeichenfolge sein, Bytes oder bytearray weise ein ganzzahliges Literal in der gegebenen Basisrepräsentiere

Also, wenn der Eingang Eine Nummer, __int__ Funktion wird für dieses Objekt aufgerufen und das Ergebnis wird zurückgegeben. Intern nb_int is an item in PyNumberMethods structure, was der __int__ Funktion entspricht. Gemäß der neuesten Quellcode zum Zeitpunkt des Schreibens dieses Artikels, long_long is the function which corresponds to the nb_int function, die wie diese

long_long(PyObject *v) 
{ 
    if (PyLong_CheckExact(v)) 
     Py_INCREF(v); 
    else 
     v = _PyLong_Copy((PyLongObject *)v); 
    return v; 
} 

Hier PyLong_checkExact ist ein Makro definiert ist, das, wenn sie nur überprüft das aktuelle Objekt wirklich vom Typ ist lang. Wenn es wahr ist, erhöht es einfach die Referenzzählung und gibt das Objekt zurück, so wie es ist, nichts ist mehr getan.

Wenn die Eingabe in Form einer Zeichenfolge erfolgt, muss die Zeichenfolge in eine Zahl mit der Funktion PyLong_FromUnicodeObject konvertiert werden.

1

Warum vergleichen Sie nicht beide?

>>> def f(): int('42') 
... 
>>> def g(): int(42) 
... 
>>> from timeit import timeit 
>>> timeit(f) 
0.3384080480027478 
>>> timeit(g) 
0.2566616949989111 
+2

@Crystal Dies hängt von der Implementierung ab, die Sie verwenden, oder von Ihrem Endbenutzer verwendet wird. – Hyperboreus

6

Falls Sie ein int Objekt int() passieren, erhalten Sie das gleiche Objekt zurück (CPython 3.3.2):

>>> a = 1000 * 1000 # large enough to avoid interning 
>>> b = int(a) 
>>> a is b 
True 

Ich weiß nicht, was Sie unter "algorithmische Performance-Unterschied" bedeuten , aber es erstellt kein neues Objekt.

+0

Keine Entschuldigung, das ist die bessere Antwort – jonrsharpe

10

Dies ist in Funktion long_long in Objects/longobject.c behandelt, wie im Detail durch thefourtheye erklärt:

static PyObject * 
long_long(PyObject *v) 
{ 
    if (PyLong_CheckExact(v)) 
     Py_INCREF(v); 
    else 
     v = _PyLong_Copy((PyLongObject *)v); 
    return v; 
} 

Also, wenn das Argument bereits ein int ist, wird der Referenzzähler erhöht und wieder das gleiche Objekt.

Sie können ein ähnliches Verhalten für unveränderliche Typen im Allgemeinen annehmen. Beispielsweise gibt tuple(mytuple) einen neuen Verweis auf mytuple zurück, während list(mylist) dagegen eine Kopie von mylist erstellt.

+0

Obwohl dies der tatsächlichen Funktion fast ähnelt, ist dies in der Tat eine interne Hilfsfunktion. – thefourtheye

+0

@thefourtheye Sie haben Recht, bearbeitet. –