Skip to content

Commit

Permalink
feat: adição seção módulos customizados
Browse files Browse the repository at this point in the history
  • Loading branch information
HenriqueAJNB committed Sep 30, 2024
1 parent 08ea610 commit d787d26
Show file tree
Hide file tree
Showing 6 changed files with 335 additions and 9 deletions.
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,7 @@ _build
.ipynb_checkpoints

# Ambiente virtual
.venv
.venv

# Scripts
scripts/
330 changes: 330 additions & 0 deletions book/09-modulos/03-modulos-proprios.ipynb
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
}
1 change: 1 addition & 0 deletions book/_toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ parts:
chapters:
- file: 09-modulos/01-introducao.ipynb
- file: 09-modulos/02-modulos-nativos.ipynb
- file: 09-modulos/03-modulos-proprios.ipynb

- caption: Pratique
chapters:
Expand Down
Binary file added book/img/09-03-modulos.png
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.
8 changes: 0 additions & 8 deletions scripts/meu_primeiro_script.py

This file was deleted.

0 comments on commit d787d26

Please sign in to comment.