Nesta aula, vamos explorar o conceito de módulos em Python, que são arquivos contendo definições e instruções que podem ser reutilizados em outros programas. Módulos são fundamentais para organizar código, evitar repetição e facilitar a manutenção. Você aprenderá a importar módulos de várias maneiras, a entender o comportamento da variável especial __name__ e a estruturar seus projetos de forma eficiente.

Dominar módulos é essencial para qualquer programador Python, pois permite construir aplicações maiores e mais complexas de maneira organizada. Vamos começar com o básico e progredir para tópicos mais avançados, com exemplos práticos que você pode testar em seu próprio ambiente.

import

A instrução import é a forma mais simples de usar um módulo em Python. Quando você escreve import nome_do_modulo, o interpretador procura pelo arquivo nome_do_modulo.py nos diretórios listados na variável sys.path e o executa, disponibilizando suas funções, classes e variáveis no namespace atual, mas acessíveis apenas através da sintaxe modulo.nome.

Por exemplo, o módulo padrão math fornece funções matemáticas. Para usá-lo, fazemos:

import math
print(math.sqrt(16))  # 4.0

Isso evita conflitos de nomes, pois todas as referências ao módulo são qualificadas. É uma boa prática para evitar ambiguidades, especialmente em projetos grandes.

Formas de importar

Existem várias formas de importar módulos, cada uma com suas vantagens e desvantagens. A primeira é a importação direta de itens específicos usando from ... import .... Isso permite usar o nome diretamente, sem o prefixo do módulo:

from math import sqrt
print(sqrt(25))  # 5.0

Você também pode importar múltiplos itens de uma vez: from math import sqrt, pi. Outra forma é usar um alias, útil para nomes longos: import numpy as np. Isso é comum em bibliotecas como pandas e numpy.

Há ainda a importação de todos os itens com from math import *, que não é recomendado porque pode poluir o namespace e causar conflitos. Prefira sempre importar apenas o que você precisa.

__name__ == "__main__"

A variável __name__ é uma variável especial que o Python define em cada módulo. Quando um módulo é executado diretamente (como script principal), __name__ é definido como a string "__main__". Quando o módulo é importado, __name__ é definido como o nome do módulo (sem a extensão .py).

Essa distinção é crucial para escrever código que pode ser tanto executado diretamente quanto importado sem efeitos colaterais indesejados. O padrão comum é:

def main():
    print("Executando diretamente")

if __name__ == "__main__":
    main()

Assim, se o arquivo for executado como script, a função main() roda; se for importado, ela não roda, permitindo que outras partes do código usem as funções definidas sem executar ações desnecessárias.

Organização

Organizar seu código em módulos é uma prática essencial para projetos escaláveis. Uma boa estrutura pode incluir uma pasta para o projeto, com subpastas para módulos relacionados. Por exemplo:

meu_projeto/
    __init__.py
    main.py
    utils/
        __init__.py
        helpers.py
    models/
        __init__.py
        usuario.py

O arquivo __init__.py pode estar vazio, mas indica que a pasta é um pacote Python. Você pode importar módulos de pacotes usando a notação de ponto: from utils.helpers import funcao.

Além disso, é importante manter módulos pequenos e com responsabilidade única. Isso facilita a leitura, testes e manutenção. Evite colocar muitas funcionalidades em um único arquivo; divida em módulos coesos.

Boas práticas

Algumas boas práticas ao trabalhar com módulos: use nomes descritivos para seus módulos, evite importações circulares (quando dois módulos se importam mutuamente), e sempre coloque a lógica de execução dentro de if __name__ == "__main__": para permitir reutilização.

Também é recomendado usar aliases para bibliotecas comuns, mas com moderação. E lembre-se de que a importação de um módulo executa seu código no topo, então evite efeitos colaterais no nível do módulo.

Exercícios

  1. Crie um módulo chamado operacoes.py com funções para somar, subtrair, multiplicar e dividir. Em outro arquivo, importe e use essas funções.
  2. ✓ Resposta:
    # operacoes.py
    def soma(a, b):
        return a + b
    
    def subtracao(a, b):
        return a - b
    
    def multiplicacao(a, b):
        return a * b
    
    def divisao(a, b):
        if b == 0:
            raise ValueError("Divisão por zero")
        return a / b
    
    # uso.py
    import operacoes
    print(operacoes.soma(10, 5))
    print(operacoes.divisao(10, 2))
  3. Escreva um script que use from math import factorial e calcule o fatorial de 5.
  4. ✓ Resposta:
    from math import factorial
    print(factorial(5))  # 120
  5. Explique o que acontece quando você executa um módulo diretamente vs importá-lo, em relação ao __name__.
  6. ✓ Resposta: Quando executado diretamente, __name__ é "__main__"; quando importado, é o nome do módulo. Isso permite controlar se o código deve rodar ou não.
  7. Crie um pacote chamado meu_pacote com dois módulos: modulo1.py e modulo2.py. No primeiro, defina uma função ola(); no segundo, importe e chame essa função.
  8. ✓ Resposta:
    # meu_pacote/__init__.py (vazio)
    # meu_pacote/modulo1.py
    def ola():
        print("Olá!")
    
    # meu_pacote/modulo2.py
    from meu_pacote.modulo1 import ola
    ola()
  9. Refatore o código a seguir para usar módulos: suponha que você tenha funções de validação de email e CPF. Coloque-as em um módulo validacoes.py e importe-as em um arquivo principal.
  10. ✓ Resposta:
    # validacoes.py
    def valida_email(email):
        return "@" in email
    
    def valida_cpf(cpf):
        return len(cpf) == 11
    
    # main.py
    from validacoes import valida_email, valida_cpf
    print(valida_email("teste@exemplo.com"))
    print(valida_cpf("12345678901"))

Referências