Una f-string evalúa la expresión entre llaves y mete el resultado en el texto. Es más rápida que % y .format(), y se lee en el orden en que piensas.
Una comprensión construye una lista a partir de un bucle en una sola expresión. No es solo más corta: también es más rápida que ir agregando dentro de un bucle.
Un asterisco delante de un parámetro junta los argumentos posicionales que sobran en una tupla. Dos asteriscos juntan los argumentos por palabra clave que sobran en un diccionario.
Un decorador es una función que toma una función y devuelve un reemplazo. La línea con @ es la forma corta de reasignar el nombre.
== pregunta si dos objetos tienen el mismo valor. is pregunta si son el mismo objeto en memoria. Coinciden lo bastante seguido como para que usar el equivocado casi siempre funcione.
Asignar una lista a un segundo nombre no copia nada. Copiar tiene dos niveles, y el superficial se detiene justo donde suelen estar tus datos anidados.
Un argumento por defecto se evalúa una sola vez, cuando se define la función. Si ese valor es una lista o un diccionario, todas las llamadas comparten el mismo objeto.
Una dataclass escribe por ti los métodos aburridos. Declaras los campos con anotaciones de tipo y el decorador genera __init__, __repr__ y __eq__.
with existe para que la limpieza ocurra pase lo que pase en el cuerpo. Salgas antes, lances una excepción o termines normal, el código de salida corre igual.
Contar cosas, agruparlas y mantener una cola son tres bucles que casi todo el mundo escribe a mano. El módulo collections ya tiene los tres.
La mayoría de quienes programan en Python usa f-strings todos los días y conoce como una quinta parte de lo que hacen. Esta es la otra cuatro quintas partes.