▷ Preguntas de entrevista de Python — 20 que más caen (con respuestas) 2026

Preguntas de entrevista de Python — 20 que más caen (con respuestas)

Llevo desde 2018 a los dos lados de la mesa en entrevistas técnicas de Python: como candidato y, cada vez más, entrevistando a otros. Y hay un patrón claro. Las mismas preguntas caen una y otra vez. No porque los entrevistadores no tengan imaginación, sino porque destilan muy bien quién entiende Python de verdad y quién lo ha copiado de Stack Overflow.

Aquí tienes las 20 que más se repiten, agrupadas por bloques, con respuestas que puedes decir en voz alta y código que se ejecuta tal cual. No las memorices como un loro: entiéndelas. En la entrevista se nota la diferencia.

Si todavía estás decidiendo a qué perfil tirar (backend, data, IA…), antes lee salidas profesionales de Python — te ahorra prepararte para el puesto equivocado.

Bloque 1 — Conceptos que SIEMPRE caen

Estas son las de calentamiento. Si fallas una de estas, la entrevista se acaba antes de empezar.

1. ¿Diferencia entre is y ==?

== compara valores: ¿son iguales? is compara identidad: ¿son el mismo objeto en memoria?

a = [1, 2, 3]
b = [1, 2, 3]

print(a == b)   # True  -> mismo contenido
print(a is b)   # False -> objetos distintos

Regla práctica: usa == para comparar valores y is solo con None, True y False (if x is None:). La trampa con enteros pequeños la vemos en el bloque 3.

2. ¿Listas vs tuplas?

La lista es mutable (puedes cambiarla); la tupla es inmutable (no). Por eso una tupla puede ser clave de un diccionario y una lista no.

coordenadas = (40.4, -3.7)   # no va a cambiar -> tupla
historial = [40.4, -3.7]     # va creciendo  -> lista

posiciones = {(0, 0): "origen"}   # tupla como clave: OK
# posiciones = {[0, 0]: "origen"} # TypeError: unhashable type: 'list'

Buena respuesta extra: las tuplas señalan intención (“esto no debería cambiar”) y son ligeramente más eficientes.

3. ¿Qué es mutable e inmutable en Python?

Inmutables: int, float, str, tuple, frozenset, bool. Mutables: list, dict, set, y los objetos de tus clases por defecto.

Importa porque cambia cómo se pasan a las funciones: con un mutable, la función puede modificar el original.

def añadir(lista):
    lista.append(99)   # modifica el original

datos = [1, 2]
añadir(datos)
print(datos)   # [1, 2, 99]

4. ¿Qué son *args y **kwargs?

*args recoge argumentos posicionales extra en una tupla; **kwargs, los nombrados en un diccionario. Sirven para escribir funciones que aceptan un número variable de argumentos.

def registrar(*args, **kwargs):
    print(args)     # (1, 2)
    print(kwargs)   # {'nivel': 'INFO'}

registrar(1, 2, nivel="INFO")

Si quieres la guía a fondo: *args y **kwargs explicados.

5. ¿Qué es una list comprehension y cuándo NO usarla?

Una forma compacta de construir una lista. Es más rápida y legible que un for con append… hasta que deja de serlo.

cuadrados = [n * n for n in range(10) if n % 2 == 0]

La respuesta que impresiona: “La uso cuando cabe en una línea y se lee de un vistazo. Si tiene dos for anidados y tres condiciones, vuelvo al bucle normal: la legibilidad gana.” Más detalle en list comprehensions.

6. ¿append vs extend?

append añade un elemento (aunque sea una lista entera). extend añade cada elemento de un iterable.

a = [1, 2]
a.append([3, 4])   # [1, 2, [3, 4]]

b = [1, 2]
b.extend([3, 4])   # [1, 2, 3, 4]

7. ¿Cómo funciona el slicing?

secuencia[inicio:fin:paso]. fin no se incluye. Los índices negativos cuentan desde el final.

texto = "Python"
print(texto[1:4])    # 'yth'
print(texto[::-1])   # 'nohtyP'  -> invertir
print(texto[-2:])    # 'on'

El truco [::-1] para invertir cae mucho.

Bloque 2 — Estructuras de datos y rendimiento

Aquí es donde un junior y alguien con criterio empiezan a separarse. No basta con conocer la sintaxis: hay que saber qué cuesta cada operación.

8. ¿Por qué buscar en un set o dict es O(1) y en una lista O(n)?

Porque set y dict son tablas hash: calculan dónde está el elemento directamente. La lista tiene que recorrer elemento a elemento.

nombres_lista = ["ana", "luis", "marta"]   # "marta" in lista -> O(n)
nombres_set = {"ana", "luis", "marta"}     # "marta" in set   -> O(1)

Si vas a comprobar pertenencia muchas veces sobre datos grandes, convertir a set primero es la diferencia entre milisegundos y minutos. Tienes el desglose completo en Big-O en Python para entrevistas.

9. ¿Cuándo usar un set?

Dos casos estrella: eliminar duplicados y comprobar pertenencia rápido.

emails = ["a@x.com", "b@x.com", "a@x.com"]
unicos = list(set(emails))   # sin duplicados

10. ¿Qué es un diccionario por dentro?

Una tabla hash: cada clave se pasa por una función hash que decide dónde se guarda. Por eso las claves deben ser hashables (inmutables) y por eso el acceso es tan rápido. Desde Python 3.7, además, mantienen el orden de inserción.

11. collections: Counter, defaultdict, deque

Conocer el módulo collections señala experiencia real:

from collections import Counter, defaultdict, deque

Counter("banana")          # Counter({'a': 3, 'n': 2, 'b': 1})

grupos = defaultdict(list)
grupos["frutas"].append("pera")   # sin comprobar si la clave existe

cola = deque([1, 2, 3])
cola.appendleft(0)         # O(1) por ambos extremos (una lista no)

Bloque 3 — Las trampas que descartan candidatos

Estas son las preguntas con “truco”. No buscan que las sepas de memoria: buscan ver si entiendes cómo funciona Python por dentro.

12. El argumento mutable por defecto (la pregunta trampa nº 1)

def añadir(item, lista=[]):
    lista.append(item)
    return lista

print(añadir(1))   # [1]
print(añadir(2))   # [1, 2]  <- ¡sorpresa!

El valor por defecto se evalúa una sola vez, al definir la función, no en cada llamada. Así que todas comparten la misma lista. La solución correcta:

def añadir(item, lista=None):
    if lista is None:
        lista = []
    lista.append(item)
    return lista

Si respondes esta bien, subes un escalón inmediato.

13. Late binding en closures (el clásico del bucle)

funciones = [lambda: i for i in range(3)]
print([f() for f in funciones])   # [2, 2, 2]  <- no [0, 1, 2]

Las lambdas capturan la variable i, no su valor en ese momento. Cuando se ejecutan, i ya vale 2. Solución: fijar el valor con un argumento por defecto.

funciones = [lambda i=i: i for i in range(3)]
print([f() for f in funciones])   # [0, 1, 2]

14. Copia superficial vs copia profunda

import copy

original = [[1, 2], [3, 4]]
superficial = original.copy()        # copia la lista externa, no las internas
profunda = copy.deepcopy(original)   # copia todo, en todos los niveles

original[0][0] = 99
print(superficial)   # [[99, 2], [3, 4]]  <- afectada
print(profunda)      # [[1, 2], [3, 4]]   <- intacta

15. is con enteros pequeños

a = 256; b = 256
print(a is b)   # True  -> Python cachea -5..256

a = 257; b = 257
print(a is b)   # False (normalmente) -> fuera del caché

La moraleja no es memorizar el rango: es “por eso nunca comparo números con is, uso ==. Eso es lo que el entrevistador quiere oír.

📥 Llévate el cheatsheet de Python (gratis)

PDF de 6 páginas con lo esencial: tipos, condicionales, bucles, estructuras de datos, funciones y los errores que más vas a cometer. Para tener al lado mientras programas.

Sin spam. Te apuntas a la lista, descargas el cheatsheet y recibes contenido de Python cada semana.

Bloque 4 — Para subir de nivel (intermedio/senior)

16. ¿Qué es un generador y yield?

Una función que produce valores uno a uno, sin construir toda la lista en memoria. Ideal para datos grandes o infinitos.

def numeros():
    n = 0
    while True:
        yield n        # pausa aquí y devuelve n
        n += 1

La frase ganadora: “Una list comprehension materializa todo en memoria; un generador es perezoso y solo calcula el siguiente cuando se lo pides.” Profundiza en generadores y yield.

17. ¿Qué es un decorador?

Una función que recibe otra función y devuelve una versión envuelta, sin tocar el original. El @ es solo azúcar sintáctico.

@medir_tiempo
def procesar():
    ...
# equivale a: procesar = medir_tiempo(procesar)

Los ves por todos lados: @app.route, @property, @pytest.fixture. Guía completa: decoradores explicados.

18. ¿Qué es el GIL? ¿Threads o procesos?

El GIL (Global Interpreter Lock) hace que en CPython solo un hilo ejecute bytecode Python a la vez. Consecuencia práctica:

  • Tareas I/O-bound (red, disco): los threads sí ayudan (el GIL se libera esperando).
  • Tareas CPU-bound (cálculo puro): los threads NO aceleran; usa multiprocessing o asyncio según el caso.

Si quieres entender el “Python es lento” que hay detrás: ¿por qué Python es lento?.

19. ¿Duck typing? ¿EAFP vs LBYL?

Duck typing: “si camina como un pato y hace cuac, es un pato” — importa lo que un objeto hace, no su tipo. De ahí el estilo EAFP (easier to ask forgiveness than permission), idiomático en Python:

# EAFP (pythónico)
try:
    valor = config["clave"]
except KeyError:
    valor = "por defecto"

# LBYL (menos pythónico aquí)
if "clave" in config:
    valor = config["clave"]
else:
    valor = "por defecto"

20. ¿Cómo manejas excepciones? try/except/else/finally

try:
    f = abrir_archivo()
except FileNotFoundError:
    print("No existe")
else:
    print("Todo bien")    # solo si NO hubo excepción
finally:
    print("Siempre se ejecuta")   # limpieza

La buena práctica que valoran: captura excepciones concretas, no un except: pelado que se traga hasta los errores de teclado.

Cómo prepararte el resto (no solo memorizar)

Saber las respuestas es el 50%. El otro 50% es resolver el ejercicio en vivo y explicar tu razonamiento en voz alta sin quedarte en blanco. Eso se entrena aparte:

Y si quieres llevarte todo esto en una hoja para repasar el día antes, descárgate el cheatsheet (justo aquí abajo).

En resumen

Las entrevistas de Python repiten patrones: conceptos base (is/==, mutabilidad), estructuras de datos con su coste, las trampas clásicas (argumento mutable por defecto, late binding) y un par de temas senior (GIL, generadores). Si entiendes el porqué de cada una —no solo la respuesta— vas a transmitir criterio, que es justo lo que se evalúa.

Todo lo que has visto aquí (y más) está explicado paso a paso, con proyectos reales, en el curso. Si quieres pasar de “sé responder preguntas sueltas” a “domino Python para trabajar de esto”, ese es el camino.

¿Quieres aprender Python en orden, no a saltos?

Esto que has leído es solo una pieza. En El Pythonista lo verás todo encadenado: 11 módulos, 37+ horas de vídeo, 734 actividades y un proyecto real (MovieTracker) que crece contigo desde la primera variable hasta el deploy a producción.

Ver el curso completo →

37+ horas · 734 actividades · Proyecto real · Acceso de por vida · 14 días de garantía

Compartir