Guia de estudo

08/04/2026 · Aula 03

Métodos e

representação de objetos

Programação Orientada a Objetos com Python
Tecnologia em Análise e Desenvolvimento de Sistemas

4 horas Teoria + Prática Mão na massa

destino da aula

Para onde vamos hoje

No final desta aula você vai entender cada linha dessa classe — e saber escrever uma igual do zero.

conta_bancaria.py
class ContaBancaria:
    taxa_juros = 0.05                 # atributo de classe ← hoje

    def __init__(self, titular, saldo=0):
        self.titular   = titular.strip().title()  # método de string ← hoje
        self.saldo     = saldo
        self.historico = []               # método de lista ← hoje

    def depositar(self, valor):
        self.saldo += valor
        self.historico.append(f"+ R$ {valor:.2f}")

    def sacar(self, valor):
        if valor > self.saldo:
            return False
        self.saldo -= valor
        self.historico.append(f"- R$ {valor:.2f}")
        return True

    @classmethod                        # método de classe ← hoje
    def criar_zerada(cls, titular):
        return cls(titular, 0)

    def __str__(self):               # representação ← hoje
        return f"Conta de {self.titular} | Saldo: R$ {self.saldo:.2f}"

bloco 1 · ferramentas do Python

Métodos de string

Seus objetos vão armazenar nomes, CPFs e descrições como strings. Dominar esses métodos é essencial para manipular atributos e construir um bom __str__.

.strip(): Remove espaços nas bordas
.title(): Cada palavra capitalizada
.upper() / .lower(): Maiúsculas / minúsculas
.replace(a, b): Substitui ocorrências
.split(sep): Divide em lista
.startswith(s): Começa com?
len(s) / x in s: Tamanho / contém
strings.py
class Pessoa:
    def __init__(self, nome):
        self.nome = nome.strip().title()

# Strings são IMUTÁVEIS — salve o resultado!
nome = "  ana silva  "
nome.strip()       # ← resultado vai pro lixo
nome = nome.strip()  # ← guarda o novo valor

bloco 1 · ferramentas do Python

Métodos de lista

Atributos como histórico de operações, notas de alunos ou itens de carrinho são listas. Esses métodos são usados dentro dos seus objetos o tempo todo.

append(item): Adiciona ao final
pop(): Remove e retorna o último
pop(i): Remove e retorna pelo índice
remove(item): Remove a 1ª ocorrência do valor
insert(i, item): Insere na posição i
len(lista): Quantidade de itens
item in lista: Verifica se existe
sort() / sorted(): Ordena / retorna nova lista
listas.py
historico = []

historico.append("+ R$ 500")   # adiciona ao final
historico.append("- R$ 200")

print(historico[-1])  # último: "- R$ 200"
print(len(historico)) # 2

# pop vs remove
historico.pop()           # remove pelo índice (retorna)
historico.remove("+ R$ 500")  # remove pelo valor

bloco 1 · na prática

Strings e listas dentro de um objeto

O que acabamos de ver não é teoria isolada — é exatamente o que acontece dentro de qualquer classe bem construída.

conta_bloco1.py
class ContaBancaria:
    def __init__(self, titular, saldo=0):
        self.titular   = titular.strip().title()  # .strip() e .title()
        self.saldo     = saldo
        self.historico = []                        # lista vazia como atributo

    def depositar(self, valor):
        self.saldo += valor
        self.historico.append(f"+ R$ {valor:.2f}")  # .append()

    def ultima_operacao(self):
        if len(self.historico) == 0:
            return "Nenhuma operação ainda"
        return self.historico[-1]              # índice negativo

c = ContaBancaria("  ana silva  ")
print(c.titular)                # "Ana Silva" — .title() limpou
c.depositar(500)
print(c.ultima_operacao())     # "+ R$ 500.00"

bloco 2 · onde moram os dados

Atributos de instância vs classe

Antes de criar ações, precisamos entender quem é o "dono" da informação que estamos guardando.

Individual (Instância)

Criados com self dentro do __init__. Cada objeto tem o seu próprio valor.

Compartilhado (Classe)

Criados na classe. Todos os objetos daquela classe compartilham o mesmo dado.

Regra de ouro: Use instância para dados únicos (CPF). Use classe para regras globais (Juros).
# Para mudar para TODOS: Conta.taxa = 0.06

bloco 2 · métodos

Métodos de instância

Todo método de instância recebe self e acessa os dados do próprio objeto.

conta.py
class ContaBancaria:
    def __init__(self, titular, saldo):
        self.titular = titular
        self.saldo   = saldo

    def depositar(self, valor):   # método de instância
        self.saldo += valor
        return self.saldo          # retorna o novo saldo

conta = ContaBancaria("João", 1000)
novo = conta.depositar(500)
print(novo)  # 1500
self dá ao método acesso a todos os atributos do objeto. Sem ele, o método não saberia de qual conta está falando.

bloco 2 · três padrões essenciais

Como métodos de instância trabalham

① return, não print

Evite que o valor desapareça na tela. Com return, ele pode ser guardado em variáveis ou reusado em cálculos.

# ❌ Errado: valor desaparece
def area(self):
    print(self.l * self.a)

# ✅ Certo: valor reusável
def area(self):
    return self.l * self.a

② self.metodo()

Dentro da classe, qualquer método pode chamar outro via self.metodo(). Isso evita repetição de código.

def situacao(self):
    # delega para outro método
    media = self.calcular_media()
    if media >= 7:
        return "Aprovado"
    return "Reprovado"

③ _ auxiliar

O _ no início sinaliza um método interno de implementação que não faz parte da interface pública.

def depositar(self, v):
    self.saldo += v
    # método auxiliar
    self._registrar(f"+ {v}")

def _registrar(self, op):
    self.historico.append(op)
Esses padrões garantem que sua classe seja modular e fácil de manter.

bloco 2 · uma necessidade nova

E se eu precisar criar um objeto sem ter todos os dados?

?
Quero criar uma ContaBancaria com saldo zero sem passar 0 toda hora
?
Quero rastrear quantas contas foram criadas — não é dado de UMA conta, é da classe toda
?
Quero mudar a taxa de juros para todas as contas ao mesmo tempo
problema.py
# Módulo de instância não funciona aqui
# precisaria de um objeto JÁ EXISTENTE:
conta.criar_zerada()  # ← mas qual "conta"?

# O que faz sentido é chamar NA CLASSE:
ContaBancaria.criar_zerada("Maria")

# Para isso existe: @classmethod

bloco 2 · o contraste

Métodos de classe — lado a lado

item detalhe
Decorador — (nenhum) vs @classmethod
1º parâmetro self (o objeto) vs cls (a classe)
Chamado em objeto.metodo() vs Classe.metodo()
Acessa Dados daquele objeto vs A classe toda / cria objetos
Quando usar Comportamento do objeto vs Construtores alternativos, config global

bloco 3 · representação

O que acontece quando você imprime um objeto?

!
Endereço de memória — inútil para o usuário
!
Não mostra nenhum atributo do objeto
!
Impossível debugar só olhando a saída
sem_str.py
class Produto:
    def __init__(self, nome, preco):
        self.nome  = nome
        self.preco = preco

p = Produto("Teclado", 149.90)
print(p)
# <__main__.Produto object at 0x7f3c...>
Python precisa saber como você quer que o objeto seja descrito. Para isso existe o método mágico __str__.

bloco 3 · o padrão por baixo

O universo dos dunder methods

Dunder = double underscore. São chamados automaticamente pelo Python em situações específicas — você nunca os chama diretamente.

Já conhecemos

__init__ → ao criar __str__ → print()

Vamos encontrar

__repr__ → repr() __len__ → len(obj) __eq__ → obj1 == obj2 __lt__ → obj1 < obj2

Mais avançados

__add__ → obj1 + obj2 __contains__ → in __iter__ → for loop

O padrão é sempre o mesmo: você define o dunder e o Python o chama automaticamente.

bloco 3 · representação

O método __str__

Chamado automaticamente pelo Python quando você usa print(objeto) ou str(objeto).

produto.py
class Produto:
    def __init__(self, nome, preco):
        self.nome  = nome
        self.preco = preco

    def __str__(self):
        return f"Produto: {self.nome} | Preço: R$ {self.preco:.2f}"

p = Produto("Teclado", 149.90)
print(p)         # Produto: Teclado | Preço: R$ 149.90
print(f"Item: {p}")  # também funciona em f-strings!
__str__ deve sempre retornar uma string. Use f-strings — elas garantem isso e ficam muito legíveis.

bloco 3 · para desenvolvedores

__str__ vs __repr__

👤
__str__ — para o usuário. Legível, amigável
🛠
__repr__ — para o desenvolvedor. Mostra como recriar o objeto
Se definir só um, defina __str__
representacao.py
class Produto:
    def __init__(self, nome, preco):
        self.nome  = nome
        self.preco = preco

    def __str__(self):
        return f"{self.nome} — R$ {self.preco:.2f}"

    def __repr__(self):
        return f"Produto('{self.nome}', {self.preco})"

p = Produto("Teclado", 149.90)
print(p)   # Teclado — R$ 149.90
print(repr(p))  # Produto('Teclado', 149.9)

bloco 4 · antes da prática

Erros mais comuns de hoje

1

Método de string não salvo

Lembre-se: self.nome = nome.strip().

2

__str__ sem retornar string

Tentar retornar um número direto (ex: return self.saldo) gera erro de tipo.

3

Print em métodos de cálculo

Cálculos exigem return para serem reusados.

4

Chamar método sem self.

Dentro da classe, use sempre self.metodo().

5

Dunder com erro de digitação

São sempre dois underscores de cada lado: __str__, não _str_.

bloco 4 · antes da prática

Perguntas que todo mundo tem

?

Strings são imutáveis — como isso afeta meus objetos?

Métodos de string retornam uma nova string. Use self.nome = nome.strip() para guardar o resultado.

?

Qual a diferença entre pop() e remove()?

pop() remove pela posição e retorna o item. remove(valor) remove por valor e não retorna nada.

?

__str__ ou um método exibir()?

O __str__ é automático no print(). O exibir() precisa ser chamado manualmente.

?

Quando uso @classmethod vs método de instância?

Use @classmethod para ações que não dependem de um objeto já criado, como construtores alternativos.

?

__str__ pode chamar outros métodos?

Sim! Pode usar self.calcular_media() dentro dele para compor a string de retorno.

?

Posso usar .split() no input do usuário?

Sim. É ideal para transformar uma string de entrada em uma lista de dados para preencher o objeto.

bloco 5 · prática

Conta Bancária completa

Vamos construir juntos uma ContaBancaria com operações reais e saída legível.

Parte 1 · base

Crie ContaBancaria com titular, saldo=0 e historico (lista). Métodos depositar e sacar com validação.

Parte 2 · extrato

Crie extrato() que percorre o historico com for e imprime o saldo final formatado.

Parte 3 · refatoração

Crie o __str__ e refatore o extrato(): use print(self) no final para exibir o saldo usando a regra do __str__.

Trabalho individual. A Parte 3 é o grande desafio: ela mostra como um método mágico pode simplificar outros métodos.

exercício · partes 1 e 2

ContaBancaria — base e extrato

conta_bancaria.py
class ContaBancaria:
    def __init__(self, titular, saldo=0):
        self.titular   = titular
        self.saldo     = saldo
        self.historico = []   # lista vazia

    def depositar(self, valor):
        self.saldo += valor
        self.historico.append(f"+ R$ {valor:.2f}")

    def sacar(self, valor):
        if valor > self.saldo:
            print("Saldo insuficiente!")
            return False
        self.saldo -= valor
        self.historico.append(f"- R$ {valor:.2f}")
        return True

    def extrato(self):
        print(f"=== Extrato de {self.titular} ===")
        for op in self.historico:   # for na lista
            print(f"  {op}")
        print(f"Saldo atual: R$ {self.saldo:.2f}")

exercício · parte 3

Refatoração com __str__

conta_completa.py
class ContaBancaria:
    # ... __init__, depositar, sacar ...

    def extrato(self):
        print(f"=== Extrato de {self.titular} ===")
        for op in self.historico:
            print(f"  {op}")
        # Refatorado: usa a regra do __str__ abaixo
        print(self) 

    def __str__(self):
        return f"Saldo atual: R$ {self.saldo:.2f}"

# Testando a integração
c = ContaBancaria("João", 1000)
c.depositar(500)
c.sacar(200)

c.extrato() 
# O print(self) dentro do extrato chamará o __str__ automaticamente!
Por que refatorar? Agora, se você quiser mudar como o saldo aparece, você só altera o __str__ e o extrato() se atualiza sozinho.

desafio

Classe Retangulo

Aplique tudo que vimos: atributos, métodos com retorno e __str__.

Atributos: largura e altura
Métodos: area() e perimetro() com return
__str__: "Retângulo 10x5 | Área: 50 | Perímetro: 30"
Bônus: método e_quadrado() que retorna True se largura == altura
retangulo.py
class Retangulo:
    def __init__(self, largura, altura):
        self.largura = largura
        self.altura  = altura

    def area(self):
        return self.largura * self.altura

    def perimetro(self):
        return 2 * (self.largura + self.altura)

    def __str__(self):
        return (
          f"Retângulo {self.largura}x{self.altura} | "
          f"Área: {self.area()} | Perímetro: {self.perimetro()}"
        )

fechamento

O que vimos hoje

  • Métodos de string e de lista — ferramentas essenciais para trabalhar com atributos
  • Métodos de instância vs @classmethod — quando o método pertence ao objeto vs à classe
  • Métodos com return — diferença crucial em relação a print
  • Um método pode chamar outro via self.metodo()
  • __str__ — representação do objeto para o usuário (sempre retorna string)
  • Dunder methods — o padrão por trás de __init__, __str__, __repr__ e além

para casa

18 exercícios gradativos

Faça o máximo que conseguir e anote suas dúvidas para a próxima aula.

3

Fácil

Exercícios: #1 ao #3

6

Médio

Exercícios: #4 ao #9

5

Difícil

Exercícios: #10 ao #14

4

Avançado

Exercícios: #15 ao #18

exercícios para casa · nível fácil

Nível Fácil

01

__str__ no Carro

Pegue a classe Carro da aula 02 e adicione um __str__ que retorne: "[marca] [modelo] ([ano])". Teste com print().

02

Classe Círculo

Crie Circulo com raio. Métodos area() e perimetro() com return. __str__ com os dois valores formatados em 2 casas decimais.

03

Temperatura

Crie Temperatura com celsius. Método em_fahrenheit() que retorna a conversão (C × 1.8 + 32). __str__ exibindo ambas as unidades.

exercícios para casa · nível médio

Nível Médio

04

Conta com __str__ e __repr__

Refaça a ContaBancaria do exercício da aula, agora com __repr__ que exibe ContaBancaria('nome', saldo). Teste os dois no terminal.

05

Produto com desconto

Crie Produto com nome, preco. Método aplicar_desconto(pct) que retorna o preço após desconto. __str__ com preço original e após desconto.

06

Aluno melhorado

Evoluir o Aluno da aula 02: adicionar __str__ que exibe nome, média (via calcular_media()) e situação (via situacao()).

07

Veículo com combustível

Crie Veiculo com modelo, combustivel (litros). Métodos abastecer(litros) e viajar(km) (gasta 0.1 L/km, usa append no histórico). __str__ com modelo e combustível atual.

08

Placar de jogo

Crie Placar com time_a e time_b (pontos em 0). Métodos gol_a(), gol_b() e vencedor() (retorna nome ou "Empate"). __str__ com placar.

09

Contador de cliques

Crie Contador com valor (inicia em 0). Métodos incrementar(), decrementar() (não vai abaixo de 0) e resetar(). __str__ com o valor atual.

exercícios para casa · nível difícil

Nível Difícil

10

ContaBancaria completa

Implemente a ContaBancaria completa: inclua um atributo de classe taxa_manutencao (ex: 5.00) e um @classmethod para alterá-lo. No extrato(), use o __str__ refatorado e mostre como a alteração da taxa afeta todas as instâncias criadas.

11

Fila (Queue)

Crie Fila com lista interna. Métodos entrar(item) (adiciona ao final), sair() (remove o primeiro), proximo() e esta_vazia(). __str__ mostrando o conteúdo.

12

Turma com estatísticas

Crie Turma com lista de alunos (Aluno da aula 02). Métodos matricular(), media_turma(), melhor_aluno() e __str__ com resumo completo.

13

Produto com @classmethod

Crie Produto com nome, preco, categoria. Adicione @classmethod criar_promocional(cls, nome, preco) que cria um produto na categoria "Promoção" com preço reduzido em 20%.

14

Playlist

Crie Playlist com nome e lista de músicas. Métodos adicionar, remover e embaralhar() (use import random no topo e random.shuffle(self.musicas)). O __str__ deve exibir o nome da playlist e o total de faixas.

exercícios para casa · nível avançado

Nível Avançado

15

Biblioteca com empréstimos

Crie Livro com titulo, autor, disponivel=True e __str__. Crie Biblioteca com adicionar(), emprestar(titulo), devolver(titulo) e listar_disponiveis().

16

Calculadora com histórico

Evolua a calculadora da aula 01 para uma classe com historico. Cada operação registra um texto descritivo na lista. Método ver_historico() exibe tudo. @classmethod limpar_tudo() reseta a instância.

17

Carrinho de compras

Crie Carrinho com lista de Produto. Métodos adicionar, remover e total().
Dica Avançada: No método total(), use um for para percorrer a lista e acessar o .preco de cada produto. O __str__ deve listar os nomes dos itens e o valor final.

18

Sistema de notas completo

Crie Disciplina com nome e lista de alunos (objetos da classe Aluno). Métodos matricular(), media_disciplina() (percorre os alunos e calcula a média geral) e listar_aprovados(). Use @classmethod para criar uma disciplina com nome padrão.

próxima aula

Aula 4 · 10/04

Aula 04 · 10/04

Vamos aprender a proteger os dados dos nossos objetos — atributos privados com _ e __, properties com @property e validações no setter.

atributos privados @property @setter validação de dados