diff --git a/exercises/exercise1.py b/exercises/exercise1.py index 4d88ccc..1668f25 100644 --- a/exercises/exercise1.py +++ b/exercises/exercise1.py @@ -1,45 +1,53 @@ -"""Variables de Instancia y Métodos de instancia.""" - -from math import pi - - -class Circle: - """Todo cículo tiene un radio y se desea conocer tanto el área como el - perímetro (longitud de circunferencia). - - Reportar los números redondeados a dos decimales - - Restricciones: - - Utilizar 1 variable de instancia - - Utilizar 2 métodos de instancia - - No utilizar variable de clase - - No utilizar Dataclasses - - No utilizar Properties - - Utilizar Type Hints en todos los métodos y variables - """ - - -# NO MODIFICAR - INICIO -# Test básico -circle = Circle(1) -assert circle.radio == 1 -assert circle.area() == 3.14 -assert circle.perimetro() == 6.28 - -# Test palabra clave -circle = Circle(radio=1) -assert circle.radio == 1 -assert circle.area() == 3.14 -assert circle.perimetro() == 6.28 - -# Test parámetro obligatorio -try: - circle = Circle() - assert False, "No se puede instanciar sin radio" -except TypeError: - assert True - -# Test invocación encadenada -assert Circle(1).area() == 3.14 -assert Circle(1).perimetro() == 6.28 -# NO MODIFICAR - FIN +"""Variables de Instancia y Métodos de instancia.""" + +from math import pi + + +class Circle: + """Todo cículo tiene un radio y se desea conocer tanto el área como el + perímetro (longitud de circunferencia). + + Reportar los números redondeados a dos decimales + + Restricciones: + - Utilizar 1 variable de instancia + - Utilizar 2 métodos de instancia + - No utilizar variable de clase + - No utilizar Dataclasses + - No utilizar Properties + - Utilizar Type Hints en todos los métodos y variables + """ + def __init__(self,radio): + self.radio=radio + + def area(self): + return round(pi*self.radio**2,2) + + def perimetro(self): + return round(pi*self.radio*2,2) + + +# NO MODIFICAR - INICIO +# Test básico +circle = Circle(1) +assert circle.radio == 1 +assert circle.area() == 3.14 +assert circle.perimetro() == 6.28 + +# Test palabra clave +circle = Circle(radio=1) +assert circle.radio == 1 +assert circle.area() == 3.14 +assert circle.perimetro() == 6.28 + +# Test parámetro obligatorio +try: + circle = Circle() + assert False, "No se puede instanciar sin radio" +except TypeError: + assert True + +# Test invocación encadenada +assert Circle(1).area() == 3.14 +assert Circle(1).perimetro() == 6.28 +# NO MODIFICAR - FIN diff --git a/exercises/exercise2.py b/exercises/exercise2.py index 2b02c90..ef71a5a 100644 --- a/exercises/exercise2.py +++ b/exercises/exercise2.py @@ -1,71 +1,95 @@ -"""Variables de Clase y Métodos de Clase.""" - - -class Article: - """Todos los artículos tienen un nombre y un costo, opcionalmente algunos - tienen un porcentaje de descuento. - - El IVA es un impuesto que se aplica a todos los productos por igual, - actualmente es de 21% pero puede cambiar en el futuro. - - Para calcular el precio de un artículo, hay que sumar el IVA y luego restar - los descuentos si hubiera. Redondear a 2 decimales. - - Restricciones: - - Utilizar 3 variables de instancia - - Utilizar 1 método de instancia - - Utilizar 1 variable de clase - - Utilizar 1 método de clase - - No utilizar Dataclasses - - No utilizar Properties - - Utilizar Type Hints en todos los métodos y variables - """ - - -# NO MODIFICAR - INICIO -# Test parámetro obligatorio -try: - article = Article() - assert False, "No se puede instanciar sin nombre ni costo" -except TypeError: - assert True - -try: - article = Article("Auto") - assert False, "No se puede instanciar sin costo" -except TypeError: - assert True - -try: - article = Article(nombre="Auto", costo=1) - assert True -except TypeError: - assert False, "El descuento es opcional" - -# Test básico -article = Article("Auto", 1) -assert article.nombre == "Auto" -assert article.calcular_precio() == 1.21 - -article = Article("Auto", 1, 0.21) -assert article.nombre == "Auto" -assert article.calcular_precio() == 0.96 - - -# Test palabra clave -article = Article(costo=1, nombre="Auto") -assert article.nombre == "Auto" -assert article.calcular_precio() == 1.21 - -article = Article(costo=1, nombre="Auto", descuento=0.21) -assert article.nombre == "Auto" -assert article.calcular_precio() == 0.96 - - -# Test de método de clase -Article.actualizar_iva(0.25) - -article = Article(costo=1, nombre="Auto") -assert article.nombre == "Auto" -assert article.calcular_precio() == 1.25 -# NO MODIFICAR - FIN +"""Variables de Clase y Métodos de Clase.""" + + +from typing_extensions import Self + + +class Article: + """Todos los artículos tienen un nombre y un costo, opcionalmente algunos + tienen un porcentaje de descuento. + + El IVA es un impuesto que se aplica a todos los productos por igual, + actualmente es de 21% pero puede cambiar en el futuro. + + Para calcular el precio de un artículo, hay que sumar el IVA y luego restar + los descuentos si hubiera. Redondear a 2 decimales. + + Restricciones: + - Utilizar 3 variables de instancia + - Utilizar 1 método de instancia + - Utilizar 1 variable de clase + - Utilizar 1 método de clase + - No utilizar Dataclasses + - No utilizar Properties + - Utilizar Type Hints en todos los métodos y variables + """ + + __iva=0.21 + + def __init__(self, nombre, costo, descuento=0): + self.nombre=nombre + self.costo=costo + self.descuento=descuento + + def calcular_precio(self): + precio = round(self.costo + (self.costo * self.__iva), 2) + print(precio) + precio_final = round( precio - (self.descuento * precio), 2) + print(precio_final) + return precio_final + + @classmethod + def actualizar_iva(cls,iva): + cls.__iva=iva + + + + + +# NO MODIFICAR - INICIO +# Test parámetro obligatorio +try: + article = Article() + assert False, "No se puede instanciar sin nombre ni costo" +except TypeError: + assert True + +try: + article = Article("Auto") + assert False, "No se puede instanciar sin costo" +except TypeError: + assert True + +try: + article = Article(nombre="Auto", costo=1) + assert True +except TypeError: + assert False, "El descuento es opcional" + +# Test básico +article = Article("Auto", 1) +assert article.nombre == "Auto" +assert article.calcular_precio() == 1.21 + +article = Article("Auto", 1, 0.21) +assert article.nombre == "Auto" +assert article.calcular_precio() == 0.96 + + +# Test palabra clave +article = Article(costo=1, nombre="Auto") +assert article.nombre == "Auto" +assert article.calcular_precio() == 1.21 + +article = Article(costo=1, nombre="Auto", descuento=0.21) +assert article.nombre == "Auto" +assert article.calcular_precio() == 0.96 + + +# Test de método de clase +Article.actualizar_iva(0.25) + +article = Article(costo=1, nombre="Auto") +assert article.nombre == "Auto" +assert article.calcular_precio() == 1.25 +# NO MODIFICAR - FIN diff --git a/exercises/exercise3.py b/exercises/exercise3.py index 331440a..6d81843 100644 --- a/exercises/exercise3.py +++ b/exercises/exercise3.py @@ -1,74 +1,91 @@ -"""Properties""" - - -class Article: - """Re-Escribir el ejercicio anterior utilizando una property en vez de un - método de instancia. - - Restricciones: - - Utilizar 3 variables de instancia - - Utilizar 1 property - - Utilizar 1 variable de clase - - Utilizar 1 método de clase - - No utilizar métodos de instancia - - No utilizar Dataclasses - - Utilizar Type Hints en todos los métodos y variables - """ - - -# NO MODIFICAR - INICIO -# Test parámetro obligatorio -try: - article = Article() - assert False, "No se puede instanciar sin nombre ni costo" -except TypeError: - assert True - -try: - article = Article("Auto") - assert False, "No se puede instanciar sin costo" -except TypeError: - assert True - -try: - article = Article(nombre="Auto", costo=1) - assert True -except TypeError: - assert False, "El descuento es opcional" - -try: - article = Article(nombre="Auto", costo=1) - article.precio = 2 - assert False, "No se puede modificar el precio" -except AttributeError: - assert True - - -# Test básico -article = Article("Auto", 1) -assert article.nombre == "Auto" -assert article.precio == 1.21 - - -article = Article("Auto", 1, 0.21) -assert article.nombre == "Auto" -assert article.precio == 0.96 - - -# Test palabra clave -article = Article(costo=1, nombre="Auto") -assert article.nombre == "Auto" -assert article.precio == 1.21 - -article = Article(costo=1, nombre="Auto", descuento=0.21) -assert article.nombre == "Auto" -assert article.precio == 0.96 - - -# Test de método de clase -Article.actualizar_iva(0.25) - -article = Article(costo=1, nombre="Auto") -assert article.nombre == "Auto" -assert article.precio == 1.25 -# NO MODIFICAR - FIN +"""Properties""" + + +class Article: + """Re-Escribir el ejercicio anterior utilizando una property en vez de un + método de instancia. + + Restricciones: + - Utilizar 3 variables de instancia + - Utilizar 1 property + - Utilizar 1 variable de clase + - Utilizar 1 método de clase + - No utilizar métodos de instancia + - No utilizar Dataclasses + - Utilizar Type Hints en todos los métodos y variables + """ + + __iva = 0.21 + + def __init__(self, nombre, costo, descuento=0): + self.nombre = nombre + self.costo = costo + self.descuento = descuento + + @property + def precio(self): + precio_iva = self.costo + (self.costo*self.__iva) + precio_descuento = precio_iva - (precio_iva*self.descuento) + precio_descuento = round(precio_descuento, 2) + return precio_descuento + + @classmethod + def actualizar_iva(cls, iva): + cls.__iva = iva + +# NO MODIFICAR - INICIO +# Test parámetro obligatorio +try: + article = Article() + assert False, "No se puede instanciar sin nombre ni costo" +except TypeError: + assert True + +try: + article = Article("Auto") + assert False, "No se puede instanciar sin costo" +except TypeError: + assert True + +try: + article = Article(nombre="Auto", costo=1) + assert True +except TypeError: + assert False, "El descuento es opcional" + +try: + article = Article(nombre="Auto", costo=1) + article.precio = 2 + assert False, "No se puede modificar el precio" +except AttributeError: + assert True + + +# Test básico +article = Article("Auto", 1) +assert article.nombre == "Auto" +assert article.precio == 1.21 + + +article = Article("Auto", 1, 0.21) +assert article.nombre == "Auto" +assert article.precio == 0.96 + + +# Test palabra clave +article = Article(costo=1, nombre="Auto") +assert article.nombre == "Auto" +assert article.precio == 1.21 + +article = Article(costo=1, nombre="Auto", descuento=0.21) +assert article.nombre == "Auto" +assert article.precio == 0.96 + + +# Test de método de clase +Article.actualizar_iva(0.25) + +article = Article(costo=1, nombre="Auto") +assert article.nombre == "Auto" +assert article.precio == 1.25 +# NO MODIFICAR - FIN diff --git a/exercises/exercise4.py b/exercises/exercise4.py index b424db7..e4f8e32 100644 --- a/exercises/exercise4.py +++ b/exercises/exercise4.py @@ -1,55 +1,67 @@ -"""DataClasses y Sobrecarga de operadores.""" - -from dataclasses import dataclass -from typing import List - - -"""Una carrera tiene varias materias, la "longitud" de una carrera hace -referencia a cuantas materias tiene. - -Cada materia tiene un nombre. - -Escribir una estructura de clases que refleje lo anterior. - -Restricciones: - - Utilizar Dataclasses - - Utilizar 2 clases - - Utilizar 1 variables de instancia en cada clase - - Utilizar 1 método mágico - - No utilizar variables de clase - - No utilizar métodos de clase - - No utilizar métodos de instancia - - No utilizar properties - - Utilizar Type Hints en todos los métodos y variables -""" - - -# NO MODIFICAR - INICIO -# Test parámetro obligatorio -try: - materia = Materia() - assert False, "No se puede instanciar sin nombre" -except TypeError: - assert True - -try: - materia = Carrera() - assert False, "No se puede instanciar sin materias" -except TypeError: - assert True - -# Test básico -matematica = Materia("Matemática") -assert matematica.nombre == "Matemática" - -estadistica = Materia(nombre="Estadística") -assert estadistica.nombre == "Estadística" - -ciclo_basico = Carrera([matematica, estadistica]) -assert ( - str(ciclo_basico) - == "Carrera(materias=[Materia(nombre='Matemática'), Materia(nombre='Estadística')])" # noqa: 501 -) - -assert len(ciclo_basico) == 2 -# NO MODIFICAR - FIN +"""DataClasses y Sobrecarga de operadores.""" + +from dataclasses import dataclass +from typing import List + + +"""Una carrera tiene varias materias, la "longitud" de una carrera hace +referencia a cuantas materias tiene. + +Cada materia tiene un nombre. + +Escribir una estructura de clases que refleje lo anterior. + +Restricciones: + - Utilizar Dataclasses + - Utilizar 2 clases + - Utilizar 1 variables de instancia en cada clase + - Utilizar 1 método mágico + - No utilizar variables de clase + - No utilizar métodos de clase + - No utilizar métodos de instancia + - No utilizar properties + - Utilizar Type Hints en todos los métodos y variables +""" +@dataclass +class Carrera: + longitud:list + + def __len__(self): + return len(self.longitud) + + def __str__(self): + return f"Carrera(materias={self.longitud})" + +@dataclass +class Materia: + nombre:str + +# NO MODIFICAR - INICIO +# Test parámetro obligatorio +try: + materia = Materia() + assert False, "No se puede instanciar sin nombre" +except TypeError: + assert True + +try: + materia = Carrera() + assert False, "No se puede instanciar sin materias" +except TypeError: + assert True + +# Test básico +matematica = Materia("Matemática") +assert matematica.nombre == "Matemática" + +estadistica = Materia(nombre="Estadística") +assert estadistica.nombre == "Estadística" + +ciclo_basico = Carrera([matematica, estadistica]) +assert ( + str(ciclo_basico) + == "Carrera(materias=[Materia(nombre='Matemática'), Materia(nombre='Estadística')])" # noqa: 501 +) + +assert len(ciclo_basico) == 2 +# NO MODIFICAR - FIN diff --git a/exercises/exercise5.py b/exercises/exercise5.py index 92d717c..6227712 100644 --- a/exercises/exercise5.py +++ b/exercises/exercise5.py @@ -1,103 +1,138 @@ -"""El ente regulador de impuestos llama a todas las personas activas -laboralmente Contribuyentes, sin embargo, existen varios tipos de -contribuyentes, por ejemplo, el Monotributista y el que es Empleado en relación -de dependencia. Ambos están dentro del sistema pero pagan diferentes impuestos. - -El monotributista tiene que pagar en función de sus ingresos brutos anuales: - - Si son menores a $370.000, paga $2646,22 mensuales - - Si son menores a $550.000, paga $2958,95 mensuales - - Si son menores a $770.000, paga $3382,62 mensuales - - Si son mayores a $770.000, paga $3988,85 mensuales - -En el caso de los empleados en relación de dependencia, ellos pagan un 17% de -impuestos sobre sus ingresos brutos mensuales. - -Inspirado en datos reales: https://www.afip.gob.ar/monotributo/categorias.asp - -Escribir una estructura de clases que refleje lo anterior. Para simplificar el -análisis, todos los montos serán mensuales (dividir los límites del monotributo -por 12). - -Aclaración: Este ejercicio está basado en la realidad pero se realizaron -múltiples simplificaciones para adecuarlo al contexto del curso. - -Restricciones: - - Utilizar Dataclasses - - Utilizar 3 clases: 1 abstracta y 2 concretas - - Utilizar 1 variables de instancia en cada clase concreta - - Utilizar 1 métodos de instancia con polimorfismo - - No utilizar variables de clase - - No utilizar métodos de clase - - No utilizar properties - - Utilizar Type Hints en todos los métodos y variables -""" - -import abc -from abc import ABC, abstractmethod -from dataclasses import dataclass -from typing import List - - -def calcular_sueldos(contribuyentes: List[Contribuyente]): - """Data una lista de contribuyentes, devuelve una lista de los sueldos de - cada uno.""" - - -# NO MODIFICAR - INICIO -assert type(Contribuyente) == abc.ABCMeta, "Contribuyente debe ser abstracta" -assert issubclass(Empleado, Contribuyente), "Empleado debe heredar de Contribuyente" # noqa: 501 -assert issubclass(Monotributista, Contribuyente), "Monotributista debe heredar de Contribuyente" # noqa: 501 - -try: - juan = Contribuyente() - assert False, "No se puede instanciar una clase abstracta" -except TypeError: - assert True - -try: - juan = Empleado() - assert False, "No se puede instanciar sin sueldo" -except TypeError: - assert True - -try: - juan = Monotributista() - assert False, "No se puede instanciar sin sueldo" -except TypeError: - assert True - - -# Test Básico -juan = Monotributista(25_000) -assert juan.calcular_sueldo() == 22353.78 - -juan = Monotributista(35_000) -assert juan.calcular_sueldo() == 32041.05 - -juan = Monotributista(50_000) -assert juan.calcular_sueldo() == 46617.38 - -juan = Monotributista(75_000) -assert juan.calcular_sueldo() == 71011.15 - - -maria = Empleado(25_000) -assert maria.calcular_sueldo() == 20750.0 - -maria = Empleado(35_000) -assert maria.calcular_sueldo() == 29050.0 - -maria = Empleado(50_000) -assert maria.calcular_sueldo() == 41500.0 - -maria = Empleado(75_000) -assert maria.calcular_sueldo() == 62250.0 - - -# Test Calculadora de sueldos - -contribuyentes = [Monotributista(80_000), Empleado(80_000)] - -assert calcular_sueldos(contribuyentes) == [76011.15, 66400.0] - -# NO MODIFICAR - FIN +"""El ente regulador de impuestos llama a todas las personas activas +laboralmente Contribuyentes, sin embargo, existen varios tipos de +contribuyentes, por ejemplo, el Monotributista y el que es Empleado en relación +de dependencia. Ambos están dentro del sistema pero pagan diferentes impuestos. + +El monotributista tiene que pagar en función de sus ingresos brutos anuales: + - Si son menores a $370.000, paga $2646,22 mensuales + - Si son menores a $550.000, paga $2958,95 mensuales + - Si son menores a $770.000, paga $3382,62 mensuales + - Si son mayores a $770.000, paga $3988,85 mensuales + +En el caso de los empleados en relación de dependencia, ellos pagan un 17% de +impuestos sobre sus ingresos brutos mensuales. + +Inspirado en datos reales: https://www.afip.gob.ar/monotributo/categorias.asp + +Escribir una estructura de clases que refleje lo anterior. Para simplificar el +análisis, todos los montos serán mensuales (dividir los límites del monotributo +por 12). + +Aclaración: Este ejercicio está basado en la realidad pero se realizaron +múltiples simplificaciones para adecuarlo al contexto del curso. + +Restricciones: + - Utilizar Dataclasses + - Utilizar 3 clases: 1 abstracta y 2 concretas + - Utilizar 1 variables de instancia en cada clase concreta + - Utilizar 1 métodos de instancia con polimorfismo + - No utilizar variables de clase + - No utilizar métodos de clase + - No utilizar properties + - Utilizar Type Hints en todos los métodos y variables +""" +import abc +from abc import ABC, abstractmethod +from dataclasses import dataclass +from decimal import Rounded +from typing import List + + +class Contribuyente(ABC): + @abstractmethod + def calcular_sueldo(self): + pass + +@dataclass +class Empleado(Contribuyente): + sueldo:int + + def calcular_sueldo(self): + return self.sueldo*0.83 + +@dataclass +class Monotributista(Contribuyente): + sueldo:float + + def calcular_sueldo(self): + sueldo_final = self.sueldo*12 + + if sueldo_final<370000: + sueldo_mensual=self.sueldo-2646.22 + elif sueldo_final<550000: + sueldo_mensual=self.sueldo-2958.95 + elif sueldo_final<770000: + sueldo_mensual=self.sueldo-3382.62 + elif sueldo_final>770000: + sueldo_mensual=self.sueldo-3988.85 + return sueldo_mensual + + + +def calcular_sueldos(contribuyentes: List[Contribuyente]): + """Data una lista de contribuyentes, devuelve una lista de los sueldos de + cada uno.""" + sueldos=[] + for i in contribuyentes: + sueldos.append(i.calcular_sueldo()) + return sueldos + + +# NO MODIFICAR - INICIO +assert type(Contribuyente) == abc.ABCMeta, "Contribuyente debe ser abstracta" +assert issubclass(Empleado, Contribuyente), "Empleado debe heredar de Contribuyente" # noqa: 501 +assert issubclass(Monotributista, Contribuyente), "Monotributista debe heredar de Contribuyente" # noqa: 501 + +try: + juan = Contribuyente() + assert False, "No se puede instanciar una clase abstracta" +except TypeError: + assert True + +try: + juan = Empleado() + assert False, "No se puede instanciar sin sueldo" +except TypeError: + assert True + +try: + juan = Monotributista() + assert False, "No se puede instanciar sin sueldo" +except TypeError: + assert True + + +# Test Básico +juan = Monotributista(25_000) +assert juan.calcular_sueldo() == 22353.78 + +juan = Monotributista(35_000) +assert juan.calcular_sueldo() == 32041.05 + +juan = Monotributista(50_000) +assert juan.calcular_sueldo() == 46617.38 + +juan = Monotributista(75_000) +assert juan.calcular_sueldo() == 71011.15 + + +maria = Empleado(25_000) +assert maria.calcular_sueldo() == 20750.0 + +maria = Empleado(35_000) +assert maria.calcular_sueldo() == 29050.0 + +maria = Empleado(50_000) +assert maria.calcular_sueldo() == 41500.0 + +maria = Empleado(75_000) +assert maria.calcular_sueldo() == 62250.0 + + +# Test Calculadora de sueldos + +contribuyentes = [Monotributista(80_000), Empleado(80_000)] + +assert calcular_sueldos(contribuyentes) == [76011.15, 66400.0] + +# NO MODIFICAR - FIN