¿Cómo funciona la parametrización de consultas SQL?

Me siento un poco tonta por preguntar esto, ya que parece que soy la única persona en el mundo que no lo entiende, pero aquí va de todos modos. Voy a usar Python como ejemplo. Cuando uso consultas de SQL sin procesar (normalmente uso ORM), uso parametrización, como en este ejemplo que usa SQLite:

Método A:

username = "wayne"
query_params = (username)
cursor.execute("SELECT * FROM mytable WHERE user=?", query_params)

Sé que esto funciona y sé que esta es la forma generalmente recomendada de hacerlo. Una forma vulnerable a la inyección de SQL para hacer lo mismo sería algo como esto:

Método B:

username = "wayne"
cursor.execute("SELECT * FROM mytable WHERE user='%s'" % username)

Por lo que sé, entiendo que la inyección SQL, como se explica eneste artículo de Wikipedia. Mi pregunta es simple: ¿en qué se diferencia el método A del método B? ¿Por qué el resultado final del método A no es el mismo que el método B? Supongo que elcursor.execute() El método (que forma parte de la especificación DB-API de Python) se encarga de que la entrada se escape y se compruebe correctamente, pero esto nunca se establece explícitamente en ninguna parte. ¿Es eso todo lo que la parametrización en este contexto es? Para mí, cuando decimos "parametrización", todo lo que significa es "sustitución de cadenas", como% de formato. ¿Eso es incorrecto?