Dos conceptos podrían ayudarnos a comprender mejor por qué Python compilado en código máquina nativo "puede" no ejecutarse tan rápido como C compilado u otros lenguajes compilados comúnmente. Se llaman unión temprana y unión tardía.
Debería comenzar diciendo que no soy un experto en Python, y vine a este sitio por accidente. Pero me gusta este sitio.
Como se mencionó en otra respuesta aquí, el compilador de C ++ puede saber mucho sobre el programa y tomar decisiones sobre qué operaciones usar para estructuras de datos específicas. Como ejemplo, si se deben agregar dos variables enteras, el compilador sabe que son enteros nativos, de 32 bits de ancho, por ejemplo, y puede agregarlos junto con una instrucción "ADD". Por lo tanto, compila la instrucción ADD en el código. Está bloqueado y no se puede cambiar mientras el programa se está ejecutando. Eso es vinculante temprano.
Por otro lado, en un lenguaje como Python, podríamos esperar que el programa arroje diferentes tipos de datos juntos de formas complejas. Ahora el compilador no sabe si nuestras 2 variables son enteros, flotantes, cadenas o listas. Por lo tanto, tiene que compilar el código que determina esa información en tiempo de ejecución y seleccionar la operación correcta mientras se ejecuta el programa. Esto es vinculante tarde y podemos entender que habrá un impacto en el rendimiento por hacer ese trabajo adicional mientras se ejecuta el programa. Es el precio que paga por mantener abiertas esas opciones en un lenguaje como Python, pero proporciona la máxima flexibilidad de tiempo de ejecución.