IDS Guía de estudio

Semana 12 · Evaluación de fin de ciclo

Repaso y Examen Final

Última semana: examen integral de lógica en Python y fundamentos de C#. Aquí tienes el mapa de todo el curso, los errores más comunes de la segunda mitad, un simulacro teórico y un problema resuelto en los dos lenguajes.

Pregunta orientadora¿Puedo resolver un problema de negocio completo y expresar la misma solución en Python y en C#?

Lecturas
Repaso de todo el ciclo
Proyecto
Proyecto entregado (v1.0)
Evaluación
Examen Final (esta semana)

Cómo usar esta semana

Esta semana es el Examen Final Integral: evaluación individual de lógica en Python y fundamentos formales de C#, sin IA. El temario exacto lo confirma el docente en Moodle.

6 días antesSimulacro teórico sin apuntes. Clasifica tus errores: ¿Python básico, estructuras, objetos o C#?
4 días antesRepasa las semanas débiles: sus trazas y listas “puedo…”. Rehaz el simulacro del Parcial.
2 días antesSimulacro práctico con reloj (2 horas): dos problemas en Python y dos traducciones a C#.
El día antesTabla de equivalencias Python ↔ C# y errores comunes. Descansa.

Mapa de repaso de todo el curso

En palabras simples

El curso es una escalera: pensar el algoritmo (S1), escribirlo con variables, decisiones, bucles y funciones (S2–S4), organizar los datos (S5, S7), modelar el negocio con objetos (S8–S9) y cambiar de lenguaje sin cambiar el diseño (S10–S11).

BloqueSemanasLo indispensable
Fundamentos1–4algoritmos, tipos, if/elif, bucles, funciones, ámbito, pruebas
Datos5, 7listas, tuplas, ordenamiento, diccionarios, conjuntos, archivos, excepciones
Objetos8–9clases, invariantes, herencia, polimorfismo, composición
C#10–11compilación, tipos, decimal, TryParse, clases, propiedades, List<T>, virtual/override
Tabla de traducción de Python a C#: declaración de variables con tipo, conversión con int.Parse, if y else if con llaves, for con contador, while, Console.WriteLine y métodos static.
Las equivalencias de sintaxis que más se preguntan.
Equivalencias entre una clase en Python y en C#: constructor, atributo privado, propiedad de solo lectura, método, excepción, herencia y redefinición con override.
Las equivalencias de clases entre Python y C#.

Errores comunes de la segunda mitad

#MalPor quéBien
1d["clave"] con clave que puede no existirKeyErrord.get("clave", valor)
2except: a secasesconde errores de programaciónexcept ValueError:
3json.dumps(datos) y creer que ya se guardósolo produce textoPath(r).write_text(json.dumps(datos))
4atributo definido fuera de __init__ (saldo = 0 en la clase)lo comparten todos los objetosself._saldo = 0 en __init__
5método sin selfTypeError al llamarlodef depositar(self, monto):
6hija sin super().__init__faltan los atributos de la madrellamar a super().__init__(...)
7herencia para “tiene un”una factura no es un clientecomposición
8C#: 7 / 2 esperando 3.5división entera7 / 2.0
9C#: decimal p = 12.5;literal double (CS0664)12.5m
10C#: redefinir sin virtual/overrideno hay polimorfismovirtual en la base, override en la hija

Simulacro teórico (15 preguntas)

Sin apuntes y sin ejecutar nada.

(Python) ¿Qué imprime?

ventas = [3, 8, 1, 9, 4]
print(sum(v for v in ventas if v > 3), ventas[1:4])

8 + 9 + 4 = 21; slice de 1 a 3.

(Python) ¿Qué devuelve f(4)?

def f(n):
    if n == 0:
        return 1
    return 2 * f(n - 1)

2 × 2 × 2 × 2 × 1 = 16.

(Python) ¿Qué imprime?

stock = {"A": 5}
stock["B"] = stock.get("B", 0) + 3
stock["A"] -= 2
print(stock)

get da 0 para B; A baja a 3.

(Python) ¿Qué imprime?

try:
    x = int("4.5")
except ValueError:
    x = -1
else:
    x = x * 2
print(x)

int("4.5") falla: se ejecuta except, no else.

(Python) {"a", "b", "c"} - {"b"} es…

Diferencia de conjuntos.

(Objetos) ¿Qué imprime?

class C:
    def __init__(self):
        self.n = 0
    def mas(self):
        self.n += 1
        return self
print(C().mas().mas().n)

Cada mas() devuelve el mismo objeto; se encadenan.

(Objetos) Con class B(A) que redefine f, y A.g que llama a self.f(), ¿qué versión de f usa B().g()?

self es un objeto B: polimorfismo.

(Objetos) Un Pedido contiene una lista de Item. ¿Qué relación es?

“Tiene un”.

(C#) ¿Qué imprime?

int a = 10, b = 4;
Console.WriteLine(a / b + a % b);

10 / 4 = 2 (entera) y 10 % 4 = 2.

(C#) ¿Qué tipo usar para el saldo de una cuenta?

Exacto en base 10; literales con m.

(C#) ¿Qué hace el compilador con string s = 5;?

Tipos incompatibles detectados antes de ejecutar.

(C#) ¿Qué es public decimal Saldo { get; private set; }?

Equivale a @property sin setter público.

(C#) ¿Qué equivale a super().__init__(nombre)?

Llama al constructor de la clase base.

(C#) decimal.TryParse("abc", out decimal m) devuelve…

Es la forma segura de convertir texto.

(C#) ¿Qué propiedad da la cantidad de elementos de una List<T>?

En arreglos es Length; en listas, Count.

Simulacro práctico (2 horas)

El mismo problema de negocio, primero en Python (con archivos, diccionarios y clases) y luego en C#. Es exactamente el tipo de “equivalencia entre lenguajes” que evalúa el Final.

P1 · Suscripciones SaaS en Python (S7 + S8)

clases + JSON + diccionarios · ★★★★

Una plataforma cobra planes básico ($9.99) y pro ($24.99) por mes; desde 12 meses activos el cliente recibe 15 % de descuento. Carga las suscripciones desde JSON (si el archivo no existe, lista vacía), calcula el ingreso mensual y cuenta clientes por plan. Un plan desconocido lanza ValueError.

Tu programa debe cumplir estos casos de prueba:

DatoEsperado
Ana, pro, 14 meses$21.24
Luis, básico, 3 meses$9.99
Eva, pro, 2 meses$24.99
Ingreso mensual$56.22
Clientes por plan{'pro': 2, 'basico': 1}
Sin archivo[]
Pista

Clase con validación en __init__; función cargar con try/except FileNotFoundError; acumular por clave para contar planes.

Solución
import json
from pathlib import Path


class Suscripcion:
    PRECIOS = {"basico": 9.99, "pro": 24.99}

    def __init__(self, cliente, plan, meses_activos=0):
        if plan not in self.PRECIOS:
            raise ValueError(f"plan desconocido: {plan}")
        self.cliente = cliente
        self.plan = plan
        self.meses_activos = meses_activos

    def cobro_mensual(self):
        precio = self.PRECIOS[self.plan]
        if self.meses_activos >= 12:
            precio *= 0.85                       # lealtad: 15 % desde el año
        return round(precio, 2)

    def a_dict(self):
        return {"cliente": self.cliente, "plan": self.plan, "meses_activos": self.meses_activos}


def cargar(ruta):
    try:
        datos = json.loads(Path(ruta).read_text())
    except FileNotFoundError:
        return []
    return [Suscripcion(d["cliente"], d["plan"], d["meses_activos"]) for d in datos]


Path("subs.json").write_text(json.dumps([
    {"cliente": "Ana", "plan": "pro", "meses_activos": 14},
    {"cliente": "Luis", "plan": "basico", "meses_activos": 3},
    {"cliente": "Eva", "plan": "pro", "meses_activos": 2}]))

subs = cargar("subs.json")
ingreso = sum(s.cobro_mensual() for s in subs)
por_plan = {}
for s in subs:
    por_plan[s.plan] = por_plan.get(s.plan, 0) + 1
print(f"Ingreso mensual: ${ingreso:.2f}")
print("Clientes por plan:", por_plan)
print("Sin archivo:", cargar("no_existe.json"))
Ingreso mensual: $56.22
Clientes por plan: {'pro': 2, 'basico': 1}
Sin archivo: []

P2 · La misma clase, en C# (S10 + S11)

traducción de clase · ★★★

Traduce Suscripcion y el cálculo del ingreso a C#. Usa propiedades de solo lectura, decimal y List<Suscripcion>. El resultado debe ser idéntico al de Python.

Tu programa debe cumplir estos casos de prueba:

DatoEsperado
Ingreso mensual56.22 (igual que Python)
new Suscripcion("X", "gold", 1)ArgumentException
Pista

raise ValueError → throw new ArgumentException; @property → { get; }; lista → List<T>; el operador ternario reemplaza el diccionario de precios.

Solución
var subs = new List<Suscripcion>
{
    new Suscripcion("Ana", "pro", 14),
    new Suscripcion("Luis", "basico", 3),
    new Suscripcion("Eva", "pro", 2),
};
decimal ingreso = 0;
foreach (var s in subs) ingreso += s.CobroMensual();
Console.WriteLine($"Ingreso mensual: {ingreso:F2}");


public class Suscripcion
{
    public string Cliente { get; }
    public string Plan { get; }
    public int MesesActivos { get; }

    public Suscripcion(string cliente, string plan, int mesesActivos)
    {
        if (plan != "basico" && plan != "pro")
            throw new ArgumentException($"plan desconocido: {plan}");
        Cliente = cliente;
        Plan = plan;
        MesesActivos = mesesActivos;
    }

    public decimal CobroMensual()
    {
        decimal precio = Plan == "pro" ? 24.99m : 9.99m;
        if (MesesActivos >= 12) precio *= 0.85m;
        return Math.Round(precio, 2, MidpointRounding.AwayFromZero);
    }
}
Ingreso mensual: 56.22

Verificación: 24.99 × 0.85 = 21.2415 → 21.24; 21.24 + 9.99 + 24.99 = 56.22 ✔ en ambos lenguajes.

Estrategia para el Final

Durante el examen
  • Separa mentalmente las preguntas de Python y las de C#: antes de responder, pregúntate “¿en qué lenguaje estoy?” (división entera, True vs true, ;).
  • En C#, escribe primero los tipos de cada variable: evita la mitad de los errores.
  • En problemas de objetos: lista atributos, métodos y la regla que se protege antes de escribir.
  • Traza en papel. Prueba con un caso normal y uno de frontera.