Um dos exemplos clássicos e intuitivos para exemplificar o uso de classes simples é a implementação de uma versão simplificada de uma classe ContaCorrente.
a) codifique uma classe ContaCorrente, inicializada com um código, um saldo inicial e um limite.
b) implemente os métodos sacar(valor) e depositar(valor), com o cuidado especial de não permitir sacar valores que resultariam na extrapolação do limite da conta.
c) modifique a implementação para que todas operações sejam registradas. Então, forneça um método ver_extrato() que retorna uma lista com as operações realizadas.
d) adicione um método salvar_extrato (arquivo) que recebe um nome de um arquivo e salva o registro de operações nele.
a) codifique uma classe ContaCorrente, inicializada com um código, um saldo inicial e um limite.
b) implemente os métodos sacar(valor) e depositar(valor), com o cuidado especial de não permitir sacar valores que resultariam na extrapolação do limite da conta.
c) modifique a implementação para que todas operações sejam registradas. Então, forneça um método ver_extrato() que retorna uma lista com as operações realizadas.
d) adicione um método salvar_extrato (arquivo) que recebe um nome de um arquivo e salva o registro de operações nele.
Passo 1
O enunciado pede quatro coisas relacionadas a uma implementação simples de uma classe de conta corrente. Vou listar exatamente o que cada item exige e as informações que temos:
- (a) Criar uma classe chamada ContaCorrente, que seja inicializada com:
- um código (identificador da conta),
- um saldo inicial,
- um limite (limite de cheque especial).
- (b) Implementar métodos:
sacar(valor)— deve realizar saque, mas NÃO permitir que o saque exceda o saldo mais o limite.depositar(valor)— deve aumentar o saldo.
- (c) Registrar todas as operações realizadas (saque e depósito) e fornecer um método
ver_extrato()que retorne a lista com essas operações. - (d) Adicionar um método
salvar_extrato(arquivo)que recebe o nome de um arquivo e salva o registro de operações nele.
Informações relevantes dadas:
- Precisamos garantir a checagem do limite ao sacar.
- O extrato deve armazenar cada operação (tipo e valores) para ser consultado e salvo.
- Não foi especificado o formato exato do registro, então posso escolher um formato razoável e bem explicado.
Passo 2
Vamos começar pela estrutura básica de uma classe em Python (isso vale como “aula rápida” sobre classes):
- Uma classe é definida com
class Nome:. - O método especial
__init__(self, ...)é o construtor: é chamado quando criamos um objeto e serve para inicializar os atributos. - Atributos (variáveis do objeto) são criados atribuindo
self.atributo = valor. - Métodos são funções definidas dentro da classe que recebem
selfcomo primeiro argumento para acessar os atributos do objeto.
Implementação inicial (resposta ao item a): uma classe
ContaCorrente com codigo, saldo e limite. Vou também inicializar o registro de operações como uma lista vazia — isso já prepara para o item (c).Exemplo de código para essa etapa:
class ContaCorrente:
def __init__(self, codigo, saldo_inicial=0.0, limite=0.0):
"""
Inicializa a conta.
codigo: identificador da conta (string ou int)
saldo_inicial: saldo inicial (float)
limite: limite de cheque especial (float)
"""
self.codigo = codigo
self.saldo = float(saldo_inicial)
self.limite = float(limite)
# Lista para registrar operações (cada entrada será um dicionário)
self._extrato = []
Explicação das escolhas:
- Converti
saldo_inicialelimiteparafloatpara garantir operações numéricas consistentes. _extratocom underscore para indicar que é “interno” (convenção), mas ainda acessível por métodos públicos.
Passo 3
Agora implementamos os métodos
depositar e sacar (item b). Primeiro a lógica que precisamos entender e aplicar:-
Depositando:
- O valor deve ser positivo; se for inválido, não alteramos o saldo.
- Ao depositar, o saldo aumenta.
- Registramos a operação no extrato.
-
Sacando:
- Definimos o “disponível” como
saldo + limite. Isso é o máximo que pode ser usado. - Antes de permitir o saque, verificamos se
valor <= disponível. - Se sim: subtrair do
saldoe registrar a operação. - Se não: não permitir o saque (retornar
Falseou lançar erro). Vou optar por fazer o método retornarTruese teve sucesso eFalsese falhou — isso é prático para código em prova e evita ter que tratar exceções.
- Definimos o “disponível” como
Vou mostrar passo a passo os cálculos (a “aula” sobre esse ponto):
- Disponível = saldo atual + limite.
- Condição para permitir saque:
valor <= disponível. - Atualização do saldo:
self.saldo -= valor(se permitido).
Código para estes métodos:
def depositar(self, valor):
"""Deposita um valor positivo. Retorna True se sucesso, False se valor inválido."""
valor = float(valor)
if valor <= 0:
return False
saldo_antes = self.saldo
self.saldo += valor
saldo_depois = self.saldo
# Registrar no extrato (vou padronizar o formato no Passo 4)
self._extrato.append({
"tipo": "deposito",
"valor": valor,
"saldo_antes": saldo_antes,
"saldo_depois": saldo_depois
})
return True
def sacar(self, valor):
"""Tenta sacar. Retorna True se sucesso, False se insuficiente ou valor inválido."""
valor = float(valor)
if valor <= 0:
return False
disponivel = self.saldo + self.limite
if valor > disponivel:
# Não permite extrapolar o limite
return False
saldo_antes = self.saldo
self.saldo -= valor
saldo_depois = self.saldo
self._extrato.append({
"tipo": "saque",
"valor": valor,
"saldo_antes": saldo_antes,
"saldo_depois": saldo_depois
})
return True
Observações didáticas:
- Usei
float(valor)para evitar problemas se o usuário passar um inteiro; em prova, isso demonstra cuidado com tipos. - Retornar booleano facilita testes rápidos:
if conta.sacar(100): ... else: ....
Passo 4
Agora formalizamos o formato do extrato (item c) e implementamos
ver_extrato().Decisões de formato (claras e fáceis de ler):
- Cada entrada do extrato será um dicionário com chaves:
"tipo":"deposito"ou"saque"."valor": valor da operação (float)."saldo_antes": saldo antes da operação (float)."saldo_depois": saldo depois da operação (float).- Opcionalmente poderíamos adicionar
"descricao"ou"data", mas o enunciado não exige; se quiser, posso incluir timestamp mais tarde.
Implementação de
ver_extrato():- Deve retornar a lista de operações. Para segurança, retornamos uma cópia superficial (
list(self._extrato)) para que o usuário não modifique diretamente o registro interno sem querer.
Código:
def ver_extrato(self):
"""Retorna uma cópia da lista de operações (extrato)."""
return list(self._extrato)
Exemplo de uso e interpretação:
- Se eu fizer
conta.depositar(200)e depoisconta.sacar(50), over_extrato()poderá retornar algo como:[{"tipo": "deposito", "valor": 200.0, "saldo_antes": 0.0, "saldo_depois": 200.0}, {"tipo": "saque", "valor": 50.0, "saldo_antes": 200.0, "saldo_depois": 150.0}]
- Isso facilita mostrar extratos na tela ou salvar em arquivo.
Passo 5
Agora implementamos
salvar_extrato(arquivo) (item d). O método vai receber uma string com o nome do arquivo (p.ex. "extrato.txt") e gravar uma representação legível do extrato nele. Cuidados:- Usar
with open(arquivo, "w", encoding="utf-8")para garantir fechamento do arquivo. - Formatar cada entrada de forma legível — por exemplo:
TIPO: depósito | VALOR: 100,00 | SALDO ANTES: 50,00 | SALDO DEPOIS: 150,00 - Tratar possíveis exceções de I/O? Em prova, basta documentar que erros podem propagar; posso optar por capturar e retornar
Falseem caso de erro eTruese gravou com sucesso.
Implementação:
def salvar_extrato(self, arquivo):
"""
Salva o extrato em um arquivo texto.
Retorna True se sucesso, False se ocorreu erro de escrita.
"""
try:
with open(arquivo, "w", encoding="utf-8") as f:
f.write(f"Extrato da conta: {self.codigo}\n")
f.write(f"Saldo atual: {self.saldo}\n")
f.write(f"Limite: {self.limite}\n")
f.write("-" * 40 + "\n")
for op in self._extrato:
linha = (
f"{op['tipo'].upper():8} | "
f"VALOR: {op['valor']:,.2f} | "
f"ANTES: {op['saldo_antes']:,.2f} | "
f"DEPOIS: {op['saldo_depois']:,.2f}\n"
)
f.write(linha)
return True
except Exception:
return False
Explicação didática:
- Usei formatação com
:,.2fpara duas casas decimais e separador de milhar (apenas para saída legível). - O bloco
try/exceptevita que a função lance uma exceção para quem apenas quer saber se salvou com sucesso.
Passo 6
Juntando tudo: abaixo está a classe completa com todos os métodos implementados, docstrings e comportamento explicado. Também incluí (comentado) um pequeno exemplo de uso que ajuda a testar a classe rapidamente.
Código final (pronto para usar em uma prova ou exercício prático):
class ContaCorrente:
def __init__(self, codigo, saldo_inicial=0.0, limite=0.0):
"""
Inicializa a conta.
codigo: identificador da conta (string ou int)
saldo_inicial: saldo inicial (float)
limite: limite de cheque especial (float)
"""
self.codigo = codigo
self.saldo = float(saldo_inicial)
self.limite = float(limite)
# Lista para registrar operações (cada entrada será um dicionário)
self._extrato = []
def depositar(self, valor):
"""Deposita um valor positivo. Retorna True se sucesso, False se valor inválido."""
try:
valor = float(valor)
except (TypeError, ValueError):
return False
if valor <= 0:
return False
saldo_antes = self.saldo
self.saldo += valor
saldo_depois = self.saldo
# Registrar no extrato
self._extrato.append({
"tipo": "deposito",
"valor": valor,
"saldo_antes": saldo_antes,
"saldo_depois": saldo_depois
})
return True
def sacar(self, valor):
"""Tenta sacar. Retorna True se sucesso, False se insuficiente ou valor inválido."""
try:
valor = float(valor)
except (TypeError, ValueError):
return False
if valor <= 0:
return False
disponivel = self.saldo + self.limite
if valor > disponivel:
# Não permite extrapolar o limite
return False
saldo_antes = self.saldo
self.saldo -= valor
saldo_depois = self.saldo
self._extrato.append({
"tipo": "saque",
"valor": valor,
"saldo_antes": saldo_antes,
"saldo_depois": saldo_depois
})
return True
def ver_extrato(self):
"""Retorna uma cópia da lista de operações (extrato)."""
return list(self._extrato)
def salvar_extrato(self, arquivo):
"""
Salva o extrato em um arquivo texto.
Retorna True se sucesso, False se ocorreu erro de escrita.
"""
try:
with open(arquivo, "w", encoding="utf-8") as f:
f.write(f"Extrato da conta: {self.codigo}\n")
f.write(f"Saldo atual: {self.saldo}\n")
f.write(f"Limite: {self.limite}\n")
f.write("-" * 40 + "\n")
for op in self._extrato:
linha = (
f"{op['tipo'].upper():8} | "
f"VALOR: {op['valor']:,.2f} | "
f"ANTES: {op['saldo_antes']:,.2f} | "
f"DEPOIS: {op['saldo_depois']:,.2f}\n"
)
f.write(linha)
return True
except Exception:
return False
# Exemplo de uso (pode descomentar para testar):
# conta = ContaCorrente("123-4", saldo_inicial=100.0, limite=50.0)
# conta.depositar(50)
# sucesso = conta.sacar(160) # deve ser False, pois 160 > 100+50
# sucesso2 = conta.sacar(120) # deve ser True: saldo 150 -> após saque saldo = 30
# print(conta.ver_extrato())
# conta.salvar_extrato("meu_extrato.txt")
Resposta
class ContaCorrente:
def __init__(self, codigo, saldo_inicial=0.0, limite=0.0):
"""
Inicializa a conta.
codigo: identificador da conta (string ou int)
saldo_inicial: saldo inicial (float)
limite: limite de cheque especial (float)
"""
self.codigo = codigo
self.saldo = float(saldo_inicial)
self.limite = float(limite)
# Lista para registrar operações (cada entrada será um dicionário)
self._extrato = []
def depositar(self, valor):
"""Deposita um valor positivo. Retorna True se sucesso, False se valor inválido."""
try:
valor = float(valor)
except (TypeError, ValueError):
return False
if valor <= 0:
return False
saldo_antes = self.saldo
self.saldo += valor
saldo_depois = self.saldo
# Registrar no extrato
self._extrato.append({
"tipo": "deposito",
"valor": valor,
"saldo_antes": saldo_antes,
"saldo_depois": saldo_depois
})
return True
def sacar(self, valor):
"""Tenta sacar. Retorna True se sucesso, False se insuficiente ou valor inválido."""
try:
valor = float(valor)
except (TypeError, ValueError):
return False
if valor <= 0:
return False
disponivel = self.saldo + self.limite
if valor > disponivel:
# Não permite extrapolar o limite
return False
saldo_antes = self.saldo
self.saldo -= valor
saldo_depois = self.saldo
self._extrato.append({
"tipo": "saque",
"valor": valor,
"saldo_antes": saldo_antes,
"saldo_depois": saldo_depois
})
return True
def ver_extrato(self):
"""Retorna uma cópia da lista de operações (extrato)."""
return list(self._extrato)
def salvar_extrato(self, arquivo):
"""
Salva o extrato em um arquivo texto.
Retorna True se sucesso, False se ocorreu erro de escrita.
"""
try:
with open(arquivo, "w", encoding="utf-8") as f:
f.write(f"Extrato da conta: {self.codigo}\n")
f.write(f"Saldo atual: {self.saldo}\n")
f.write(f"Limite: {self.limite}\n")
f.write("-" * 40 + "\n")
for op in self._extrato:
linha = (
f"{op['tipo'].upper():8} | "
f"VALOR: {op['valor']:,.2f} | "
f"ANTES: {op['saldo_antes']:,.2f} | "
f"DEPOIS: {op['saldo_depois']:,.2f}\n"
)
f.write(linha)
return True
except Exception:
return False