Curso de introducción a la programación con Python¶

    Autor: Luis Fernando Apáez Álvarez
    -Curso PyM-
    Proyecto 1 (parte I): Creando la clase graficar
    Fecha: 01 de diciembre del 2022


En este proyecto comenzaremos creando una clase denominada graficar, con la cual conseguiremos graficar funciones. Para lograrlo nos valdremos del código ya creado en el anterior proyecto, más especificamente en Proyecto 1 (parte I): Graficador de funciones. Nuestra labor será adaptar dicho código a una clase. Para ello

  • Comenzaremos por crear un menú que nos auxilie a saber el tipo de función que ingresará el usuario. Después pediremos a dicho usuario que ingrese su función
In [68]:
# Importamos las librerías que más adelante ocuparemos
import matplotlib.pyplot as mplot
import numpy as np

# Menú:

print("De que tipo es tu función: ")
print("_" * 30)
print("1: Algebraicas")
print("2: Trigonométricas")
print("3: Exponencial")
print("4: Logarítmica")
print("_" * 30)

# Número del tipo de función que ingresa el usuario
n_aux = input("Coloca un número del 1 al 4: ")
print("_" * 30)

# Controlamos posibles errores
if int(n_aux) not in (1,2,3,4):
    print("Error, debes ingresar un número del 1 al 4")
    print("Fin del proceso")
else:
    # Función ingresada por el usuario
    fun = input("Ingresa tu función: ")

# -------------------------------------------------
De que tipo es tu función: 
______________________________
1: Algebraicas
2: Trigonométricas
3: Exponencial
4: Logarítmica
______________________________
Coloca un número del 1 al 4: 1
______________________________
Ingresa tu función: x**2

Agregamos un condicional para manejar las funciones trigonométricas, exponenciales y logarítmicas mediante la librería numpy

In [69]:
if int(n_aux) != 1:
    fun = "np." + fun
else:
    fun = fun
  • Creamos la clase graficar colocando en el constructor los atributos necesarios para que el usuario ingrese un intervalo de graficación (que denominaremos rango) y la función en sí a graficar. Asimismo, crearemos la clase str para mostrar el rango de graficación de dicha función y la expresión de dicha función.
In [81]:
# Creación de la clase graficar
class graficar:
    # Constructor
    def __init__(self, rango, funcion):
        
        # Atributos de la clase
        self.rango_inf = rango[0]
        self.rango_sup = rango[1]
        self.funcion = funcion
    
    # Método str
    def __str__(self):
        return f'Rango:({self.rango_inf},{self.rango_sup})\nf(x) = {self.funcion}'

cabe resaltar que supondremos que el parámetro de rango será o una tupla o una lista. Probemos lo que llevamos:

In [82]:
# Instanciamos la clase
prueba = graficar((-1,1), fun)

# Utilizamos el método str
print(prueba)
Rango:(-1,1)
f(x) = x**2
  • Finalmente, dentro de la clase graficar agregaremos el método Graficador() para que se grafique la función que el usuario ha ingresado:
In [87]:
# Creación de la clase graficar
class graficar:
    # Constructor
    def __init__(self, rango, funcion):
        
        # Atributos de la clase
        self.rango_inf = rango[0]
        self.rango_sup = rango[1]
        self.funcion = funcion
    
    # Método str
    def __str__(self):
        return f'Rango:({self.rango_inf},{self.rango_sup})\nf(x) = {self.funcion}'
    
    # Método para graficar
    def Graficador(self):
        
        # Rango
        x = np.arange(self.rango_inf, self.rango_sup, 0.01)

        # definimos la función f(x)=y
        y = self.funcion

        # creamos la gráfica
        mplot.plot(x, eval(y))

        # mostramos la cuadrícula en el gráfico
        mplot.grid()

        # mostramos la gráfica
        mplot.show()

Ponemos a prueba la clase creada:

In [88]:
# Instanciamos la clase
prueba = graficar((-1,1), fun)

# Utilizamos el método str
print(prueba)

# Invocamos el método Graficador()
prueba.Graficador()
Rango:(-1,1)
f(x) = x**2

De modo que, por el momento, la clase graficar ha quedado terminada.

  • Si bien la configuración del menú ya ha quedado, para los fines del proyecto adaptaremos el código que escribimos para convertirlo en una clase
In [113]:
# Creamos la clase menú

class menu:
    
    # Creamos el método str para mostrar el mensaje inicial
    def __str__(self):
        self.cadena1 = "De que tipo es tu función:"
        self.cadena2 = "_" * 30
        self.cadena3 = "1: Algebraicas"
        self.cadena4 = "2: Trigonométricas"
        self.cadena5 = "3: Exponencial"
        self.cadena6 = "4: Logarítmica"
        self.cadena7 = "_" * 30
        return self.cadena1 + "\n" + self.cadena2 + "\n" + self.cadena3 \
    + "\n" + self.cadena4 + "\n" + self.cadena5 + "\n" + self.cadena6 \
    + "\n" + self.cadena7
In [115]:
# Realizamos una prueba

prueba = menu()
print(prueba)
De que tipo es tu función:
______________________________
1: Algebraicas
2: Trigonométricas
3: Exponencial
4: Logarítmica
______________________________

adaptamos el resto del código a un método de la clase menu:

In [130]:
# Creamos la clase menú

class menu:
    
    # Constructor
    def __init__(self):
        self.fun = ""
        
    # Creamos el método str para mostrar el mensaje inicial
    def __str__(self):
        self.cadena1 = "De que tipo es tu función:"
        self.cadena2 = "_" * 30
        self.cadena3 = "1: Algebraicas"
        self.cadena4 = "2: Trigonométricas"
        self.cadena5 = "3: Exponencial"
        self.cadena6 = "4: Logarítmica"
        self.cadena7 = "_" * 30
        return self.cadena1 + "\n" + self.cadena2 + "\n" + self.cadena3 \
    + "\n" + self.cadena4 + "\n" + self.cadena5 + "\n" + self.cadena6 \
    + "\n" + self.cadena7
    
    def info_usuario(self):
        # Número del tipo de función que ingresa el usuario
        self.n_aux = input("Coloca un número del 1 al 4: ")
        print("_" * 30)

        # Controlamos posibles errores
        if int(self.n_aux) not in (1,2,3,4):
            print("Error, debes ingresar un número del 1 al 4")
            print("Fin del proceso")
        else:
            # Función ingresada por el usuario
            self.fun = input("Ingresa tu función: ")
            
        # Adaptamos    
        if int(self.n_aux) != 1:
            self.fun = "np." + self.fun
        else:
            self.fun = self.fun

Nos vimos en la necesidad de crear un constructor para almacenar un valor para el atributo self.fun al cual le asignaremos la expresión de la función que ingrese el usuario más adelante con el método info_usuario.

In [131]:
# Probamos

prueba = menu()
print(prueba)

# Invocamos el método info_usuario()
prueba.info_usuario()
De que tipo es tu función:
______________________________
1: Algebraicas
2: Trigonométricas
3: Exponencial
4: Logarítmica
______________________________
Coloca un número del 1 al 4: 1
______________________________
Ingresa tu función: x**2

Veamos que expresión tiene asignado el objeto prueba en el atributo fun

In [132]:
prueba.fun
Out[132]:
'x**2'

De modo que la clase menú ah quedado realizada ( por el momento :) ).

  • Notemos que, si a la clase menu le agregamos como atributo el rango de graficación, entonces esta clase junto con la clase graficar tendrán los mismos atributos en el constructor. Además, de la clase menu podemos extraer la expresión de la función que ocupamos en la clase graficar. Así, podemos intuir que la clase graficar en realidad puede ser parte de la clase menu, o en otras palabras, la clase menu es superclase de la clase graficar. De tal manera, tendríamos que agregar solamente el atributo rango al constructor de la clase menu, pero eso lo podemos ingresar como se ingresa la expresión de la función en el método info_usuario()
In [199]:
# Creamos la clase menú

class menu:
    
    # Constructor
    def __init__(self):
        # Atributos de la clase
        self.fun = ""
        self.rango = ""
        
    # Creamos el método mensaje_inicial para mostrar el mensaje inicial
    def mensaje_inicial(self):
        self.cadena1 = "De que tipo es tu función:"
        self.cadena2 = "_" * 30
        self.cadena3 = "1: Algebraicas"
        self.cadena4 = "2: Trigonométricas"
        self.cadena5 = "3: Exponencial"
        self.cadena6 = "4: Logarítmica"
        self.cadena7 = "_" * 30
        return self.cadena1 + "\n" + self.cadena2 + "\n" + self.cadena3 \
    + "\n" + self.cadena4 + "\n" + self.cadena5 + "\n" + self.cadena6 \
    + "\n" + self.cadena7
    
    def info_usuario(self):
        # Número del tipo de función que ingresa el usuario
        self.n_aux = input("Coloca un número del 1 al 4: ")
        print("_" * 30)

        # Controlamos posibles errores
        if int(self.n_aux) not in (1,2,3,4):
            print("Error, debes ingresar un número del 1 al 4")
            print("Fin del proceso")
        else:
            # Función y rango ingresados por el usuario
            self.fun = input("Ingresa tu función: ")
            
            # Rango
            self.rango = input("Ingresa el rango de graficación: ")
            self.rango_inf = self.rango[self.rango.find("(") + 1: self.rango.find(",")]
            self.rango_sup = self.rango[self.rango.find(",") + 1: self.rango.find(")")]
            
        # Adaptamos    
        if int(self.n_aux) != 1:
            self.fun = "np." + self.fun
        else:
            self.fun = self.fun

Para después definir la clase hija graficar adaptando los cambios pertinentes. Notemos que self.rango será una cadena de texto, de modo que el código para definir las variables self.rango_inf y self.rango_sup extraen los valores numéricos de dicha cadena de texto; por ejemplo, si se ingresó la cadena "(0,-4)", entonces extraeremos sólo las cadenas "0" y "-4" para estas variables respectivamente. Continuando

In [200]:
# Creación de la clase hija graficar
class graficar(menu):
    
    # Sobreescritura del método init
    def __init__(self):
        super().__init__()

    
    # Método str 
    def __str__(self):
        return f'Rango:({self.rango_inf},{self.rango_sup})\nf(x) = {self.fun}'
    
    # Método para graficar
    def Graficador(self):
        
        # Rango
        x = np.arange(eval(self.rango_inf), eval(self.rango_sup), 0.01)

        # definimos la función f(x)=y
        y = self.fun

        # creamos la gráfica
        mplot.plot(x, eval(y))

        # mostramos la cuadrícula en el gráfico
        mplot.grid()

        # mostramos la gráfica
        mplot.show()

donde con la fucnión eval() podemos extraer un número de una cadena de texto; por ejemplo, la cadena "0" se transforma en el número 0 al emplear eval("0").

Finalmente probamos cada método de la clase graficar:

In [201]:
# instanciamos la clase
prueba = graficar()
In [202]:
# Mensaje inicial (proviene de la clase menu)
print(prueba.mensaje_inicial())
De que tipo es tu función:
______________________________
1: Algebraicas
2: Trigonométricas
3: Exponencial
4: Logarítmica
______________________________
In [204]:
# información dle usuario (proviene de la clase menu)
prueba.info_usuario()
Coloca un número del 1 al 4: 1
______________________________
Ingresa tu función: x**2
Ingresa el rango de graficación: (-1,1)
In [205]:
# método str (proviene de la clase graficar)
print(prueba)
Rango:(-1,1)
f(x) = x**2
In [206]:
# graficamos (proviene de la clase graficar)
prueba.Graficador()