Función int de Python

¿Intenta la función incorporada de Python intentar convertir el valor enviado incluso si el valor ya es un entero?

Más concisamente: ¿hay alguna diferencia de rendimiento entre int('42') e int(42) causada por el algoritmo de conversión?

Según los comentarios en el código fuente ,

Convierta un número o una cadena en un entero, o devuelva 0 si no se proporcionan argumentos. Si x es un número, devuelva x.__int__ (). Para los números de punto flotante, esto se trunca hacia cero.

Si x no es un número o si se proporciona una base, entonces x debe ser una cadena, bytes o instancia de bytearray que representa un literal entero en la base dada

Por lo tanto, si la entrada es un número, se __int__ función __int__ en ese objeto y se devolverá el resultado. Internamente nb_int es un elemento en la estructura de PyNumberMethods , que corresponde a la función __int__ . Según el último código fuente en el momento de esta escritura, long_long es la función que corresponde a la función nb_int , que se define así:

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

Aquí PyLong_checkExact es una macro, que solo verifica si el objeto actual es realmente de tipo largo. Si es cierto, simplemente aumenta el recuento de referencias y devuelve el objeto tal como está, no se hace nada adicional.

Si la entrada tiene la forma de una cadena, la cadena debe convertirse en un número con la función PyLong_FromUnicodeObject .

Esto se maneja en la función long_long en Objects/longobject.c , como se explica con más detalle en los long_long Objects/longobject.c :

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

Entonces, cuando el argumento ya es un int , el recuento de referencia se incrementa y se devuelve el mismo objeto.

Puedes asumir un comportamiento similar para tipos inmutables en general ,. Por ejemplo, tuple(mytuple) devuelve una nueva referencia a mytuple , mientras que, por el contrario, list(mylist) crea una copia de mylist .

Si pasas un objeto int a int() , obtienes el mismo objeto (CPython 3.3.2):

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

No sé qué quiere decir con “diferencia de rendimiento algorítmico”, pero no crea un nuevo objeto.

¿Por qué no comparas ambos?

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