Alto nivel versus bajo nivel no es una cosa en blanco y negro, sino una escala continua. Los términos se usan para describir qué tan cerca está un lenguaje de programación del hardware; cuanto mayor sea el nivel, más abstrae el hardware.
El nivel más bajo, obviamente, es el código binario de la máquina: es la representación exacta que el sistema operativo carga y alimenta a la CPU. El ensamblaje es el primer nivel de abstracción construido sobre él: en lugar de código binario, uno escribe mnemoics, códigos simbólicos legibles por humanos que representan instrucciones de máquina binarias. Esto es lo que la gente usaba para la programación de sistemas antes de UNIX.
C es el siguiente paso en la cadena de abstracción, agrupando patrones comunes en construcciones de control de flujo y abstrayendo instrucciones específicas de la máquina en sintaxis independiente de la plataforma, y estas últimas abstracciones fueron uno de los principales factores que hicieron que UNIX fuera revolucionario y altamente exitoso, porque significaba que se podía compilar el mismo código para cualquier plataforma sin ningún cambio importante.
C ++ agrega otra capa de abstracciones: agrega clases (abstrayendo vtables y el contexto pasando a una sintaxis OOP) new
y delete
(agrupando la asignación de memoria y la inicialización de variables en una sola construcción), verificación de tipo en tiempo de compilación, plantillas (tiempo de compilación seguro de tipo) metaprogramación), y un montón de conveniencias de sintaxis en tiempo de compilación como espacios de nombres, sobrecarga de funciones y operadores, etc.
Python da otro gran paso lejos del hardware. C ++ todavía le da al programador un control total sobre la asignación de memoria y permite la manipulación directa de RAM; Python se encarga de la administración de la memoria por usted. Además, en lugar de compilar su código con instrucciones de máquina totalmente nativas, lo ejecuta en una máquina virtual; esto conlleva una penalización de rendimiento (que a veces puede ser considerable, pero generalmente no es algo de qué preocuparse), pero también permite cosas interesantes que serían complicadas en C ++ y terriblemente difíciles en C, como manipular funciones y clases en ejecución tiempo, obtener los nombres de objetos arbitrarios en tiempo de ejecución, instanciar clases por nombre en tiempo de ejecución, parches de mono, etc. etc.
Entonces, cuando las personas dividen los idiomas en "alto nivel" y "bajo nivel", dibujan una línea arbitraria en alguna parte, y esa línea no siempre es la misma. En 1970, la línea estaba entre el ensamblaje y C (abstrayendo las instrucciones de máquina específicas de la plataforma como factor decisivo); en 1987, pudo haber estado en algún lugar entre C y C ++; hoy, puede ser entre C ++ y Java (con la gestión automática de la memoria como factor decisivo).
Larga historia corta: el alto nivel es una escala móvil, y para los tres idiomas que mencionas es C <C ++ <Python.