Curso de programacion en python3 : 07 - Orientacion a objetos

Esta entrada es parte de una serie, puedes ver la primera aquí

Una de las mejores cosas que tiene python es que podemos leer todo su código fuente, entender un lenguaje desde sus cimientos es el mayor regalo que un programador que quiere especializarse en un solo lenguaje puede tener.

Como sabemos el lenguaje es interpretado y los tipos de datos no se necesita que sean declarados, si nos ponemos a pensar desde el lado de un programador que quiere hacer su propio lenguaje, resulta bastante complicado de desarrollar, ¿como se puede conseguir que cada variable declarada, que necesita tener un tipo de dato asociado, sea creada de forma correcta?, hasta el momento el conocimiento que hemos adquirido en este curso es insuficiente para crear un lenguaje de programación (claramente al finalizar el curso solo sabremos como funciona python, pero quiero poner un ejemplo fuerte para entender la orientación a objetos y su importancia).

Si deseamos que algo se pueda generalizar(usar para cualquier cosa), necesitamos una solución específica que a la hora de ser usada, pueda modificarse de forma simple, las matemáticas dicen con exactitud cuales son las condiciones para generalizar y por tanto con algo llamado teoría que conjuntos podemos ir construyendo jerarquías(o un árbol de elementos para ser mas exacto) donde existe una raíz y vamos a añadir la cantidad de elementos necesaria a esta raíz hasta que la jerarquía cumpla nuestros requerimientos.

Las variables que se utilizan en lenguajes de programación fuertemente tipados(aquellos que requieren declarar el tipo de dato de una variable) son en realidad almacenadas dentro de una estructura del lenguaje llamada heap y ocupan un espacio fijo dentro de RAM, las variables en python, a pesar de ocupar espacios fijos, se almacenan todas de forma aleatoria en la RAM, no todas nuestras variables en python van a ocupar espacios consecutivos, la única forma de que ocupen espacios de memoria consecutivos es utilizar un arreglo como vimos antes, la memoria de un arreglo debe ser consecutiva del primero al ultimo de sus componentes.

La definición de objeto es: "aquel que ocupa un espacio determinado en un tiempo determinado", por tanto un objeto es cualquier variable en python, en otros lenguajes las variables ocupan un espacio común y se apilan en orden, python desde la primera variable permite que el sistema operativo asigne como quiera donde van a estar esas variables.

Ahora que entendemos la definición de objeto, hay que señalar que la orientación a objetos(POO) debe ser una forma distinta de resolver problemas utilizando la generalización, es decir, la POO fue creada haciendo jerarquías para que nosotros pudiéramos hacer jerarquías propias que resuelvan de formas muy simples y ordenadas, problemas muy complicados y confusos.

Para generalizar necesitamos crear una maqueta (molde, estructura) que sea capaz de convertirse en un objeto (elemento en memoria), esta maqueta se llama clase, una clase es un conjunto de atributos(variables) y comportamientos(funciones o métodos), que comparten espacio, por tanto una clase no es un lugar en donde guardar datos, es como un ser viviente que tiene caracteristicas o atributos propios y existen formas determinadas para llegar a esos atributos, hagamos un ejemplo.

/*Creacion del archivo Persona.py*/

#coding:utf-8
#!/usr/local/bin/python3
class persona():
__nombre = ""
__apellido = ""
__edad = 0
def __init__(self, nombre, apellido, edad):
self.setNombre(nombre)
self.setApellido(apellido)
self.setEdad(edad)
def setNombre(self, nombre):
self.__nombre = nombre
def getNombre(self):
return self.__nombre
def setApellido(self, apellido):
self.__apellido = apellido
def getApellido(self):
return self.__apellido
def setEdad(self, edad):
try:
edad = int(edad) #intenta convertir el contenido de edad a un tipo numerico
except:#captura cualquier error
print("La edad debe ser numerica")
self.__edad = edad #pasa la edad de el objeto temporal al atributo global __edad
def getEdad(self):
return self.__edad
def mostrarDatos(self):
print("La persona se llama", self.getNombre(), "su apellido es", self.getApellido(), "su edad es", self.getEdad())
/*Fin de clase persona*/

Esto es una clase, que no es un objeto, será uno en el momento que decidamos instanciar un objeto de esta clase, sin instancia no hay paraíso y se quedará en una clase, en una simple maqueta o molde del cual sacaremos nuestros objetos, el archivo deberá llamarse Persona.py, esto por que todo el código ha sido probado y cualquier cambio de nombre invalida el resto del código que veremos, estamos ya separando nuestro código en distintos archivos por motivos muy simples, el primero es que mas archivos nos permiten organizar el código de nuestro proyecto, cada uno de esos archivos puede dañarse por separado, si se corrompe uno, el resto de nuestro código puede salvarse y lo mas importante, los errores existirán en cada archivo independiente, para solucionarlos solo será necesario ir a donde se generó el error en vez de buscar entre miles de lineas de código.

Lo primero que vemos es la palabra class, esta nos indica el ámbito de la clase, todo lo que esté identado a la altura de esta etiqueta, le pertenecerá, es recomendable declarar los atributos o variables de nuestra clase en la parte de arriba, el lector del código lo primero que necesita saber es cuales son los atributos de nuestra clase para entender todo el siguiente código.

Al final agregaremos los métodos, que serán la forma estándar de acceder a los atributos(variables) de la clase, la forma debe ser por los métodos, python nos dice que hay que colocar dos guiones bajos detrás de cada atributo para hacer que no sea fácil de encontrar y así tener que usar los métodos obligatoriamente, nuestros objetos no son almacenes de información, deberán ser criaturas que tienen un comportamiento definido, no debemos ser como ladrones que toman la información sin ayuda de la persona, cuando queremos saber algo de alguien, tenemos que preguntar primero de la forma adecuada, otros lenguajes se toman la OO mas en serio, python la utiliza pero no permite bloquear nuestros atributos para que sean privados, así que no hay garantías de que alguien entre y tome la información, pero el paradigma de programación nos recomienda esto y tiene mucho sentido hacerlo de esta forma, conseguimos así un código mas limpio y un orden de ejecución con verificaciones puesto que los datos entrarán y saldrán de la forma predefinida, el siguiente tema a tratar será la herencia.

/*Creacion del archivo Maestro.py*/

#coding:utf-8
#!/usr/local/bin/python3 

from Persona import persona as Persona
class maestro(Persona):
__persona = ""
__materiaQueImparte = ""
def __init__(self, nombre, apellido, edad, materia):
self.__persona = Persona(nombre, apellido, edad) #se guarda un objeto del tipo persona en la variable global __persona
self.setMateria(materia) #se añade la materia que es atributo de un maestro
def setMateria(self, materia):
self.__materiaQueImparte = materia
def getMateria(self):
return self.__materiaQueImparte
def mostrarDatos(self):
self.__persona.mostrarDatos()
print("Imparte la materia", self.getMateria() )
/*Fin del archivo*/

Heredamos las características de persona, importando la clase y referenciando los atributos hacia la súper clase, añadiendo las características de la súper clase a la clase hija sin añadir una sola linea de código repetida, para finalizar añadimos una clase principal y probamos el código resultante.

/*Creacion de archivo Main.py*/

#!/usr/local/bin/python3
#coding:utf-8

#del archivo X importamos la clase X como etiqueta X
from Persona import persona as Persona
from Maestro import maestro as Maestro
def menu():
    opcion = input("1 - Crear una persona \n2 - Crear un maestro\n3 - salir\n")
    if(opcion == '1'):
        crearPersona()
    if(opcion == '2'):
        crearMaestro()
    else:
        exit()   

def crearPersona():
    laPersona = Persona(input("ingrese el nombre\n"), input("ingrese el apellido\n"), input("ingrese la edad\n"))
   
def crearMaestro():
    elMaestro = Maestro(input("ingrese el nombre\n"), input("ingrese el apellido\n"), input("ingrese la edad\n"), input("ingrese la materia\n"))

if(__name__ == '__main__'):
    while(True):
        menu()

/*fin de Main*/

Este programa tiene un ciclo infinito para crear los objetos, una vez creados, se eliminan por que no los estamos almacenando en self, aunque podríamos, también podríamos poner una lista e ir agregando los objetos, pero la idea era ver como funciona la orientación a objetos, las estructuras de datos ya las vimos en su momento y queda de tarea hacer que este código sea mas útil.

Llevo mucho sin publicar sobre python y ya me estaba poniendo nervioso, debería escribir por aquí mas seguido, pero de alguna manera se me olvida que tengo un blog por temporadas, lo importante es que hay salud y lenguajes de programación para seguir aprendiendo, la próxima entrada en construcción será mas entretenida y nos ayudará a automatizar trabajos, lo mas importante es que tiene muchas utilidades, desde ahorrarnos trabajo de ratón, hasta hacer trampa en ciertos juegos, esto ultimo no lo recomiendo, pero yo solo voy a explicar como funciona una librería de python, los malos usos que se le den no están relacionados con mis intenciones enseñanza :D

Comentarios

Entradas populares de este blog

Hablemos de difamación, parafilias y denuncias bien hechas

Criticamos a pablito: "Atrapado en el cuerpo equivocado"

El fruto de una era: Antiintelectualismo moderno