7

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

4 回答 4

11

这是在函数long_longObjects/longobject.c处理的,正如 thefourtheye 更详细地解释的那样:

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

因此,当参数已经是int时,引用计数会增加并返回相同的对象。

通常,您可以为不可变类型假设类似的行为。例如,tuple(mytuple)返回对 的新引用mytuple,而相反,list(mylist)创建 的副本mylist

于 2014-02-23T09:55:11.550 回答
7

如果将int对象传递给int(),则返回相同的对象(CPython 3.3.2):

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

我不知道您所说的“算法性能差异”是什么意思,但它不会创建新对象。

于 2014-02-23T09:52:48.177 回答
6

根据源代码中的注释

将数字或字符串转换为整数,如果没有给出参数,则返回 0。如果 x 是数字,则返回x.__int__()。对于浮点数,这将截断为零。

如果 x 不是数字或给定基数,则 x 必须是字符串、字节或字节数组实例,表示给定基数中的整数文字

因此,如果输入是一个数字,__int__则会对该对象调用函数并返回结果。内部nb_int是 PyNumberMethods 结构中的一项,对应于__int__函数。根据撰写本文时的最新源代码,long_long函数对应的nb_int函数是这样定义的

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

PyLong_checkExact是一个宏,它只是检查当前对象是否真的是 long 类型。如果是真的,它只是增加引用计数并按原样返回对象,没有做任何额外的事情。

如果输入是字符串的形式,则必须将字符串转换为带有PyLong_FromUnicodeObject函数的数字。

于 2014-02-23T10:56:06.260 回答
1

为什么不直接比较两者?

>>> def f(): int('42')
... 
>>> def g(): int(42)
... 
>>> from timeit import timeit
>>> timeit(f)
0.3384080480027478
>>> timeit(g)
0.2566616949989111
于 2014-02-23T09:33:12.293 回答