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?
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?
这是在函数long_long
中Objects/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
。
如果将int
对象传递给int()
,则返回相同的对象(CPython 3.3.2):
>>> a = 1000 * 1000 # large enough to avoid interning
>>> b = int(a)
>>> a is b
True
我不知道您所说的“算法性能差异”是什么意思,但它不会创建新对象。
根据源代码中的注释,
将数字或字符串转换为整数,如果没有给出参数,则返回 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
函数的数字。
为什么不直接比较两者?
>>> def f(): int('42')
...
>>> def g(): int(42)
...
>>> from timeit import timeit
>>> timeit(f)
0.3384080480027478
>>> timeit(g)
0.2566616949989111