سؤال

Does Python's built-in function int still try to convert the submitted value even if the value is already an integer?

More concisely: is there any performance difference between int('42') and int(42) caused by conversion algorithm?

هل كانت مفيدة؟

المحلول 3

As per the comments in the source code,

Convert a number or string to an integer, or return 0 if no arguments are given. If x is a number, return x.__int__(). For floating point numbers, this truncates towards zero.

If x is not a number or if base is given, then x must be a string, bytes, or bytearray instance representing an integer literal in the given base

So, if the input is a number, __int__ function will be called on that object and the result will be returned. Internally nb_int is an item in PyNumberMethods structure, which corresponds to the __int__ function. As per the latest source code at the time of this writing, long_long is the function which corresponds to the nb_int function, which is defined like this

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

Here PyLong_checkExact is a Macro, which just checks if the current object is really of type long. If it is true, it simply increases the reference count and returns the object as it is, nothing extra is done.

If the input is in the form of a string, the string has to be converted to a number with PyLong_FromUnicodeObject function.

نصائح أخرى

This is handled in function long_long in Objects/longobject.c, as explained in more detail by thefourtheye:

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

So, when the argument is already an int, the reference count is incremented and the same object returned.

You can assume similar behavior for immutable types in general,. For example, tuple(mytuple) returns a new reference to mytuple, while, by contrast, list(mylist) creates a copy of mylist.

If you pass an int object to int(), you get the same object back (CPython 3.3.2):

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

I don't know what you mean by "algorithmic performance difference", but it doesn't create a new object.

Why don't you just compare both?

>>> def f(): int('42')
... 
>>> def g(): int(42)
... 
>>> from timeit import timeit
>>> timeit(f)
0.3384080480027478
>>> timeit(g)
0.2566616949989111
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top