Introdução a Orientação a Objetos no Python

Para a melhor compreensão do código dos produtos da itflex é essencial conhecer melhor a Orientação a Objetos no Python. Por isso montamos o resumo deste conteúdo.

Em Python tudo é objeto, a orientação a objetos é construida utilizando alguns componentes como:

Classe- utilizamos a palavra chave class e ela define a categoria do objeto, alguns exemplos do que poderiam ser classes no mundo real são: MaterialDeEscritorio, Eletronicos, Frutas Objetos- São instâncias criadas a partir da classe alguns exemplos do que poderiam ser objetos no mundo real são:- Caneta, celular, banana Atributos- Valores definidos nas classes e nos objetos Método - Função definida no escopo da classe

Exemplo:

Definição da classe

  class Pessoa:  
    """Represents a Person"""

    # Atributos da classe
    nome_da_empresa = "Escola quintal aroeira"
    endereco_do_trabalho = "Rua positiva, São Paulo"
    bonus_salarial = 0

    # Métodos ou funções associadas
    def adiciona_bonus(pessoa, valor):
        if pessoa.funcao == "diretor":
            valor *=2
        pessoa.bonus_salarial += valor

fernanda = Pessoa()  # Instanciação de um objeto a partir da classe

fernanda.adiciona_bonus(100)  # Chamada de método associado

print(fernanda.nome)  # Acesso a atributo

Os 4 pilares do POO em Python

1. Abstração:

A Capacidade de representar um objeto abstrato do mundo real ou do dominio do programa sendo desenvolvido.

class Pessoa:
    """Represents a Person"""
    reino = "animal"

class Fruit:
    """Represents a fruit"""
    reino = "vegetal"

class Animal:
    """Represents an animal"""
    reino = "animal"

E então a partir desta classe abstrata criar novas classes derivadas que veremos em detalhes no pŕoximo

2.Herança:

A capacidade de uma classe herdar atributos e comportamento a partir de outra classe, no exemplo abaixo as classes Maca, Melancia e Abacaxi herdam atributos e comportamento da classe Fruta.

# super classe 
class Fruta:  # Classe abstrata
    reino = "vegetal"

# sub classes (classes derivadas)
class Maca(Fruta):  # Classe Material
    cores = ["vermelho", "branco"]
    imagens = "🍎"

class Melancia(Fruta):
    cores = ["verde", "vermelho"]
    imagens = "🍉"

class Abacaxi(Fruta):
    cores = ["amarelo", "verde"]
    imagens = "🍍"

O python permite a herança múltipla No exemplo abaixo a classe Bilingual herda os métodos das classes English e Portugues.

class Ingles:
    def saudacao(self):
        print("Hi!")


class Portugues:
    def saudacao(self):
        print("Oi!")


class Bilingue(Ingles, Portugues):
    pass

No Python, em casos de herança múltipla, a prioridade é definida da esquerda para a direita, ou seja:

class Bilingue(Ingles, Portugues):

Bilingue dará preferência ao método saudacao de Ingles.

A vantagem de se usar herança é que se em algum momento precisarmos alterar algo na implementação de todas as frutas, basta alter a super classe e todas as sub classes vão adotar este mesmo comportamento. E também é uma ótima forma de se economizar código.

3.Polimorfismo:

Polimorfismo é o princípio pelo qual duas ou mais classes derivadas da mesma superclasse podem invocar métodos que têm a mesma assinatura, mas comportamentos distintos.

class Super:
    def hello(self):
        print("Olá, sou a superclasse!")
  
class Sub (Super):
    def hello(self):
        print("Olá, sou a subclasse!")

teste = Sub()
teste.hello()

O resultado vai ser: Olá, sou a subclasse! Veja bem, Sub herda a Superclasse, ou seja, tudo que nem na superclasse (atributos e métodos), vai ter na subclasse.

Porém, quando chamamos o método hello(), ele vai invocar o método da subclasse e não da superclasse! O Python entende: “Opa, ele instanciou um objeto da subclasse. Por isso vou invocar o método da subclasse e não da superclasse”

4.Encapsulamento:

Encapsulamento é a capacidade de um objeto esconder sua implementação interna e expor apenas o que for conveniente.

Exemplo de encapsulamento Digamos que temos uma empresa que vende cursos para estudantes, engenheiros e profissionais. As diferentes seções desta empresa incluem as seguintes operações, finanças, contas, vendas, etc. Agora, se um funcionário da seção de contas precisar dos registros de vendas em 2022, ele não poderá acessá-los diretamente.

Para acessar, o funcionário das seções de conta precisa obter permissão do membro da equipe da seção de vendas. Portanto, os dados de vendas são ocultados de outros departamentos. Da mesma forma, o balanço da empresa é acessível apenas ao departamento financeiro e oculto de outras seções. Os dados de contas, vendas, finanças, operações, marketing etc. estão ocultos em outras seções.

Outro exemplo de encapsulamento: Aqui, a função personalizada demofunc() exibe os registros dos alunos . Usando os objetos st1, st2, st3, st4, acessamos os métodos da classe demofunc()

class Estudantes:
   def __init__(self, nome, classificacao, pontuacao):
      self.nome = nome
      self.classificacao = classificacao
      self.pontuacao = pontuacao

   # custom function
   def demofunc(self):
      print("Meu nome é "+self.nome)
      print("Minha classificação foi",+self.classificacao)

# create 4 objects
est1 = Estudantes("Estevão", 1, 100)
est2 = Estudantes("Chris", 2, 90)
est3 = Estudantes("Mari", 3, 76)
est4 = Estudantes("Catia", 4, 60)

# call the functions using the objects created above
est1.demofunc()
est2.demofunc()
est3.demofunc()
est4.demofunc()
Output
Meu nome é Estevão
Minha classificação foi  1
Meu nome é Chris
Minha classificação foi  2
Meu nome é Mari
Minha classificação foi  3
Meu nome é Catia
Minha classificação foi  4

Especificidades do Python

Criando objetos a partir das classes abstratas

Em teoria, deveriamos ser incapazes de criar objetos a partir das classes abstratas e apenas conseguir a partir de classes materiais em nosso exemplo deveriamos ser impedidos de criar uma instancia de um objeto diretamente a partir da classe abstrata Fruta mas em Python todas as classes são abertas e nada nos impede de fazer:

fruta1 = Maca()  # OK instancia criada a partir da classe material
print(fruta1.reino)

fruta2 = Fruit()  # NÃO ok, instancia criada a partir da classe abstrata
print(fruta2.reino)

No mundo real, não existe um objeto chamado Fruta sempre temos uma derivação de fruta com um nome material e caracteristicas bem definidas como “Maçã”, “Banana” etc.. A linguagem Python segue a filosofia de “Somos todos adultos e sabemos o que fazemos”, portanto este tipo de regra é aplicada mais a título de convenção e sempre que uma classe é abstrata nós podemos deixar isso explicito usando uma Abstract Base Class(ABC)

from abc import ABC
class Fruta(ABC):
    reino = "vegetal"

Não somos impedidos de criar a instância a partir da classe base, mesmo utilizando o ABC, mas isso não é uma boa prática.

Atributos privados

Nenhum atributo é realmente privado em Python,muitos programadores Python usam apenas um underscore ‘_’ para indicar quando um atributo deve ser protegido.

O prefixo com apenas um underscore não tem significado para o interpretador quando usado em nome de atributos, mas entre programadores Python é uma convenção que deve ser respeitada. O programador alerta que esse atributo não deve ser acessado diretamente:

def __init__(self, idade):
    self._idade = idade

Um atributo com apenas um underscore é chamado de protegido, mas quando usado sinaliza que deve ser tratado como um atributo “privado”, fazendo com que acessá-lo diretamente possa ser perigoso.

Onde praticar o conhecimento

Lista de exercícios no Codewars para treinar POO

Você ainda pode buscar outros exercícios em:

Outros sites para estudo: