Médio Python
Conta com atributo de classe
Enunciado
Crie a classe Conta com um atributo de classe total_contas que conta quantas instâncias já foram criadas. Cada conta tem titular e saldo (atributos de instância). Adicione os métodos depositar(valor) e sacar(valor), sendo que sacar deve levantar ValueError("saldo insuficiente") se o valor for maior que o saldo. Imprima o total de contas criadas.
Requisitos
Conta.total_contascomeça em 0 e é incrementado a cada nova instância.depositarsoma ao saldo;sacarsubtrai, mas levantaValueErrorse faltar saldo.- O programa cria duas contas e imprime
Conta.total_contas. - A saída final contém o total igual a 2.
Código inicial
class Conta:
total_contas = 0
def __init__(self, titular, saldo=0.0):
# incremente o contador de classe e guarde atributos de instância
pass
def depositar(self, valor):
pass
def sacar(self, valor):
pass
c1 = Conta("Ana", 100.0)
c2 = Conta("Bruno")
c1.depositar(50)
c1.sacar(30)
print("Total de contas:", Conta.total_contas)
print("Saldo Ana:", c1.saldo)
Saída esperada
Total de contas: 2
Saldo Ana: 120.0
Ver dica
Para alterar o atributo de classe use Conta.total_contas += 1 (ou type(self).total_contas += 1). self.total_contas também funciona, mas cria um atributo de instância se você atribuir.
Mostrar solução
class Conta:
# atributo de classe: pertence à classe, não à instância
total_contas = 0
def __init__(self, titular, saldo=0.0):
self.titular = titular
self.saldo = saldo
# incrementa o contador compartilhado
Conta.total_contas += 1
def depositar(self, valor):
if valor <= 0:
raise ValueError("valor deve ser positivo")
self.saldo += valor
def sacar(self, valor):
if valor > self.saldo:
raise ValueError("saldo insuficiente")
self.saldo -= valor
c1 = Conta("Ana", 100.0)
c2 = Conta("Bruno")
c1.depositar(50)
c1.sacar(30)
print("Total de contas:", Conta.total_contas)
print("Saldo Ana:", c1.saldo)
Passo a passo
total_contas = 0é definido no corpo da classe, então é um atributo de classe compartilhado.__init__recebetitularesaldoe os guarda como atributos de instância comself.titulareself.saldo.- A linha
Conta.total_contas += 1atualiza o atributo da classe, contando cada criação. depositarvalida o valor e soma ao saldo do objeto atual (self.saldo).sacarverifica se há saldo suficiente; se não, levantaValueError.- Criamos
c1ec2; cada chamada aConta(...)roda__init__e incrementa o contador. c1.depositar(50)ec1.sacar(30)alteram apenas o saldo dec1.- Imprimimos
Conta.total_contas(2) ec1.saldo(120.0).
Por que funciona
Atributos de classe existem uma única vez e são acessados por Classe.atributo. Como __init__ roda em toda criação de objeto, incrementar Conta.total_contas ali garante a contagem correta. Já self.saldo é individual: alterar c1.saldo não afeta c2.saldo, exatamente o comportamento desejado.
Erros comuns
- Escrever
total_contas += 1sem prefixo dentro de__init__geraUnboundLocalError, pois o Python trata como variável local. - Usar
self.total_contas += 1cria um atributo de instância que sombreia o da classe; o contador da classe fica em 0 e a contagem quebra. - Em
sacar, compararvalor > self.saldoantes de checar valores negativos pode aceitar saques negativos; valide entradas.
Outra forma de resolver
Use type(self).total_contas += 1 para funcionar também em subclasses:
type(self).total_contas += 1
Assim, se ContaEspecial(Conta) existir, o contador da subclasse é usado em vez do da classe base.
Saída esperada
Total de contas: 2
Saldo Ana: 120.0