-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: adição seção módulos customizados
- Loading branch information
1 parent
08ea610
commit d787d26
Showing
6 changed files
with
335 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,4 +8,7 @@ _build | |
.ipynb_checkpoints | ||
|
||
# Ambiente virtual | ||
.venv | ||
.venv | ||
|
||
# Scripts | ||
scripts/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,330 @@ | ||
{ | ||
"cells": [ | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"# Módulos customizados" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"Nós já aprendemos sobre funções e módulos nativos. Agora é hora de elevar o nível e aprender a criar nossos próprios módulos. Vamos começar com um exemplo de projeto pra explicar e contextualizar sobre módulos customizados.\n", | ||
"\n", | ||
"```{admonition} Nota (múltiplos arquivos .py)\n", | ||
":class: attention\n", | ||
"Neste capítulo, vamos trabalhar com múltiplos arquivos *.py*. Para fins didáticos, no início de cada código eu vou colocar o nome do arquivo no qual o código está sendo escrito. Por exemplo, se o código está sendo escrito no arquivo *estoque.py*, eu vou colocar o seguinte comentário no início do código: `# estoque.py`. Ou então se o arquivo está dentro de uma pasta chamada *funcoes*, por exemplo, eu vou informar o caminho relativo do arquivo da seguinte forma: `# funcoes/estoque.py`. Preste atenção nesses comentários para saber em qual arquivo o código está sendo escrito.\n", | ||
"\n", | ||
"Isso é apenas para fins didáticos, pois no mundo real, você não precisa colocar tais comentários.\n", | ||
"```" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"## O projeto" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"Vamos começar com um exemplo de projeto de um sistema de gerenciamento de vendas online simulando um e-commerce." | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 2, | ||
"metadata": {}, | ||
"outputs": [ | ||
{ | ||
"name": "stdout", | ||
"output_type": "stream", | ||
"text": [ | ||
"Usuário Henrique registrado com sucesso!\n", | ||
"1. Verificar Saldo\n", | ||
"2. Depositar\n", | ||
"3. Sacar\n", | ||
"4. Mostrar Transações\n", | ||
"5. Sair\n", | ||
"Seu saldo é: 0\n" | ||
] | ||
} | ||
], | ||
"source": [ | ||
"# sistema_bancario.py\n", | ||
"\n", | ||
"usuarios = {}\n", | ||
"\n", | ||
"\n", | ||
"def registrar_usuario(nome: str) -> None:\n", | ||
" usuarios[nome] = {\"saldo\": 0, \"transacoes\": []}\n", | ||
" print(f\"Usuário {nome} registrado com sucesso!\")\n", | ||
"\n", | ||
"\n", | ||
"def verificar_saldo(nome: str) -> int:\n", | ||
" return usuarios[nome][\"saldo\"]\n", | ||
"\n", | ||
"\n", | ||
"def depositar(nome: str, quantia: int) -> None:\n", | ||
" usuarios[nome][\"saldo\"] += quantia\n", | ||
" usuarios[nome][\"transacoes\"].append(f\"Depositou {quantia}\")\n", | ||
" print(f\"Depositou {quantia} na conta de {nome}.\")\n", | ||
"\n", | ||
"\n", | ||
"def sacar(nome: str, quantia: int) -> None:\n", | ||
" if quantia > usuarios[nome][\"saldo\"]:\n", | ||
" print(\"Saldo insuficiente!\")\n", | ||
" else:\n", | ||
" usuarios[nome][\"saldo\"] -= quantia\n", | ||
" usuarios[nome][\"transacoes\"].append(f\"Sacou {quantia}\")\n", | ||
" print(f\"Sacou {quantia} da conta de {nome}.\")\n", | ||
"\n", | ||
"\n", | ||
"# Histórico de Transações\n", | ||
"def mostrar_transacoes(nome: str) -> list:\n", | ||
" return usuarios[nome][\"transacoes\"]\n", | ||
"\n", | ||
"\n", | ||
"# Descomente a linha abaixo para capturar do terminal um nome\n", | ||
"# nome = input(\"Digite seu nome para registrar: \")\n", | ||
"nome = \"Henrique\"\n", | ||
"registrar_usuario(nome)\n", | ||
"\n", | ||
"while True:\n", | ||
" print(\"1. Verificar Saldo\")\n", | ||
" print(\"2. Depositar\")\n", | ||
" print(\"3. Sacar\")\n", | ||
" print(\"4. Mostrar Transações\")\n", | ||
" print(\"5. Sair\")\n", | ||
"\n", | ||
" # Descomente a linha abaixo para capturar do terminal uma opção\n", | ||
" # opcao = int(input(\"Escolha uma opção: \"))\n", | ||
" opcao = 1\n", | ||
"\n", | ||
" if opcao == 1:\n", | ||
" print(f\"Seu saldo é: {verificar_saldo(nome)}\")\n", | ||
" # Remova a instrução break para o loop funcionar\n", | ||
" break\n", | ||
" elif opcao == 2:\n", | ||
" quantia = float(input(\"Digite a quantia para depositar: \"))\n", | ||
" depositar(nome, quantia)\n", | ||
" # Remova a instrução break para o loop funcionar\n", | ||
" break\n", | ||
" elif opcao == 3:\n", | ||
" quantia = float(input(\"Digite a quantia para sacar: \"))\n", | ||
" sacar(nome, quantia)\n", | ||
" # Remova a instrução break para o loop funcionar\n", | ||
" break\n", | ||
" elif opcao == 4:\n", | ||
" print(f\"Transações: {mostrar_transacoes(nome)}\")\n", | ||
" # Remova a instrução break para o loop funcionar\n", | ||
" break\n", | ||
" elif opcao == 5:\n", | ||
" print(\"Até mais!\")\n", | ||
" # Este break é o de saída do loop! Não remova!\n", | ||
" break\n", | ||
" else:\n", | ||
" print(\"Opção inválida. Tente novamente.\")\n" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"Tome o tempo que for necessário e leia o código acima. Nesta altura do livro, não há nada acima que não tenha sido ensinado aqui no livro. **Não continue a leitura até que você tenha entendido a ideia do projeto**. Não se preocupe em entender cada detalhe do código, o importante é ter uma visão geral do que está sendo feito. Se você não entendeu algo, volte e revise os capítulos anteriores referentes ao tema que você não entendeu." | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"# Separando o projeto em módulos" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"Conforme vimos no final do código, ele funciona, mas o projeto está um pouco longo (mais que 70 linhas) e acaba ficando um pouco confuso e difícil de manter. Vamos dividir o código em módulos customizados para facilitar a manutenção e organização do código.\n", | ||
"\n", | ||
"Se observarmos o nosso projeto, ele contém alguns grandes blocos:\n", | ||
"\n", | ||
"- Controlar e registrar usuários do sistema bancário\n", | ||
"\n", | ||
"- Realizar operações na conta bancária (saque, depósito, ver saldo)\n", | ||
"\n", | ||
"- Ver o histórico de transações\n", | ||
"\n", | ||
"- Fluxo principal do sistema (escolha e execução das operações)\n", | ||
"\n", | ||
"Dada essa divisão, vamos criar um módulo para cada um desses blocos. Cada módulo vai ser um arquivo `.py` separado. Vou criar os sequintes arquivos (a princípio em branco): \n", | ||
"\n", | ||
"- *gerenciamento_usuarios.py*\n", | ||
"- *gerenciamento_contas.py*\n", | ||
"- *historico_transacoes.py*\n", | ||
"- *sistema.py*\n", | ||
" \n", | ||
"Cada um deles vai conter um dos blocos acima. Vamos começar com o arquivo *gerenciamento_usuarios.py*:\n", | ||
"\n", | ||
"```python\n", | ||
"# gerenciamento_usuarios.py\n", | ||
"usuarios = {}\n", | ||
"\n", | ||
"\n", | ||
"def registrar_usuario(nome):\n", | ||
" usuarios[nome] = {\"saldo\": 0, \"transacoes\": []}\n", | ||
" print(f\"Usuário {nome} registrado com sucesso!\")\n", | ||
"```\n", | ||
"\n", | ||
"Até aqui nenhuma novidade. O que vem a seguir representa a importação dos dados em outro módulo.\n", | ||
"\n", | ||
"```python\n", | ||
"# gerenciamento_contas.py\n", | ||
"from gerenciamento_usuarios import usuarios\n", | ||
"\n", | ||
"\n", | ||
"def verificar_saldo(nome):\n", | ||
" return usuarios[nome][\"saldo\"]\n", | ||
"\n", | ||
"\n", | ||
"def depositar(nome, quantia):\n", | ||
" usuarios[nome][\"saldo\"] += quantia\n", | ||
" usuarios[nome][\"transacoes\"].append(f\"Depositou {quantia}\")\n", | ||
" print(f\"Depositou {quantia} na conta de {nome}.\")\n", | ||
"\n", | ||
"\n", | ||
"def sacar(nome, quantia):\n", | ||
" if quantia > usuarios[nome][\"saldo\"]:\n", | ||
" print(\"Saldo insuficiente!\")\n", | ||
" else:\n", | ||
" usuarios[nome][\"saldo\"] -= quantia\n", | ||
" usuarios[nome][\"transacoes\"].append(f\"Sacou {quantia}\")\n", | ||
" print(f\"Sacou {quantia} da conta de {nome}.\")\n", | ||
"```\n", | ||
"\n", | ||
"Em *gerenciamento_contas.py*, logo na primeira linha, estamos importando do módulo `gerenciamento_usuarios` a variável `usuarios`.\n", | ||
"\n", | ||
"Vamos seguir com a divisão.\n", | ||
"\n", | ||
"```python\n", | ||
"# historico_transacoes.py\n", | ||
"from gerenciamento_usuarios import usuarios\n", | ||
"\n", | ||
"\n", | ||
"def mostrar_transacoes(nome):\n", | ||
" return usuarios[nome][\"transacoes\"]\n", | ||
"```\n", | ||
"\n", | ||
"E, finalmente, o arquivo **sistema.py**:\n", | ||
"\n", | ||
"```python\n", | ||
"# sistema.py\n", | ||
"from gerenciamento_contas import depositar, sacar, verificar_saldo\n", | ||
"from gerenciamento_usuarios import registrar_usuario\n", | ||
"from historico_transacoes import mostrar_transacoes\n", | ||
"\n", | ||
"nome = \"Henrique\"\n", | ||
"registrar_usuario(nome)\n", | ||
"\n", | ||
"while True:\n", | ||
" print(\"1. Verificar Saldo\")\n", | ||
" print(\"2. Depositar\")\n", | ||
" print(\"3. Sacar\")\n", | ||
" print(\"4. Mostrar Transações\")\n", | ||
" print(\"5. Sair\")\n", | ||
"\n", | ||
" # Descomente a linha abaixo para capturar do terminal uma opção\n", | ||
" # opcao = int(input(\"Escolha uma opção: \"))\n", | ||
" opcao = 1\n", | ||
"\n", | ||
" if opcao == 1:\n", | ||
" print(f\"Seu saldo é: {verificar_saldo(nome)}\")\n", | ||
" # Remova a instrução break para o loop funcionar\n", | ||
" break\n", | ||
" elif opcao == 2:\n", | ||
" quantia = float(input(\"Digite a quantia para depositar: \"))\n", | ||
" depositar(nome, quantia)\n", | ||
" # Remova a instrução break para o loop funcionar\n", | ||
" break\n", | ||
" elif opcao == 3:\n", | ||
" quantia = float(input(\"Digite a quantia para sacar: \"))\n", | ||
" sacar(nome, quantia)\n", | ||
" # Remova a instrução break para o loop funcionar\n", | ||
" break\n", | ||
" elif opcao == 4:\n", | ||
" print(f\"Transações: {mostrar_transacoes(nome)}\")\n", | ||
" # Remova a instrução break para o loop funcionar\n", | ||
" break\n", | ||
" elif opcao == 5:\n", | ||
" print(\"Até mais!\")\n", | ||
" # Este break é o de saída do loop! Não remova!\n", | ||
" break\n", | ||
" else:\n", | ||
" print(\"Opção inválida. Tente novamente.\")\n", | ||
"```\n", | ||
"\n", | ||
"Quem permite reutilizar funções, variáveis e outras coisas de módulos são as linhas de importações, como em *sistema.py*:\n", | ||
"\n", | ||
"```python\n", | ||
"# sistema.py\n", | ||
"from gerenciamento_contas import depositar, sacar, verificar_saldo\n", | ||
"from gerenciamento_usuarios import registrar_usuario\n", | ||
"from historico_transacoes import mostrar_transacoes\n", | ||
"...\n", | ||
"```\n", | ||
"\n", | ||
"Essas linhas importam as funções `depositar`, `sacar`, `verificar_saldo`, `registrar_usuario` e `mostrar_transacoes` dos respectivos módulos. Cada módulo representa um arquivo `.py`.\n", | ||
"\n", | ||
"Se você executar o script *sistema.py*, o projeto vai funcionar da mesma forma que antes, mas agora está organizado em módulos customizados. Cada módulo é responsável por uma parte do projeto.\n", | ||
"\n", | ||
"No final a organização do nosso projeto ficou conforme a imagem abaixo:\n", | ||
"\n", | ||
"```{image} ../img/09-03-modulos.png\n", | ||
"```" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"## Visão geral" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"Poderíamos avançar no tema e aprofundar ainda mais, mas não vamos. A ideia principal é que você compreenda o conceito básico da divisão em módulos, cada um com sua própria responsabilidade.\n", | ||
"\n", | ||
"É possível dividir de várias formas, e não existe uma regra sobre como fazer tal divisão. Normalmente a divisão é baseada em responsabilidades e funcionalidades. Cada módulo deve ser responsável por uma parte ou escopo específico. E quem define isso é você, meu caro leitor! Aqui assumo que é necessário um pouco de criatividade para enxergar tais divisões, sim. Eu nunca disse que quem programa não precisa ser criativo... 😉\n", | ||
"\n", | ||
"É possível organizar ainda o projeto não só em módulos (arquivos `.py` separados) mas também em pastas e subpastas. Mas, por enquanto, vamos ficar com o mais simples." | ||
] | ||
} | ||
], | ||
"metadata": { | ||
"kernelspec": { | ||
"display_name": ".venv", | ||
"language": "python", | ||
"name": "python3" | ||
}, | ||
"language_info": { | ||
"codemirror_mode": { | ||
"name": "ipython", | ||
"version": 3 | ||
}, | ||
"file_extension": ".py", | ||
"mimetype": "text/x-python", | ||
"name": "python", | ||
"nbconvert_exporter": "python", | ||
"pygments_lexer": "ipython3", | ||
"version": "3.12.2" | ||
} | ||
}, | ||
"nbformat": 4, | ||
"nbformat_minor": 2 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
This file was deleted.
Oops, something went wrong.