Objetivos de aprendizagem
Ao final deste capítulo, você será capaz de:
- Explicar classe, objeto e instanciação.
- Criar classes em Python usando
class,__init__eself. - Manipular atributos e chamar métodos em objetos.
- Modelar um mini-sistema de jogo com Personagem, Vida e Inventário.
1) POO em Python: a ideia principal
A Programação Orientada a Objetos (POO) é uma forma de programar criando modelos (classes) e, a partir deles, criando coisas concretas (objetos) que têm:
- Dados → atributos (ex.: vida, nome, força)
- Ações → métodos (ex.: atacar, curar, pegar item)
Em vez de espalhar variáveis e funções soltas, a POO organiza o código em “peças” que representam entidades do sistema.
BOX — Por que isso é útil?
- O código fica mais organizado e fácil de manter.
- Você consegue reaproveitar a mesma lógica criando vários objetos.
- Fica mais natural representar problemas do mundo real (ou de um jogo).
2) Classe, Objeto e Instanciação (com exemplos rápidos)
2.1 Classe (o “molde”)
Uma classe é a definição do que um tipo de objeto terá e fará.
Ex.: no jogo, podemos ter a classe Personagem:
- Atributos:
nome,vida,itens - Métodos:
atacar(),receber_dano(),curar()
BOX — Regra de ouro
Classe não é uma coisa real.
Ela é só o “projeto” do que será criado.
2.2 Objeto (o “exemplar”)
Um objeto é algo concreto criado a partir da classe.
Ex.:
heroi(objeto da classePersonagem)inimigo(outro objeto da mesma classe)
BOX — Dica
Dois objetos podem ter os mesmos atributos e métodos, mas valores diferentes.
2.3 Instanciação (criar o objeto)
Instanciar significa criar um objeto a partir da classe.
Em Python, isso acontece ao chamar a classe:
heroi = Personagem("Artemis", 100)BOX — Tradução rápida
Personagem(...)= “crie um personagem”heroi == “guarde esse personagem nessa variável”
3) A estrutura de uma classe em Python: class, __init__ e self
3.1 class: criando a classe
class Personagem:
...
3.2 __init__: inicializando o objeto
O método __init__ roda automaticamente quando o objeto é criado e costuma definir os atributos iniciais.
3.3 self: “este objeto aqui”
self representa o objeto atual, aquele que está executando o método.
- Dentro da classe:
self.vida,self.nome - Fora da classe:
heroi.vida,heroi.nome
BOX — Erro comum
Esquecerselfem métodos:
- Errado:
def atacar():- Certo:
def atacar(self):
4) Contexto de jogo: modelando Personagem, Vida e Inventário
A seguir, vamos construir um mini-modelo de jogo usando POO.
A ideia é separar responsabilidades:
Personagem→ decisões e ações do personagem (atacar, usar item, mostrar status)Inventario→ guardar e gerenciar itens (adicionar, remover, listar)- Itens → representar coisas que podem ser usadas (poção, espada etc.)
BOX — Boa prática (design simples)
Em vez de colocar “tudo” dentro dePersonagem, separe em classes menores quando fizer sentido.
Isso deixa o código mais claro e reaproveitável.
4.1 Classe Inventario
class Inventario:
def __init__(self):
self.itens = []
def adicionar(self, item):
self.itens.append(item)
def remover(self, item):
if item in self.itens:
self.itens.remove(item)
return True
return False
def listar(self):
if not self.itens:
return "Inventário vazio."
return ", ".join(self.itens)
BOX — Observação importante
Aqui,itensé uma lista de strings (ex.:"Pocao").
Depois, você pode evoluir para itens como objetos (classeItem).
4.2 Classe Personagem
from Inventario import Inventario
class Personagem:
def __init__(self, nome, vida_maxima):
self.nome = nome
self.vida_maxima = vida_maxima
self.vida = vida_maxima
self.inventario = Inventario()
def status(self):
return f"{self.nome} | Vida: {self.vida}/{self.vida_maxima} | Itens: {self.inventario.listar()}"
def receber_dano(self, dano):
dano = max(0, dano)
self.vida = max(0, self.vida - dano)
def curar(self, cura):
cura = max(0, cura)
self.vida = min(self.vida_maxima, self.vida + cura)
def atacar(self, outro, dano):
if not isinstance(outro, Personagem):
raise TypeError("O alvo do ataque precisa ser um Personagem.")
outro.receber_dano(dano)
BOX — Atenção (vida não pode passar dos limites)
- Vida mínima:
0- Vida máxima:
vida_maxima
Por isso usamosmax()emin().
4.3 Teste rápido (criando objetos e usando métodos)
from Personagem import Personagem
heroi = Personagem("Artemis", 100)
inimigo = Personagem("Goblin", 60)
heroi.inventario.adicionar("Pocao")
heroi.inventario.adicionar("Espada Curta")
print(heroi.status())
print(inimigo.status())
heroi.atacar(inimigo, 15)
print("Após ataque:")
print(inimigo.status())
inimigo.atacar(heroi, 20)
print("Após contra-ataque:")
print(heroi.status())
heroi.curar(10)
print("Após cura:")
print(heroi.status())
BOX — O que você deve observar nesse teste
heroieinimigosão objetos diferentes da mesma classe.heroi.inventarioé um objeto dentro de outro objeto (composição).- O método
atacaraltera a vida do outro personagem.
5) Evolução do jogo: usando item (poção) de verdade (simples e didático)
Agora vamos adicionar um método em Personagem para “usar poção”.
Adição no Personagem
def usar_pocao(self):
if self.inventario.remover("Pocao"):
self.curar(25)
return f"{self.nome} usou uma Poção e recuperou 25 de vida."
return f"{self.nome} não tem Poção no inventário."
Teste:
print(heroi.usar_pocao())
print(heroi.status())
BOX — Aprendizado escondido aqui
Esse exemplo mostra bem a lógica de POO:
objetos cooperam (Personagem usa Inventário para remover item e então aplica cura).
6) Erros comuns (com exemplos)
BOX — Erro comum 1: esquecer
self.ao criar atributos
class X:
def __init__(self, nome):
nome = nome # errado (não cria atributo do objeto)
Certo:
self.nome = nomeBOX — Erro comum 2: chamar método sem
()
- Errado:
heroi.status - Certo:
heroi.status()
BOX — Erro comum 3: lista como atributo “compartilhada” (assunto para quando evoluir) Evite fazer atributos mutáveis fora do
__init__como padrão para todos.
Aqui já fizemos certo:self.itens = []dentro do__init__.
Exercícios
Parte A — Conceitos (resposta curta)
- Defina classe, objeto e instanciação com suas palavras.
- O que significa
selfdentro da classe? - Qual a diferença entre atributo e método?
Parte B — Leitura e interpretação
Considere:
heroi = Personagem("Luna", 80)
inimigo = Personagem("Slime", 30)
heroi.atacar(inimigo, 12)
- Quais objetos foram instanciados?
- Qual método foi chamado e quem foi o alvo?
- Qual atributo do
inimigomuda após o ataque?
Parte C — Implementação guiada (mão na massa)
- Adicione ao
Personagemo métodoesta_vivo()que retornaTruese a vida for maior que 0. - Crie um teste:
- Faça o
inimigoreceber dano até chegar em 0 - Imprima se ele está vivo ou não
- Faça o
Parte D — Inventário (prática essencial)
- Adicione ao
Inventarioo métodotem_item(nome_item)que retornaTrue/False. - Use isso no
Personagempara criar o métodoequipar_espada():- Só permite equipar se tiver
"Espada Curta"no inventário - Se equipar, retorne uma mensagem confirmando
- Só permite equipar se tiver
Parte E — Desafio (um passo além)
Crie uma classe Monstro (pode ser bem parecida com Personagem) com:
- atributos:
nome,vida,dano_base - método:
atacar(alvo)que causadano_base
Depois:
- Instancie 1 herói e 1 monstro.
- Faça um “turno” de batalha:
- herói ataca monstro
- monstro ataca herói
- Imprima o status de ambos.
