0% encontró este documento útil (0 votos)
45 vistas36 páginas

Clase 31. Python 7

Este documento presenta información sobre la clase 31 de un curso de Python. La clase se centrará en los temas de herencia y polimorfismo en Python. Incluye un diagrama con las clases del curso, definiciones de conceptos como herencia, superclases y subclases, y ejemplos de herencia simple y múltiple implementada con clases.

Cargado por

Paquitas Bebes
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
45 vistas36 páginas

Clase 31. Python 7

Este documento presenta información sobre la clase 31 de un curso de Python. La clase se centrará en los temas de herencia y polimorfismo en Python. Incluye un diagrama con las clases del curso, definiciones de conceptos como herencia, superclases y subclases, y ejemplos de herencia simple y múltiple implementada con clases.

Cargado por

Paquitas Bebes
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
Está en la página 1/ 36

FULL STACK PYTHON

Clase 31
PYTHON 7
Herencia y polimorfismo
Les damos la bienvenida
Vamos a comenzar a grabar la clase
Clase 30 Clase 31 Clase 32

Colaboración entre clases y Herencia y Polimorfismo Manejo de excepciones y Módulos


Encapsulamiento y paquetes
● Herencia.
● Mensajes y Métodos. ● Polimorfismo. ● Manejo de excepciones.
● Colaboración entre clases. ● Herencia simple y múltiple. ● Errores vs. excepciones.
● Atributos de clase. ● Clases Abstractas. ● Múltiples excepciones,
● Composición. ● Diagrama de Clases. invocación y creación de
● Encapsular atributos y excepciones propias.
métodos. ● Módulos y packages.
● Decorators. ● Librerías.
● Collections, datetime, math y
módulo random.
Herencia
La herencia es un mecanismo de la Programación Orientada a
Objetos (POO) que permite crear clases nuevas a partir de clases
preexistentes.
Usando este concepto, las clases nuevas pueden tomar (heredar)
atributos y métodos de clases anteriores. Incluso pueden modificarlos
para modelar una nueva situación.
La clase que aporta los métodos y atributos para heredar se la
denomina clase base, superclase o clase padre, y a las que se
construyen a partir de ella clases derivadas, subclases o clases hijas.
Herencia, superclases y subclases
Una superclase es una clase superior o clase base. Si habíamos considerado
las clases como “plantillas” para construir objetos, siguiendo esa analogía las
superclases serían “plantillas de plantillas”.
A partir de una superclase se pueden definir subclases clases (clases
derivadas), cada una compartiendo atributos y métodos con la clase
superclase, aunque también pueden sumar métodos y atributos propios.
Para utilizar el concepto de herencia es necesario identificar una clase base
(la superclase) que posea los atributos y métodos comunes y luego crear
las demás clases heredando de ella (las subclases), extendiendo los métodos
y atributos que sean necesarios.
Herencia simple
Herencia simple
Este es un ejemplo muy simple del class Padre: # Superclase
concepto de herencia. El objeto hijo1 def __init__(self):
self.apellido = "Volpin"
ha heredado los métodos y atributos
de la superclases Padre, y podemos def llevar(self):
print("Papá me lleva al colegio.")
utilizarlos en hijo1. Vemos cómo
llevar() (de la superclase) funciona en class Hijo(Padre): # Subclase
def estudiar(self):
hijo1 de la misma manera que si print("Estoy en el colegio.")
fuese un método de la subclase. Lo hijo1 = Hijo() # Instanciamos hijo1
mismo ocurre con el atributo hijo1.llevar() # Papá me lleva al colegio.
hijo1.estudiar() # Estoy estudiando
apellido: estamos viendo el que ha print(hijo1.apellido) # Volpin (heredado)
heredado de la clase Padre.
Herencia, superclases y subclases
De una superclase se pueden construir muchas subclases derivadas, o clases
que heredan de ellas. Por ejemplo, de la superclase Persona podríamos
derivar Docente, Empleado, Cliente, Proveedor, o las que sean necesarias
para la aplicación que estemos desarrollando.

En el diseño de jerarquías de herencia no siempre es fácil decidir cuándo una


clase debe extender a otra. La regla práctica para decidir si una clase S puede
ser definida como heredera de otra T es que debe cumplirse que "S es un T".
Por ejemplo, Perro es un Animal, pero Vehículo no es un Motor.

Recordemos: las subclases heredan de las superclases.


Herencia simple
Veamos un ejemplo más complejo. Supongamos que necesitamos una clase
que sea capaz de instanciar objetos que representen a los alumnos de Codo
a Codo.

Dado que los alumnos comparten buena parte de sus atributos y métodos
con otras personas (alumnos de otras instituciones, docentes, etcétera) sería
útil contar con una superclase llamada Persona que contenga los atributos y
métodos comunes a todas las personas, y que la subclase AlumnosCodo
herede de ella esos elementos, y sume los que la superclase no tenga. Por
ejemplo, podría tener un atributo que indique en qué curso se encuentra
matriculado, o una lista con los trabajos prácticos que ha realizado.
Herencia simple | Superclase
La definición de la superclase Persona no posee ninguna característica
particular. Se define como una clase más:
Superclase Persona
class Persona: # Clase que representa una persona.
def __init__(self, identificacion, nombre, apellido, dni):
#Constructor de Persona
self.id = identificacion # Atributo de instancia
self.nombre = nombre # Atributo de instancia
self.apellido = apellido # Atributo de instancia
self.dni = dni # Atributo de instancia

# Método str:
def __str__(self):
return f"{self.id} - DNI - {self.dni} {self.apellido}, {self.nombre}"
Herencia simple | Superclase
Esta clase Persona, que será la superclase de nuestro ejemplo, posee varios
atributos de instancia y un método. A pesar de que la utilizaremos como
superclase, aún es posible instanciar objetos Persona:

Programa principal Terminal


# Programa principal:
p1 = Persona(3, "Carlos", "Kleiber", 32456812)
print(p1) 3 - DNI - 32456812 Kleiber, Carlos

El método __str__ de la superclase Persona muestra la cadena de texto que


contiene una representación de los atributos del objeto p1. Este método
también será heredado por la subclase AlumnoCodo.
Herencia simple | Subclase
La definición de la subclase AlumnoCodo incluye en su declaración el
argumento “Persona”, que hace referencia a la superclase. Utiliza, en su
constructor, el método constructor de la superclase. Vemos que agrega un
nuevo atributo de clase, “curso”, que no está presente en la superclase
Persona. La subclase AlumnoCodo hereda el método __str__ de la superclase.
Subclase AlumnoCodo
class AlumnoCodo(Persona): # Parámetro: superclase
# Clase que representa a un alumno de Codo a Codo
def __init__(self, identificacion, nombre, apellido, dni, curso):
# Constructor de Alumno
# Invocamos al constructor de la superclase:
Persona.__init__(self, identificacion, nombre, apellido, dni)
# agregamos el atributo propio del alumno
self.curso = curso
Herencia simple | Subclase
En este punto, tenemos la superclase y la subclase definidas. Vimos que
podíamos instanciar objetos de la superclase. Y ahora también podemos
hacerlo con subclase: ¿Curso?
Programa principal Terminal
# Programa principal:
a1 = AlumnoCodo(1, "Eliana", "Vera", 27416319,
"Full Stack") 1 - DNI - 27416319 Vera, Eliana
print(a1)

Al imprimir el objeto a1, estamos usando el método __str__ de la superclase


Persona, que ha sido heredado por la subclase AlumnoCodo. Es por ello que
el curso al que pertenece no se muestra. Pero es posible agregar en la
subclase un nuevo método __str__ que solucione este problema.
Herencia simple | Subclase
Agregamos a la subclase AlumnoCodo su propio método __str__ , que
reemplazará al heredado de la superclase:
Método __str__ de la Subclase AlumnoCodo
# Método str propio de la subclase AlumnoCodo:
def __str__(self):
cadena = f"{self.id} - DNI - {self.dni} \n"
cadena += f"{self.apellido},{self.nombre} \n"
cadena += f"Carrera: {self.curso}"
return cadena

Programa principal Terminal


p1 = Persona(3, "Carlos", "Kleiber", 32456812) 3 - DNI - 32456812 Kleiber, Carlos
print(p1)
a1 = AlumnoCodo(1, "Eliana", "Vera", 27416319, 1 - DNI - 27416319
"Full Stack") Vera,Eliana
print(a1) Carrera: Full Stack
Herencia simple y herencia múltiple
Los casos que hemos analizado tienen lo que se conoce como herencia
simple, que tiene lugar cuando una clase derivada (subclase) hereda
atributos y métodos de una única clase base (superclase).

La herencia múltiple ocurre cuando una subclase deriva de dos o más clases
base. Al escribir el código de la subclase, las superclases de las que heredará
métodos y atributos se indican de la misma forma, separando cada una con
una coma.

Por ejemplo, una subclase Hijo podría heredar de dos superclases: Padre y
Madre.
Herencia múltiple
Herencia múltiple
Vemos como el objeto hijo1 ha class Padre: # Superclase 1
heredado los métodos de las def llevar(self):
print("Papá me lleva al colegio.")
superclases Padre y Madre.
class Madre: # Superclase 2
Podemos utilizar hijo1 los métodos def programar(self):
print("Mamá programa en Python.")
propios o los de las superclases. En
caso de que ambas superclases class Hijo(Padre, Madre): # Subclase
def amar(self):
tengan un método con el mismo print("Quiero a mis padres")
nombre, se hereda el que se escriba hijo1 = Hijo() # Instanciamos hijo1
primero en la declaración (Padre en hijo1.llevar() # Papá me lleva al colegio.
hijo1.programar()# Mamá programa en Python.
el ejemplo): hijo1.amar() # Quiero a mis padres
Clases abstractas
Un concepto importante en Programación Orientada a Objetos es el
de las clases abstractas. Son clases en las que se pueden definir tanto
métodos como propiedades, pero que no pueden ser instanciadas
directamente. Solamente se pueden usar para construir subclases
(como si fueran moldes), permitiendo tener una única implementación
de los métodos compartidos. Esto evita la duplicación de código.
Las clases abstractas definen una interfaz común para las subclases.
Proporcionan atributos y métodos comunes para todas las subclases
evitando así la necesidad de duplicar código, imponiendo además los
métodos que deben ser implementados para evitar inconsistencias
entre las subclases.
Clases abstractas
Propiedades de las clases abstractas:
● No pueden ser instanciadas, simplemente proporcionan una interfaz
para las subclases derivadas evitando así la duplicación de código.
● No es obligatorio que tengan una implementación de todos los métodos
necesarios. Pudiendo ser estos abstractos. Los métodos abstractos son
aquellos que solamente tienen una declaración, pero no una
implementación detallada de las funcionalidades.
● Las clases derivadas de las clases abstractas deben implementar
necesariamente todos los métodos abstractos para poder crear una clase
que se ajuste a la interfaz definida. En el caso de que no se defina alguno
de los métodos no se podrá crear la clase.
Clases abstractas | Creación
Para poder crear clases abstractas en Python es necesario importar la clase
ABC y el decorador abstractmethod del módulo abc (Abstract Base
Classes).
Clase abstracta
Si se intenta crear una instancia de la
from abc import ABC, abstractmethod
clase Animal, Python no lo permite.
class Animal(ABC):
@abstractmethod Si la clase no hereda de ABC o
def mover(self):
pass # permite “pasar” sin contenido contiene por lo menos un método
perro = Animal()
#TypeError: Can't instantiate abstract class abstracto, Python permitirá crear
Animal with abstract method mover instancias de la clase.
Clases abstractas
Las subclases tienen que implementar todos los métodos abstractos
definidos en la clase abstracta, o Python no permitirá instanciar la clase hija.

Desde los métodos de las subclases se pueden Clase abstracta


utilizar las implementaciones de la clase class Animal(ABC):
@abstractmethod
abstracta con el comando super() seguido del def mover(self):
pass
nombre del método. Por ejemplo:
@abstractmethod
Método de la subclase def comer(self):
def emitir_sonido(self): print("El animal come")
super().emitir_sonido()
Clases abstractas | Ejemplo
Crearemos una clase abstracta Animal de la que heredarán métodos dos
subclases (Gato y Perro).

● No podemos instanciar directamente objetos de la clase Animal, ya que


se trata de una clase abstracta.
● La clase Animal debe heredar de ABC, e implementar solo métodos
abstractos, para que funcione como clase abstracta.
● Gato y Perro completan los métodos abstractos de Animal, cada uno con
la característica propia de los objetos de esas clases.
Clases abstractas | Ejemplo
Clase abstracta Animal Subclase Gato Clase abstracta Animal
from abc import ABC, abstractmethod class Gato(Animal): class Perro(Animal):

class Animal(ABC): def mover(self): def mover(self):


@abstractmethod print("El gato se print("El perro se está
def mover(self): mueve.") moviendo.")
pass
def emitir_sonido(self): def emitir_sonido(self):
@abstractmethod super().emitir_sonido() super().emitir_sonido()
def emitir_sonido(self): print("Miau!") print("Guau, Guau!")
print("Animal dice: ",
end="")

Los métodos mover() y emitir_sonido() de las subclases Gato y Animal


completan o complementan el código disponible en los métodos abstractos
homónimos de la clase abstracta Animal. Solo nos resta instanciar objetos y
ver cómo se comportan.
Clases abstractas | Ejemplo
Programa Principal Consola
g1 = Gato()
g1.mover() El gato se mueve.
g1.emitir_sonido() Animal dice: Miau!
El perro se está moviendo.
p1 = Perro() Animal dice: Guau, Guau!
p1.mover()
p1.emitir_sonido()

g1.mover() ejecuta el código correspondiente al método de la clase abstracta,


y luego el propio de la subclase Gato. Lo mismo ocurre con emitir_sonido().

Cómo es lógico, la subclase Perro hace lo propio, y modifica ambos métodos


abstractos de la clase abstracta Animal.
Polimorfismo
El polimorfismo es uno de los pilares básicos en la Programación
Orientada a Objetos. El término polimorfismo tiene origen en las
palabras poly (muchos) y morfo (formas), y aplicado a la programación
hace referencia a que los objetos pueden tomar diferentes formas.

Esto significa que objetos de diferentes clases pueden ser accedidos


utilizando la misma interfaz, mostrando un comportamiento distinto
(tomando diferentes formas) según cómo sean accedidos.
Polimorfismo
En lenguajes de programación como Python, que tiene tipado dinámico, el
polimorfismo va muy relacionado con el duck typing (dak tiping) o “tipado
del pato”, que se resume en una frase: “Si camina como un pato y habla
como un pato, entonces tiene que ser un pato”.

Al ser Python un lenguaje de tipado dinámico no es necesario que los objetos


compartan una interfaz, simplemente basta con que todos tengan los
métodos que se quieran utilizar.

Vamos, paso a paso, a crear un ejemplo.


Polimorfismo | Ejemplo
Definimos tres clases, Pato, Perro y Cerdo, todas con un método hablar().
Cada una de las clases implementa la versión que necesita del método, pero
es importante ver que en todas tienen el mismo nombre.
Clases Pato, Perro y Cerdo
class Pato:
def hablar(self):
print("¡Cuac! "*3)

class Perro:
def hablar(self):
print("!Guau! "*3)

class Cerdo:
def hablar(self):
print("!Oink! "*3)
Polimorfismo | Ejemplo
Programa principal
El programa principal define una
def hacer_hablar(x):
x.hablar() función que recibe un objeto, y utiliza
#Creamos un pato y lo hacemos "hablar:"
(sin importar cual sea) su método
mi_pato = Pato() hablar().
hacer_hablar(mi_pato)

#Creamos un perro y lo hacemos "hablar:" Esto es posible gracias al polimorfismo:


mi_perro = Perro() no es necesario escribir código para
mi_perro.hablar()
acceder a un mismo atributo o método
#Creamos un cerdo y lo hacemos "hablar:"
mi_cerdo = Cerdo()
de objetos de distinta clase, cuando
mi_cerdo.hablar() estos tienen el mismo nombre.
Diagrama de clases
Un diagrama de clases en Lenguaje Unificado de Modelado (UML) es
un tipo de diagrama de estructura estática que describe la estructura
de un sistema mostrando las clases del sistema, sus atributos,
operaciones (o métodos), y las relaciones entre los objetos.

UML proporciona mecanismos para representar los miembros de la


clase, como atributos y métodos, así como información adicional sobre
ellos.
Diagramas de clases
En los lenguajes orientados a objetos, los algoritmos se expresan definiendo
'objetos' y haciendo que los objetos interactúen entre sí. Los lenguajes
orientados a objetos dominan el mundo de la programación porque
modelan los objetos del mundo real, y la relación entre sus clases, atributos y
métodos puede modelarse mediante UML.

La figura de clase en sí misma consiste en un rectángulo de tres filas. La fila


superior contiene el nombre de la clase, la fila del centro contiene los
atributos de la clase y la última expresa los métodos o las operaciones que la
clase puede utilizar.
Diagramas de clases
Cada atributo y método de una clase está ubicado en una línea separada:

Persona Cliente Banco


+ Nombre + ID + Nombre
+ DNI - Saldo - Clientes[]
- __init__ - __init__ - __init__
+ comer + depositar + agregar_cliente
+ trabajar + retirar + cerrar_cuenta
+ descansar # ver_saldo + ver_balance

La relación de herencia se simboliza mediante una línea de conexión recta


con una punta de flecha cerrada que señala a la superclase. La relación
predeterminada entre clases se representa mediante una línea recta.
Diagramas de clases
Para especificar la visibilidad de un miembro de la clase (es decir, cualquier
atributo o método), se coloca uno de los siguientes signos delante de ese
miembro:

● Público (+)
● Privado (-)
● Protegido (#)

El siguiente ejemplo proporciona un diagrama de clases que representa


gráficamente las relaciones entre las clases de un sistema administrativo
hotelero.
Diagramas de clases
Programa principal
El diagrama de la izquierda, a pesar
def hacer_hablar(x):
x.hablar() de su complejidad, nos proporciona
#Creamos un pato y lo hacemos "hablar:"
una gran cantidad de información
mi_pato = Pato() sobre las clases, sus métodos y
hacer_hablar(mi_pato)
atributos, y sus relaciones en un
#Creamos un perro y lo hacemos "hablar:" formato de fácil lectura. +info
mi_perro = Perro()
mi_perro.hablar()

#Creamos un cerdo y lo hacemos "hablar:"


mi_cerdo = Cerdo()
mi_cerdo.hablar()
Material extra
Artículos de interés
Material extra:
● ¿Qué es el Duck Typing en Python?
● Herencia, clases abstractas y polimorfismo
● Diagramas de clase
Videos:
● Herencia y herencia múltiple en Python
● Polimorfismo en Python
● Clases abstractas
No te olvides de dar el presente
Recordá:
● Revisar la Cartelera de Novedades.
● Hacer tus consultas en el Foro.
● Realizar los Ejercicios obligatorios.

Todo en el Aula Virtual.

También podría gustarte