Python's int function performance

2019-06-17 06:08发布

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?

4条回答
干净又极端
2楼-- · 2019-06-17 06:24

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.

查看更多
我想做一个坏孩纸
3楼-- · 2019-06-17 06:28

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.

查看更多
We Are One
4楼-- · 2019-06-17 06:33

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
查看更多
淡お忘
5楼-- · 2019-06-17 06:37

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.

查看更多
登录 后发表回答