Polimorfismo y sobrecarga de métodos en Python

Hoy vamos a continuar con Clases en python y vamos a hablar del famoso “polimorfismo“, una caracteristica aplicada en muchos lenguajes de programación que permiten el paradigma OOP (Programación Orientada a Objetos.)


Me gusta para recordarlo traducir rapidamente “polimorfismo” como “Multiples formas“, así pasamos de una pitón a un pulpo 😛

Polimorfismo en Python Utilizando polimorfismo podemos invocar un mismo método de diferentes objetos y obtener diferentes resultados según la clase de estos.

Si no me entiendes una mierda, es normal, sigue leyendo…

Esto significa que podemos llamar a un método exactamente igual a otro y el interprete automáticamente detectará a cual de ellos nos referimos según diversos parámetros, por ejemplo el tipo de dato que pasamos como argumento al momento de llamarlo, la clase a la que pertenece, o hasta podemos especificarle a que método nos referimos. El polimorfismo esta estrictamente ligado al concepto de Herencia y a como lo trabaje el lenguaje, puedes leer sobre polimorfismo en Java también y verás que se trata de conceptos muy similares pero ambos lenguajes lo trabajan diferente.

El polimorfismo es una cuestión de organización y de buena practica para el programador que trabaja con muchos objetos y métodos. Permitiendo que el desarrollador no deba escribir, pensar y recordar muchos nombres de métodos diferentes, sino que pueda llamar al método del objeto adecuado con el mismo nombre que llamaría a otros.

El polimorfismo se utiliza muy a menudo, más de lo que somos conscientes. Recordemos que en Python todo es un objeto, lo que hace muy probable que aún sin recurrir a clases utilicemos polimorfismo, por ejemplo tan solo la función print() imprime diversos tipos de objetos sin necesidad de que especifiquemos nada. y esto también es posible gracias a una de las propiedades de Python que continuamente recalco en mi blog el “tipado dinamico“.

Vamos a ver un ejemplo en código y en en una especie de diagrama de como trabaja el polimorfismo en python:

 

Polimorfismo: Mismo nombre de Método en diferentes clases y objetos:

En el ejemplo a continuación vemos el mismo nombre de Método en diferentes clases. Al momento de crear una instancia y llamar al método vemos que aunque se llamen igual el interprete se guía por el nombre de la clase.

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# polimorfismo.py
#
# Copyright 2020 <<Pyro>>

class Marino(): #Clase Padre
    def hablar(self): #Método Hablar
        print ("Hola..")

class Pulpo(Marino): #Clase Hija
    def hablar (self): #Método Hablar
        print ("Soy un Pulpo")

class Foca(Marino): #Clase Hija
    def hablar (self, mensaje): #Método Hablar
        print (mensaje)

Pulpito = Pulpo() #Instancia
Foca = Foca() #Instancia

Pulpito.hablar() #Llamamos al método
Foca.hablar("Soy una foca, este es mi mensaje") #Llamamos al método

 

Resultado:

Soy un Pulpo
Soy una foca, este es mi mensaje

Como podemos ver en el ejemplo el nombre de método es el mismo, cuando lo llamamos Python sabe cual ejecutar porque se lo dice la clase a la que pertenece el objeto (en ese caso pulpito, pertenece a la clase “pulpo” por ende obviamente llamará al método hablar de dicha clase y no de ninguna otra.).

Claro pero… la clase Padre (Marino) también tiene un método hablar() el cual no es ejecutado. Lo puse allí a propósito, para que recuerdes algo que ya vimos en el blog en la parte de Herencia Múltiple, el MRO (Method Resolution Order)el árbol de ancestros que podríamos traducir a Resolución de ordenes de métodos y es el que indica la forma en que el interprete navega buscando los métodos dentro de las clases. Para acudir al método de la clase padre desde la clase hija recordemos que podemos usar la función Super() 😉

En caso de que quisieras imprimir el método hablar() de la clase padre antes del método hablar() de la clase hija, puedes hacerlo a través de super(), o utilizando decoradores “propiedades en python” como vimos en la lección anterior para interceptarlo.

Hasta aquí vimos que se puede tener el mismo nombre de método en diferentes clases. Pero también se puede dar en el polimorfismo lo que se llama Sobrecarga de métodos, o tener varios métodos con el mismo nombre dentro de la misma clase.

 

Sobrecarga de Métodos: Mismo nombre de método en la misma clase.

comparar java
¿Otra vez comparando Python con Java!!??

En Python la sobrecarga de métodos (overloading) como tal, no existe. Quienes vienen de otros lenguajes como Java se encuentran con algunas confusiones puesto que es algo muy común en ese lenguajeEn python, la sobrecarga resulta absurda, aunque hay quienes han redactado sobre ello asegurando que es “una buena práctica en cualquier lenguaje”..En python no lo es coño!

Pero podemos recurrir a diferentes formas de emularla en el caso de que alguno quiera. Pero antes expliquemos de que trata la “sobrecarga de métodos esa” para quienes no vienen de otro lenguaje.:

 

En criollo: “La sobrecarga de métodos o comúnmente llamada Overloading es un práctica que consiste en tener diferentes métodos con el mismo nombre en una misma clase, y que el intérprete o compilador logre diferenciarlos por los tipos de datos que se envían como argumentos para los parámetros.”

Claro en JAVA, eso significa que puedo tener dos métodos exactamente con el mismo nombre pero con diferentes parámetros. Por lo que se sabrá a que método va dirigido el llamado según el “tipo de argumento” que enviamos:

Polimorfismo en Java

 

En el ejemplo anterior si envío dos números como parámetros sabrá que intento referirme al tercer Método over(). Aquí puedes leer sobre Sobrecarga en JAVA con ejemplos muy claros y sencillos.

Perdoname por meter Java aquí, en serio. Pero quiero que comprendas los conceptos más allá de que en Python no los utilices, porque son de utilidad comprenderlos para evitarse luego preguntas “¿Qué lenguaje me conviene aprender?, “¿Por qué no puedo hacer esto mismo en Python, ni esto de Python en JAVA?”

 

Esto del ejemplo en Python no es posible principalmente porque ya deberías saberlo.. “La dinamicidad” de python causa un conflicto al no saber que tipo de variables serian en el caso del ejemplo “a” y “b”. Podrías meter un string con un entero y Python se quebraría… Cómo ves el ejemplo anterior era en JAVA donde se especifica el tipo de parámetro al momento de crear el método (INT).

En realidad en Python, tampoco es que se necesite la sobrecarga, pero puede emularse de la siguientes dos maneras:

 

Emulando sobrecarga de métodos en python

Primeramente una forma que encuentro agradable es utilizar condicionales al momento de crear el método para autodetectar el tipo de dato que recibe como argumento, fíjate:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
#  polimorfismo.py
#  
#  Copyright 2020 <<Pyro>>

class testclass():                             #Clase de ejemplo
	def over(self, a):                     #Creamos el método
		if type(a) == int:             #Condicional para comprobar
			print ("A es entero")  #el tipo de dato
		elif type(a) == str:
			print ("A es texto, ingresaste texto! no seas mamón!")

Test = testclass()                              #Instancia

a = (input("Ingresa un valor entero"))          #Pedimos un valor al user
Test.over(a)                                    #Llamamos el método con el
                                                #valor que ingreso el usuario

El resultado varía según el tipo de dato que ingresa el usuario, yo lo hice así pero si no existiera el input tu dependiendo el valor de la variable podrías ejecutar un código u otro pasando diferentes valores:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
#  polimorfismo.py
#  
#  Copyright 2020 <<Pyro>>

class testclass():                        #Clase de ejemplo
	def over(self, a):                    #Creamos el método
		if type(a) == int:                #Condicional para comprobar
			print ("A es entero")         #el tipo de dato
		elif type(a) == str:
			print ("A es texto, ingresaste texto! no seas mamón!")
		else:
			print ("Qué diabl0s?")

Test = testclass()                        #Instancia

Test.over(1)                              #Llamamos al método con dif valores
Test.over("a")
Test.over(12)
Test.over(000.1)

Resultado:

A es entero
A es texto, ingresaste texto! no seas mamón!
A es entero
Qué diabl0s?

Vemos que funciona bien. Sea el tipo de dato de “a” será el código a ejecutarse como si fueran diferentes métodos de igual nombre. Pero en realidad esto tampoco es sobrecarga pura de Métodos en Python, y esta vista como absurda e innecesaria. En Python no se deben tener dos métodos con el mismo nombre ni llamar a un mismo método con diferentes tipos de parámetros salvo sea estrictamente necesario.

 

Pero en el caso estricto que quieras usar sobrecarga si o si!?. Pues existe un módulo llamado overloading que puedes utilizar!

 

¿Cuándo nos es útil el polimorfismo o la sobrecarga en python?

El polimorfismo en realidad si nos es útil cuando necesitamos utilizar diversos métodos con el mismo nombre en varias clases. Lo que significa que gracias al “polimorfismo” podemos repetir el mismo nombre de método dentro de diferentes clases aunque se Hereden. También gracias a él podemos llamar métodos de clases padres desde clases hijas. Pero en el caso de la sobrecarga de métodos en realidad se desaconseja en Python crear el mismo método dentro de la misma clase.

En conclusión en Python:

  • El mismo nombre de Métodos en diferentes clasesSI!. (Polimorfismo)
  • El mismo nombre de Métodos en la misma claseNO! (Sobrecarga)

 

Polimorfismo en Python Utilizando polimorfismo podemos invocar un mismo método de diferentes objetos y obtener diferentes resultados según la clase de estos.

Polimorfismo es diferente a Sobrecarga de métodos!

En la Wikipedia se define polimorfismo: propiedad por la que es posible enviar mensajes sintácticamente iguales a objetos de tipos distintos. El único requisito que deben cumplir los objetos que se utilizan de manera polimórfica es saber responder al mensaje que se les envía.

Sobrecarga de Métodos, es utilizar el mismo nombre de método para diferentes tipos de parámetros dentro de la misma clase. Y no es posible nativamente, ni recomendado en Python.

cuarentena

Espero haya quedado claro la diferencia entre ambos conceptos y porque no deben romperse la cabeza buscándole la vuelta en Python..

 

Un cordial saludo y me despido amablemente; por cierto, les recomiendo aprovechen la cuarenta (si has leído “cuarentena” ya estás traumado..) para reforzar conocimientos y practicar programación!. Aquí estaré aportando contenido a menudo como siempre jaja!. Vale esta vez es enserio, escribiré más a menudo!

 


Compartir es agradecer! :)