Curso de Fundamentos para Entrevistas de Programación en Python
Un curso estructurado de Python para entrevistas de programación que cubre fundamentos del lenguaje, estructuras de datos, funciones y comprensiones, POO y excepciones, además de algoritmos y estrategia con preguntas de práctica enlazadas.
Qué aprenderás
- Explicar fundamentos de Python, mutabilidad, type hints y configuración
- Elegir y usar listas, tuplas, conjuntos, diccionarios y funciones integradas con complejidad correcta
- Escribir funciones, comprensiones, closures, decoradores y generadores eficaces
- Aplicar POO, herencia, polimorfismo, métodos especiales y manejo de excepciones
- Resolver problemas de entrevista con algoritmos comunes y estrategia repetible
Antes de empezar
- Experiencia básica de programación en cualquier lenguaje
- Familiaridad con variables, funciones y bucles
- Un entorno Python 3 o intérprete en línea para practicar
Lección 1 Fundamentos de Python y mentalidad de entrevista
En una entrevista de Python, la claridad del razonamiento importa tanto como la solución final. Los entrevistadores evalúan cómo divides un problema, qué preguntas haces y cómo explicas tus decisiones. La comunicación constante durante el proceso es una señal tan fuerte como un código correcto.
Las variables en Python son referencias a objetos, no cajas que guardan valores. La función id() revela la identidad de un objeto, y el operador is compara identidades mientras que == compara valores. Entender esta distinción evita errores sutiles con listas, diccionarios y valores por defecto.
Los tipos mutables, como list, dict y set, pueden cambiar en su lugar; los inmutables, como int, str y tuple, no. Cuando un objeto mutable se comparte entre funciones, las modificaciones son visibles en todos los lugares que lo referencian. Saber cuándo copiar con copy() o copy.deepcopy() es parte fundamental de escribir código predecible.
Las type hints, como def greet(name: str) -> str:, documentan las expectativas y ayudan a detectar errores con herramientas estáticas como mypy. Aunque Python no las aplica en tiempo de ejecución, los entrevistadores valoran su uso en las firmas de las funciones. Las anotaciones hacen que la intención del código sea explícita y más fácil de discutir.
El entorno importa: conoce la versión de Python disponible y las estructuras de datos que ofrece la biblioteca estándar. Practica en un editor con un REPL rápido para probar fragmentos de código durante la entrevista. El dominio de las herramientas básicas te permite concentrarte en el problema, no en la mecánica.
Antes de escribir la solución, reformula el problema con tus palabras y confirma los casos límite. Elige una estructura de datos con justificación y nombra el costo temporal y espacial esperado. Este patrón convierte una respuesta técnica en una conversación profesional y confiable.
Consejo de práctica Fundamentos de Python y mentalidad de entrevista: Repasa esta lección en sesiones cortas cada día. Después de cada ejercicio, di la regla o el paso que usaste; si no puedes, revisa el tema antes de continuar. La constancia fija el contenido mejor que una sesión larga.
Ejemplo
Durante una llamada de preselección, la persona entrevistadora te pide explicar qué es None y cómo evalúa Python la veracidad. Respondes que None es un objeto singleton y que los contenedores vacíos, el cero y las cadenas vacías son falsy. Luego mencionas que las comparaciones deben usar is None para mostrar un conocimiento preciso de los fundamentos de Python.
Vuelve a leer la pregunta antes de terminar y confirma el significado de tu respuesta.
Lección 2 Cómo elegir la estructura de datos adecuada
Las estructuras de datos de Python resuelven la mayoría de los problemas de entrevista sin necesidad de implementarlas desde cero. La list preserva el orden y permite acceso por índice, mientras que la tuple es inmutable y útil para datos de longitud fija. El set elimina duplicados y ofrece membresía rápida, y el dict asocia claves con valores.
Las funciones integradas potencian estas estructuras. len() devuelve la cantidad de elementos, sorted() crea una copia ordenada y enumerate() agrega índices al recorrer una secuencia. zip() combina varias secuencias en pares, y min() y max() encuentran los extremos con una clave opcional.
La complejidad temporal guía la elección: acceder a un elemento de una lista por índice toma tiempo constante, pero buscar un valor toma tiempo lineal. En un set o un dict, la membresía y la búsqueda por clave son, en promedio, constantes. Recorrer cualquier estructura de tamaño n toma tiempo lineal, lo que suele ser aceptable en una primera solución.
Elegir la estructura correcta empieza por preguntar qué operaciones se repiten. Si necesitas respuestas rápidas de presencia, un set supera a una lista. Si necesitas asociar información única a cada clave, un dict es la opción natural.
Los entrevistadores esperan que menciones los costos de las operaciones antes de implementar. Por ejemplo, insertar al final de una lista es constante en promedio, pero insertar al inicio es lineal. Usar collections.deque para operaciones en ambos extremos muestra conocimiento práctico de la biblioteca estándar.
Al comparar soluciones, explica qué estructura sacrifica memoria y cuál sacrifica tiempo. Una transformación simple, como convertir una lista en un set, suele reducir un algoritmo de O(n²) a O(n). Este tipo de razonamiento demuestra que no solo conoces la sintaxis, sino también cuándo aplicarla.
Consejo de práctica Cómo elegir la estructura de datos adecuada: Repasa esta lección en sesiones cortas cada día. Después de cada ejercicio, di la regla o el paso que usaste; si no puedes, revisa el tema antes de continuar. La constancia fija el contenido mejor que una sesión larga.
Ejemplo
Necesitas comprobar pertenencia con frecuencia sobre una lista que puede contener cientos de miles de elementos. Cambias a un set para que item in seen se ejecute en tiempo constante y explicas que esto es una búsqueda basada en hash. También mencionas que, si hace falta conservar el orden, debes usar un dict o una lista según las restricciones.
Vuelve a leer la pregunta antes de terminar y confirma el significado de tu respuesta.
Lección 3 Funciones, comprehensiones y generadores
Las funciones son la unidad básica para organizar una solución. Los parámetros posicionales y con nombre definen la interfaz, y los valores por defecto hacen que los argumentos opcionales sean explícitos. Las firmas claras comunican la intención sin necesidad de comentarios extensos.
*args recolecta argumentos posicionales adicionales en una tupla, y **kwargs recolecta argumentos con nombre en un diccionario. Estos parámetros son útiles para envoltorios, decoradores y funciones que delegan en otras funciones. Al usarlos, mantén los nombres significativos para que la flexibilidad no oscurezca el propósito.
El ámbito determina qué nombres ve cada parte del código. Una variable definida en una función no existe fuera de ella, y nonlocal permite modificar una variable de un ámbito envolvente. Los cierres recuerdan ese ámbito incluso después de que la función externa haya terminado, lo que habilita fábricas de funciones y estado privado.
Los decoradores envuelven funciones para agregar comportamiento sin repetir código. Un decorador simple recibe una función, devuelve otra y se aplica con la sintaxis @timer. Son ideales para registro, autenticación y medición de tiempos, y suelen aparecer en entrevistas avanzadas.
Las comprensiones construyen colecciones de forma concisa. Una lista por comprensión como [x * x for x in nums if x > 0] reemplaza un bucle completo, y la misma idea se aplica a dict y set. La legibilidad debe guiar su uso: si la expresión se vuelve compleja, un bucle explícito es mejor.
Los generadores producen valores bajo demanda con yield y evalúan de forma perezosa. Al no materializar toda la secuencia en memoria, permiten procesar flujos grandes o infinitos con un costo predecible. Reconocer cuándo una comprensión es suficiente y cuándo un generador es necesario demuestra madurez en el lenguaje.
Consejo de práctica Funciones, comprehensiones y generadores: Repasa esta lección en sesiones cortas cada día. Después de cada ejercicio, di la regla o el paso que usaste; si no puedes, revisa el tema antes de continuar. La constancia fija el contenido mejor que una sesión larga.
Ejemplo
La persona entrevistadora te pide transformar una lista de IDs de usuario en nombres en minúsculas sin construir una lista intermedia enorme. Escribes names = (name.lower() for name in users) y explicas que una expresión generadora produce valores de forma perezosa. La comparas con una comprensión de lista y destacas que el uso de memoria es la principal compensación.
Vuelve a leer la pregunta antes de terminar y confirma el significado de tu respuesta.
Lección 4 POO y manejo de excepciones en entrevistas
Las clases organizan datos y comportamiento en una sola unidad. El método __init__ inicializa los atributos de cada instancia, y los atributos de clase se comparten entre todas las instancias. Definir los atributos con claridad evita confusiones entre estado compartido y estado particular.
La herencia permite reutilizar y especializar comportamiento: una subclase hereda métodos de su superclase y puede sobrescribirlos. El polimorfismo hace que objetos de clases distintas respondan a los mismos mensajes. Un código que depende de interfaces, no de tipos concretos, es más fácil de extender y probar.
Los métodos dunder, como __repr__, __eq__ y __len__, integran los objetos con la sintaxis de Python. Implementar __eq__ junto con __hash__ es necesario para usar instancias en conjuntos y diccionarios. Estos métodos convierten una clase en un ciudadano de primera clase del lenguaje.
El manejo de excepciones separa el flujo normal del flujo de error. La estructura try/except captura errores específicos, else ejecuta código cuando no hubo excepción y finally garantiza la limpieza en todos los casos. Capturar solo las excepciones que sabes manejar evita ocultar errores reales.
raise lanza una excepción cuando una condición hace imposible continuar. Las excepciones personalizadas, que heredan de Exception, permiten nombrar situaciones propias del dominio. Al crearlas, mantén los mensajes útiles y captura la excepción específica en lugar de Exception o BaseException.
En las entrevistas, los ejemplos de OOP suelen evaluar decisiones de diseño, no solo sintaxis. Explica por qué eliges herencia en lugar de composición y qué responsabilidades tiene cada clase. Las excepciones, por su parte, demuestran que piensas en los caminos de error antes de que ocurran.
Consejo de práctica POO y manejo de excepciones en entrevistas: Repasa esta lección en sesiones cortas cada día. Después de cada ejercicio, di la regla o el paso que usaste; si no puedes, revisa el tema antes de continuar. La constancia fija el contenido mejor que una sesión larga.
Ejemplo
Tu solución debe cargar perfiles de usuario desde una API remota y reintentar cuando falla la red. Defines una subclase personalizada RetryableError y envuelves la llamada en un bloque try/except que registra el fallo. Explicas que los tipos de excepción específicos hacen que el contrato de la clase sea más claro y más fácil de probar.
Vuelve a leer la pregunta antes de terminar y confirma el significado de tu respuesta.
Lección 5 Algoritmos, complejidad y estrategia de entrevista
El análisis de complejidad es el idioma común de las entrevistas de algoritmos. La notación Big O describe cómo crece el tiempo o la memoria cuando aumenta el tamaño de la entrada. Antes de codificar, propone una complejidad esperada y confirma que el entrevistador la considera razonable.
Varios patrones resuelven una gran parte de los problemas. Dos punteros recorren una secuencia desde ambos extremos, el hashing convierte búsquedas lineales en consultas constantes y la ventana deslizante procesa subarreglos contiguos en una sola pasada. Reconocer estos patrones te ahorra tiempo y muestra experiencia.
Ordenar es a menudo el primer paso que simplifica un problema, incluso cuando la ordenación misma no es el objetivo. La recursión descompone un problema en versiones más pequeñas de sí mismo y requiere un caso base claro. Cuando uses recursión, menciona el caso base y la posibilidad de memoización para evitar trabajo repetido.
La comunicación hace visible tu proceso de pensamiento. Lee el código en voz alta mientras escribes, explica cada bloque y nombra las decisiones importantes. Un entrevistador que entiende tu razonamiento puede ayudarte con sugerencias antes de que pierdas demasiado tiempo.
Probar casos límite distingue una solución completa de una que solo funciona con el ejemplo. Prueba con entradas vacías, un solo elemento, valores repetidos, negativos y los límites del enunciado. Verifica también invariantes simples, como que la salida conserve el orden o el tamaño esperado.
Un flujo repetible organiza la entrevista: resolver, explicar y refinar. Primero plantea un enfoque en voz alta, después impleméntalo de forma clara y finalmente mejora la complejidad si el tiempo lo permite. Este método reduce los nervios y convierte cada entrevista en una demostración consistente de tu proceso.
Consejo de práctica Algoritmos, complejidad y estrategia de entrevista: Repasa esta lección en sesiones cortas cada día. Después de cada ejercicio, di la regla o el paso que usaste; si no puedes, revisa el tema antes de continuar. La constancia fija el contenido mejor que una sesión larga.
Ejemplo
Dados dos arreglos ordenados, empiezas afirmando que una fusión por fuerza bruta es O(n log n) y que una fusión con dos punteros puede llegar a O(n). Repasas los invariantes del bucle antes de codificar, lo que demuestra un pensamiento algorítmico estructurado. Luego resumes la compensación entre complejidad temporal y simplicidad del código para la persona entrevistadora.
Vuelve a leer la pregunta antes de terminar y confirma el significado de tu respuesta.