Na parte 1 vimos como criar módulos. Criamos o módulo "funcoes" e usamos esse módulo dentro de nosso programa, o "programa.py".
Mas imaginem que criei um programa, a partir do programa anterior, que é uma calculadora científica com as mais diversas funções estatísticas. Tem função de soma, subtração, multiplicação, divisão, média, média ponderada, média geométrica, desvio padrão, desvio padrão relativo, variância, testes estatísticos, etc. Um programa relativamente grande. Além da parte de cálculo, meu programa gera gráficos das análises estatísticas e tem diversas outras funções.
Como o programa ficou grande, usar somente módulos pode deixar as coisas bastante desorganizadas. Teria um módulo para cálculos simples, outro para cálculos mais complexos, outro para testes estatísticos diversos, que só aqui é um mundo à parte, outro para a geração dos gráficos, outro para a interface gráfica, etc. Seriam muitos módulos para gerenciar e deixar tudo em formato de módulo pode não ser uma boa forma de organização.
Para casos assim, nos quais o programa fica grande o bastante para módulos não serem a melhor resposta, podemos usar pacotes.
Ao criar pacotes, eu poderia criar um pacote de cálculos básicos, e inserir dentro desse pacote módulos de cálculos básicos. Poderia criar outro pacote para os cálculos estatísticos, e dentro desse pacote inserir módulos para cálculos estatísticos. Outro pacote para a geração dos gráficos, e inserir nesse pacote módulos que seriam responsáveis pela parte de geração de gráficos. Outro pacote teria os módulos necessários para a interface gráfica, etc.
Pacotes nada menos são do que uma pasta com diversos módulos dentro dela. Abaixo, uma estrutura parecida com o que expliquei acima:
3.7 pt2$ tree
.
+-- pacotes
¦ +-- calculos_basicos
¦ ¦ +-- __init__.py
¦ +-- calculos_estatisticos
¦ ¦ +-- __init__.py
¦ +-- graficos
¦ ¦ +-- __init__.py
¦ +-- interface
¦ +-- __init__.py
+-- programa.py
Acima, temos um diretório raiz, nele temos nosso programa "programa.py", e a pasta (pacote) chamada pacotes. Dentro dessa pasta temos 4 outras pastas, "calculos_basicos", "calculos_estatisticos", "graficos" e "interface" e dentro de cada uma temos um arquivo chamado "__init__.py". O nome do arquivo dessa forma é necessário para o Python entender que cada pasta é um pacote.
Agora, imaginem que eu adicionei as funções do tópico anterior dentro do pacote "calculos_basicos", em seu __init__.py:
# /calculos_basicos/__init__.py
def raiz(x, y):
"""
Recebe dois valores, x e y, onde x é o radicando e y é o índice.
Calcula a raiz de x no índice y.
"""
return x ** (1/y)
def fatorial(n):
"""
Calcula o fatorial de um número n.
"""
f = 1
for i in range(1, n+1):
f *= i
return f
def divisao(x, y):
"""
Calcula a divisão de x por y, retornando uma tupla com o resto e o quociente.
"""
resto = x % y
quociente = x // y
return (resto, quociente)
E dentro de meu "programa.py":
# programa.py
from pacotes import calculos_basicos
a = calculos_basicos.raiz(4, 2)
print(a)
# Retorna
# 2.0
O resultado é parecido com o obtido no tópico sobre módulos.
Também podemos deixar o arquivo __init__.py vazio e criar outros arquivos dentro do pacote usando classes mas isso é assunto pra parte de orientação a objetos:
.
+-- pacotes
¦ +-- calculos_basicos
¦ ¦ +-- __init__.py
¦ ¦ +-- raiz.py
...
+-- programa.py
Percebam que criei um arquivo raiz.py. Dentro de calculos_basicos, deixei __init__.py vazio e meu raiz.py ficou assim:
# raiz.py
class Raiz:
def __init__(self, x, y):
self.raiz = x ** (1/y)
def __str__(self):
return f'{self.raiz}'
E meu programa.py ficou assim:
# programa.py
from pacotes.calculos_basicos import raiz
a = raiz.Raiz(4, 2)
print(a)
# Retorna
# 2.0
Como dito, acima usei conceitos de orientação a objetos que é assunto pra depois, mas já fica o gostinho aqui. Poderia explicar um pouco além disso mas não é algo que convém agora.
Esse assunto pode parecer algo abstrato demais agora num primeiro momento mas como falei no tópico anterior, a intenção é abrir uma nova série de posts com um projeto por aqui criando uma aplicação web e nesse projeto iremos criar pacotes ou usar pacotes já existentes no framework que será usado, então conceitos como módulos e pacotes devem ser bem entendidos.