Herança é obrigatória no polimorfismo em Python?
POLIMORFISMO
O polimorfismo em classes é um conceito fascinante! Ele torna o código mais elegante e flexível permitindo que objetos de diferentes classes respondam ao mesmo método de maneiras distintas.
Polimorfismo com funções e objetos de diferentes classes
Um exemplo clássico de polimorfismo em Python é o método `len(obj)`, que pode ser aplicado a objetos como `strings`, `lists`, `dicts` e `tuples`. Cada tipo implementa esse método de forma diferente:
print(len('Fulaninho de Abreu')) # saída: 18
print(len(['aluno', 'professor'])) # saída: 2
print(len({'nome':'João'}, 'idade': 30)) # saída: 2
print(len((1, 2, 3))) # saída: 3
As classes desses objetos não possuem relação de herança entre si, mas todas implementam o método `__len__()`, o que torna esse comportamento possível.
Polimorfismo em Ação
Imagine quando você tem duas classes `Cachorro` e `Gato`. Ambas possuem um método `fazer_som()`:
class Cachorro:
def fazer_som(self):
print('Au au!')
class Gato:
def fazer_som(self):
print('Miau!')
def fazer_animal_fazer_som(animal):
animal.fazer_som()
fazer_animal_fazer_som(Cachorro()) # saída: Au au!
fazer_animal_fazer_som(Gato()) # saída: Miau!
A função `fazer_animal_fazer_som()`não precisa saber o tipo do objeto. Basta que ele tenha o método fazer_som().
Polimorfismo com Herança
A herança dá ainda mais poder ao polimorfismo. Veja este exemplo com formas geométricas:
class Forma:
def calcular_area(self):
pass
class Retangulo(Forma):
def __init__(self, largura, altura):
self._largura = largura
self._altura = altura
def calcular_area(self):
return self._largura * self._altura
class Circulo(Forma):
def __init__(self, raio):
self._raio = raio
def calcular_area(self):
return 3.14159 * self.raio**2
def mostrar_area(forma)
print(f"A área de {forma.__class__.__name__} é: {foram.calcular_area()} u.a.")
Chamamos o mesmo método `calcular_area()` e cada classe o executa conforme sua lógica.
Duck Typing (Tipagem Dinâmica)
Python adota o "duck typing":
Se um objeto anda como pato, e grasna como pato, então para nós, ele é um pato.
Veja:
class Pato:
def quack(self):
print('Quack!')
class PessoaQueImitaPato:
def quack(self):
print('Quack quack!')
def fazer_quack(entidade):
entidade.quack()
fazer_quack(Pato()) # saída: Quack!
fazer_quack(PessoaQueImitaPato()) # saída: Quack quack!
Não importa a classe, contanto que o método exista.
Aplicações do Polimorfismo em Ciência de Dados
- Processamento de diferentes tipos de dados
Você pode criar classes como CarregadorCSV, CarregadorJSON, CarregadorSQL — todas com o método carregar_dados(). Assim, o código principal não precisa saber a origem dos dados.
- Modelos de Machine Learning
Modelos como regressão, classificação e clustering podem seguir uma interface comum com métodos treinar(), avaliar() e prever(), facilitando testes e comparações.
- Pré-processamento
Cada técnica (normalização, imputação, escalonamento) pode ser uma classe com o método aplicar(). Isso organiza e reaproveita o código.
- Visualização
Você pode criar classes GraficoBarra, GraficoPizza, GraficoDispersao — todas com o método plotar(). Isso desacopla o tipo de gráfico da lógica do programa.
Conclusão
O polimorfismo:
- Abstrai a complexidade de diferentes implementações;
- Facilita manutenção e testes;
- Promove reutilização e modularidade;
- Aumenta a clareza e a extensibilidade do código.
Em Ciência de Dados, isso se traduz em pipelines mais organizados, códigos mais reutilizáveis e soluções mais sustentáveis a longo prazo.
Até a próxima pessoal😊