Python - Clases y subclases

 
Vista:
Imágen de perfil de Jorge Alberto
Val: 137
Ha disminuido 1 puesto en Python (en relación al último mes)
Gráfica de Python

Clases y subclases

Publicado por Jorge Alberto (50 intervenciones) el 05/05/2021 20:31:54
Hola. ¿Cómo andan? Tengo un problema con un ejercicio sobre clases. El ejercicio es el siguiente:

Crear las clases Materia y Carrera, que se comporten según el siguiente ejemplo:
>>> analisis2 = Materia("61.03", "Análisis 2", 8)
>>> fisica2 = Materia("62.01", "Física 2", 8)
>>> algo1 = Materia("75.40", "Algoritmos 1", 6)
>>> c = Carrera([analisis2, fisica2, algo1])
>>> str(c)
Créditos: 0 -- Promedio: N/A -- Materias aprobadas:
>>> c.aprobar("95.14", 7)
ValueError: La materia 75.14 no es parte del plan de estudios
>>> c.aprobar("75.40", 10)
>>> c.aprobar("62.01", 7)
>>> str(c)
Créditos: 14 -- Promedio: 8.5 -- Materias aprobadas:
75.40 Algoritmos 1 (10)
62.01 Física 2 (7)

Si no entiendo mal lo que hay que hacer, la clase Materia solamente tomará los valores que reciba (no hay que crear métodos nuevos ni nada por el estilo). Y la clase Carrera, además, deberá contar con un método aprobar que funcione así:
- Si el código no es parte de la carrera, devolverá el error indicado.
- Si lo es, sumará la cantidad de créditos, obtendrá el promedio e imprimirá nombre y código de las materias aprobadas.

El código que yo usé es el siguiente:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
lista_codigo, lista_creditos, lista_aprobadas = [], [], []
 
class Materia:
 
    '''La función sólo debe tomar las variables'''
    def __init__(self, codigo, nombre, creditos):
        self.codigo = codigo
        self.nombre = nombre
        self.creditos = creditos
 
        if codigo not in lista_codigo:
            lista_codigo.append(self.codigo)
            lista_creditos.append(self.creditos)
 
'''------------------------------------------------------------------------------------------------------------------------------------'''
 
class Carrera(Materia):
 
    def __init__(self, lista):
        self.lista = lista
        self.credito, self.aprobadas, self.total, self.promedio = 0, 0, 0, 0
 
    def __str__(self):
        if self.credito == 0:
            return 'Créditos: 0 -- Promedio: N/A -- Materias aprobadas:'
        else:
            return 'Créditos: {} -- Promedio: {} -- Materias aprobadas: {}'. format(self.credito, self.promedio, 1) # FALTA el tercer argumento
 
    def aprobar(self, codigo, nota):
        try:
            lista_codigo.index(codigo)
        except:
            return ValueError('La materia {} no es parte del plan de estudios'.format(codigo)) # Lo imprime únicamente si uso 'return'
 
        if codigo not in lista_aprobadas:
            lista_aprobadas.append(codigo)
            self.credito += lista_creditos[lista_codigo.index(codigo)]
            self.aprobadas += 1
            self.total += nota
            self.promedio = self.total/self.aprobadas
        else:
            return True
 
analisis2 = Materia("61.03", "Análisis 2", 8)
fisica2 = Materia("62.01", "Física 2", 8)
algo1 = Materia("75.40", "Algoritmos 1", 6)
 
c = Carrera([analisis2, fisica2, algo1])
print(c.aprobar("95.14", 7))
print(str(c))
c.aprobar('75.40', 10)
c.aprobar("62.01", 7)
print(str(c))

El código funciona bastante bien, pero tiene algunos inconvenientes.

1. Si el código no esta en la carrera, no devuelve el error ValueError, si no que simplemente no hace nada. Si agrego return en la línea del ValueError, imprime el error, pero no como una excepción, si no como una string.

2. No sé como hacer para imprimir las materias y sus códigos en líneas diferentes. Esto sería en la línea 50 del código. Además, tiene un problema similar al anterior. Si escribo en la consola str(c), no imprime nada, salvo que use print(str(c)).

3. Esto no es un error, si no más una consulta para mejorar el código. ¿Hay alguna manera de hacerlo sin la necesidad de crear las listas que cree arriba de las clases? Tengo la sensación que el ejercicio apunta a hacerlo sin esas listas, pero no sé cómo.

4. Creo que le estoy errando al usar la subclase. Intenté obtener todos los atributos de la clase anterior con el código:
1
2
3
4
5
6
class Carrera(Materia):
 
    def __init__(self, lista):
        super().__init__(codigo, nombre, creditos)
        self.lista = lista
        self.credito, self.aprobadas, self.total, self.promedio = 0, 0, 0, 0

pero me arroja el error:

1
NameError: name 'codigo' is not defined
¿Dónde estaría el problema?

PD: perdón si la terminología no es la correcta. Estuve viendo tutoriales y videos en inglés, por lo que es posible que algún término sea incorrecto. Cualquier cosa me avisan y busco cuál es el correcto.
Valora esta pregunta
Me gusta: Está pregunta es útil y esta claraNo me gusta: Está pregunta no esta clara o no es útil
0
Responder