Noções Básicas de OOP
10 exemplos para você começar com Python orientado a objetos - 7 básicos e 3 intermediários.
Pré-requisitos
- Python 3.14.0 e Noções Básicas de Python.
Exemplos Básicos
1. Definir uma Classe e __init__
Inicialize o estado da instância no construtor.
class Greeter:
def __init__(self, prefix: str) -> None:
self.prefix = prefix
def greet(self, name: str) -> str:
return f"{self.prefix}, {name}!"
g = Greeter("Hello")
print(g.greet("Ada"))__init__configura novas instâncias - não é um construtor verdadeiro no sentido de C++.selfé a convenção para a referência da instância.- Métodos são funções associadas a instâncias.
Relacionado: Métodos Dunder / Mágicos - métodos especiais
2. Atributos de Instância vs. Classe
Atributos de classe são compartilhados; atributos de instância são por objeto.
class Counter:
total = 0
def __init__(self) -> None:
Counter.total += 1
self.value = 0- Mutar
Counter.totalafeta todas as instâncias, a menos que seja sobrescrito na instância. - Atributos de instância definidos em
__init__são independentes por objeto. - Evite atributos de classe mutáveis (
list,dict) como armadilhas de estado compartilhado.
Relacionado: Métodos de Classe vs. Instância vs. Estáticos - @classmethod
3. Herança Simples
Reutilize o comportamento por meio de subclasses.
class Animal:
def speak(self) -> str:
return "..."
class Dog(Animal):
def speak(self) -> str:
return "woof"- Subclasses sobrescrevem métodos definindo o mesmo nome.
super()chama a implementação da classe pai - crucial em cadeias de__init__.- Prefira composição quando a relação não for "é um".
Relacionado: Herança e MRO - herança múltipla
4. dataclass para Registros
Reduza o código repetitivo para classes que armazenam dados.
from dataclasses import dataclass
@dataclass
class Point:
x: int
y: int
p = Point(3, 4)
print(p.x, p.y)- Gera automaticamente
__init__,__repr__e comparações quando configurado. - Adicione
frozen=Truepara objetos de valor imutáveis. - Use
field(default_factory=list)para padrões mutáveis.
Relacionado: dataclasses - field e post_init
5. Propriedades para Encapsulamento
Exponha atributos com getters/setters sem alterar os pontos de chamada.
class Account:
def __init__(self, balance: float) -> None:
self._balance = balance
@property
def balance(self) -> float:
return self._balance- O
_inicial sinaliza interno por convenção - não é privacidade forçada. @propertypode adicionar validação no setter posteriormente.- Mantém a API pública semelhante a um atributo, permitindo lógica.
Relacionado: Propriedades e Descritores - descritores
6. __repr__ para Depuração
Representação legível do objeto em logs e REPL.
class User:
def __init__(self, user_id: int, name: str) -> None:
self.user_id = user_id
self.name = name
def __repr__(self) -> str:
return f"User({self.user_id!r}, {self.name!r})"__repr__deve ser idealmente não ambíguo e fácil de reconstruir.__str__é para exibição humana;printusa__str__recorrendo a__repr__.- Dataclasses geram
__repr__úteis automaticamente.
Relacionado: Métodos Dunder / Mágicos - repr vs str
7. Enum para Constantes Nomeadas
Substitua strings mágicas por enumerações tipadas.
from enum import StrEnum
class Role(StrEnum):
ADMIN = "admin"
DEV = "dev"
def authorize(role: Role) -> bool:
return role == Role.ADMIN- Membros
StrEnumcomparam-se claramente com strings em contextos JSON. - Enums são singletons - identidade estável para comparações.
matchexaustivo em membros de enum captura casos ausentes.
Relacionado: Enums - IntEnum e flags
Exemplos Intermediários
8. Composição em Vez de Herança
Delegue comportamento a objetos auxiliares.
class EmailSender:
def send(self, to: str, body: str) -> None:
print(f"to={to} body={body}")
class Notifier:
def __init__(self, sender: EmailSender) -> None:
self._sender = sender
def notify(self, user_email: str, message: str) -> None:
self._sender.send(user_email, message)Notifiertem umEmailSenderem vez de estendê-lo.- Testes mais fáceis com um sender falso injetado.
- Troque implementações sem explosão de subclasses.
Relacionado: Melhores Práticas de Python Orientado a Objetos - regras de design
9. Interface Abstrata com abc
Force métodos que subclasses devem implementar.
from abc import ABC, abstractmethod
class Repository(ABC):
@abstractmethod
def get(self, item_id: int) -> dict: ...
class InMemoryRepo(Repository):
def get(self, item_id: int) -> dict:
return {"id": item_id}- Não é possível instanciar ABC até que os métodos abstratos sejam implementados.
- Documenta pontos de extensão para plugins e testes.
Protocoloferece alternativa estrutural - veja a seção de type hints.
Relacionado: Classes Base Abstratas - collections.abc
10. __slots__ para Memória
Restrinja atributos e reduza o overhead do dicionário por instância.
class Coord:
__slots__ = ("x", "y")
def __init__(self, x: int, y: int) -> None:
self.x = x
self.y = y- Instâncias não podem obter atributos arbitrários novos.
- Significativo ao criar milhões de objetos pequenos.
- Incompatível com alguns padrões de herança múltipla - use com critério.
Relacionado: Imutabilidade e Hashability - pontos hashable
Versões da Stack: Esta página foi escrita para Python 3.14.0 (estável 3.14, manutenção 3.13), FastAPI 0.115+, Django 5.2, Flask 3.1, Pydantic 2, PyTorch 2.6+, pandas 2.2+, Polars 1.x, ruff 0.9+, e uv 0.6+.