Desafio
Fomos contratados por um grande banco para desenvolver o seu novo sistema. Esse banco deseja modernizar suas operações e para isso escolheu a linguagem Python.
Para a primeira versão do sistema devemos implementar apenas 3 operações: depósito, saque e extrato.
Para segunda versão precisamos deixar o código modularizado com funções e introduzir novas funcionalidades: criar usuário do banco e criar conta corrente, que vincula com o usuário.
Link ao original
Objetivo
Refatorar e expandir um sistema bancário simples utilizando funções em Python, dividindo a lógica em pequenos blocos de responsabilidade, aplicando validações e uso correto de argumentos.
Contexto
O desafio consiste em pegar um sistema bancário que antes rodava em um fluxo único e modularizar o código usando funções. Além disso, o sistema deve ser expandido para permitir a criação e associação de clientes (usuários) e suas respectivas contas bancárias (contas correntes).
- Operações Básicas: Depositar, sacar e exibir extrato.
- Novas Entidades: Cadastrar usuário (cliente) e cadastrar conta corrente vinculada a um usuário.
Passo a Passo
Passo 1: Separando as Operações Básicas em Funções
A primeira etapa consiste em organizar o fluxo principal, movendo as operações existentes de depósito, saque e extrato para dentro de funções específicas. O desafio impõe regras claras de como os argumentos devem ser recebidos em cada uma:
depositar: Deve receber argumentos apenas por posição (saldo,valor,extrato) e retornarsaldoeextrato.sacar: Deve receber argumentos apenas por nome (saldo,valor,extrato,limite,numero_saques,limite_saques) e retornarsaldoeextrato.exibir_extrato: Recebesaldopor posição eextratopor nome.
# Utilização de barras (/) e asteriscos (*) para definir tipos de argumentos
def depositar(saldo, valor, extrato, /):
# Lógica de depósito com atualizações de saldo e extrato
return saldo, extrato
def sacar(*, saldo, valor, extrato, limite, numero_saques, limite_saques):
# Lógica de saque e validações (saldo, limite, número de saques diários)
return saldo, extrato
def exibir_extrato(saldo, /, *, extrato):
# Exibição do extrato e formatação
passPasso 2: Filtrando e Criando Usuários
Agora vamos criar a funcionalidade para cadastrar clientes. Cada cliente será um dicionário contendo nome, data de nascimento, CPF (apenas números) e endereço completo, e ficará armazenado em uma lista de usuários.
Validação de CPF
Não podem existir dois clientes com o mesmo CPF! Antes de cadastrar um novo usuário, é vital checar se aquele CPF já existe na lista. Criar uma função dedicada de
filtrar_usuariofacilita não apenas essa etapa, mas também na hora de criar contas depois.
def filtrar_usuario(cpf, usuarios):
# Usando list comprehension para buscar o CPF na lista
usuarios_filtrados = [usuario for usuario in usuarios if usuario["cpf"] == cpf]
return usuarios_filtrados[0] if usuarios_filtrados else None
def criar_usuario(usuarios):
cpf = input("Informe o CPF (somente número): ")
usuario = filtrar_usuario(cpf, usuarios)
if usuario:
print("\n@@@ Já existe um usuário com esse CPF! @@@")
return # Interrompe o fluxo e volta ao menu
nome = input("Informe o nome completo: ")
data_nascimento = input("Informe a data de nascimento (dd-mm-aaaa): ")
endereco = input("Informe o endereço (logradouro, nro - bairro - cidade/UF): ")
# Adicionando na lista de usuários recebida por parâmetro
usuarios.append({"nome": nome, "data_nascimento": data_nascimento, "cpf": cpf, "endereco": endereco})
print("=== Usuário criado com sucesso! ===")Passo 3: Criando as Contas Correntes
Uma conta corrente deve sempre pertencer a um usuário. Portanto, a conta será um dicionário contendo a agencia (fixada em "0001"), o numero_conta (sequencial iniciando em 1) e o próprio usuario.
Número Sequencial Simples
Como nesse desafio as contas não podem ser excluídas, o número da próxima conta pode ser descoberto calculando o tamanho da nossa lista atual de contas e somando 1:
len(contas) + 1.
def criar_conta(agencia, numero_conta, usuarios):
cpf = input("Informe o CPF do usuário: ")
usuario = filtrar_usuario(cpf, usuarios) # Reaproveitamos a função!
if usuario:
print("\n=== Conta criada com sucesso! ===")
# Retorna o dicionário da conta, que depois sofrerá um .append() na lista principal
return {"agencia": agencia, "numero_conta": numero_conta, "usuario": usuario}
print("\n@@@ Usuário não encontrado! Fluxo de criação de conta encerrado. @@@")
return NonePasso 4: Listando Contas e Loop Principal
Para finalizar e testar as novidades, precisamos de uma função para visualizar as contas cadastradas de forma estruturada. Todo esse sistema é executado através de uma função main(), que gerencia um loop infinito (o menu de opções) e armazena as listas mestres de usuários e de contas.
def listar_contas(contas):
for conta in contas:
# Formatação de string em múltiplas linhas
linha = f"""\
Agência:\t{conta['agencia']}
C/C:\t\t{conta['numero_conta']}
Titular:\t{conta['usuario']['nome']}
"""
print("=" * 50)
print(linha)
def main():
# Inicialização das variáveis mestres (estado do sistema)
usuarios = []
contas = []
# Loop de menu chamando as funções recém-criadas...