Boas Práticas & Modularidade em Python

Laboratório de Programação — Ciência da Computação

PEP 8, legibilidade, testes, tratamento de exceções, módulos, pacotes, imports e ambientes virtuais.

Por que Boas Práticas?

  • Código legível, manutenível e testável.
  • Facilita colaboração, revisão e evolução do projeto.
  • Reduz bugs e custos de manutenção.

Dica Adote um guia de estilo (PEP 8) e automatize checagens no CI.

PEP 8 (estilo)

  • Indentação: 4 espaços
  • Linhas ≤ 79 colunas
  • snake_case para funções/variáveis
  • CapWords para classes
# bom
def calcular_media(notas: list[float]) -> float:
    return sum(notas) / len(notas)

Nomes descritivos

# ruim
def f(x): return x*x + 2*x + 1

# bom
def parabola(valor: float) -> float:
    return valor*valor + 2*valor + 1

Comentários & Docstrings

def calcular_fatorial(n: int) -> int:
    """Calcula o fatorial de n (n >= 0).
    Retorna:
        int: n!
    """
    if n < 0:
        raise ValueError("n deve ser não-negativo")
    return 1 if n == 0 else n * calcular_fatorial(n-1)

Use docstrings para o quê e por quê. Comentários em linha para o como quando necessário.

Organização

  • Arquivos curtos, funções pequenas e coesas.
  • Separe responsabilidade: lógica vs. I/O.
  • Estruture pastas por domínio e camadas.
meu_projeto/
├─ meu_projeto/
│  ├─ __init__.py
│  ├─ dominio/
│  │  ├─ __init__.py
│  │  └─ pedidos.py
│  ├─ infra/
│  │  ├─ __init__.py
│  │  └─ repositorio.py
│  └─ app.py
├─ tests/
│  └─ test_pedidos.py
└─ requirements.txt

Validação de Entrada

def ler_inteiro(prompt="Digite um número inteiro: ") -> int:
    while True:
        valor = input(prompt).strip()
        if valor.lstrip("-").isdigit():
            return int(valor)
        print("Entrada inválida. Tente novamente.")

Tratamento de Exceções

from pathlib import Path

def carregar_arquivo(caminho: str) -> str:
    try:
        return Path(caminho).read_text(encoding="utf-8")
    except FileNotFoundError:
        return "Arquivo não encontrado."
    except OSError as e:
        return f"Erro de I/O: {e}"

Capture apenas o que você sabe tratar; registre o restante.

I/O com segurança

from pathlib import Path

def salvar_texto(caminho: str, conteudo: str) -> None:
    p = Path(caminho)
    p.parent.mkdir(parents=True, exist_ok=True)
    p.write_text(conteudo, encoding="utf-8")

Evite repetição

# centralize lógica comum em funções
def media(valores: list[float]) -> float:
    return sum(valores)/len(valores) if valores else 0.0

Testes Unitários

# tests/test_media.py
import pytest
from meu_projeto.dominio.pedidos import media

def test_media_lista():
    assert media([1,2,3]) == 2

def test_media_vazia():
    assert media([]) == 0.0

Use pytest, mocks para I/O e rode no CI.

Documentação

  • Docstrings + README + exemplos executáveis.
  • Comente decisões de design relevantes.
def calcular_imposto(salario: float) -> float:
    """Calcula IR estimado (didático).
    Parâmetros:
        salario (float): salário bruto.
    Retorno:
        float: imposto devido.
    """
    return max(salario * 0.15, 0.0)

Condicionais Claras

def faixa_etaria(idade: int) -> str:
    if idade < 0:
        raise ValueError("Idade inválida")
    if idade < 18:
        return "menor"
    if idade <= 65:
        return "adulto"
    return "idoso"

Loops com parada

def coletar_nomes():
    nomes = []
    while True:
        nome = input("Nome (ou 'sair'): ").strip()
        if nome.lower() == "sair":
            break
        if nome:
            nomes.append(nome)
    return nomes

Funções pequenas

def calcular_area_retangulo(larg: float, comp: float) -> float:
    return larg * comp

Parâmetros & retorno

def salario_liquido(bruto: float, descontos: float) -> float:
    return bruto - descontos

Evite efeitos colaterais

def dobrar_lista(nums: list[int]) -> list[int]:
    # retorna nova lista, não muta a original
    return [n*2 for n in nums]

Modularidade — Conceitos

  • Módulo: unidade autônoma com interface clara.
  • Coesão: uma responsabilidade por módulo.
  • Acoplamento: dependências mínimas.
  • Abstração/Encapsulamento: esconda detalhes, exponha o essencial.

Decomposição

  • Funcional (procedural)
  • Orientada a Objetos
  • Por camadas/domínios

Boas práticas

  • Módulos pequenos e coesos
  • Nomes e interfaces significativas
  • Testes unitários por módulo
  • Revisão de código

Módulos em Python

# modulo1.py
def saudacao(nome: str) -> None:
    print(f"Olá, {nome}!")

def soma(a: float, b: float) -> float:
    return a + b
# programa_principal.py
import modulo1
modulo1.saudacao("Mundo")
print(modulo1.soma(2, 3))

Pacotes

meu_app/
├─ __init__.py
├─ contas/
│  ├─ __init__.py
│  ├─ banco.py
│  └─ investimentos.py
└─ utils/
   ├─ __init__.py
   └─ datas.py
from meu_app.contas import banco, investimentos

__init__.py & __all__

# meu_app/__init__.py
__all__ = ["contas", "utils"]

Controla o que é exposto em from meu_app import * e pode conter código de inicialização do pacote.

Formas de importar

import modulo1
from modulo1 import saudacao, soma
import modulo1 as md1
# evitar na maioria dos casos:
# from modulo1 import *

Namespaces evitam conflitos. Prefira imports explícitos.

Built-in Modules (exemplos)

import math, random, os, sys, json, csv, re, datetime

print(math.sqrt(16))      # 4.0
print(random.randint(1,3))# 1..3
print(os.getcwd())        # diretório atual

Pacotes de Terceiros (PyPI)

# instalar
pip install numpy pandas requests

# requirements
pip freeze > requirements.txt
pip install -r requirements.txt
import pandas as pd
df = pd.DataFrame({"Nome":["Ana","Bob"], "Idade":[20,22]})
print(df)

Boas práticas

  • Leia a documentação
  • Use versões fixadas quando necessário
  • Ambientes virtuais por projeto

Ambientes Virtuais (venv / virtualenv)

Isolam dependências por projeto, evitam conflitos e facilitam a portabilidade.

Característicavenvvirtualenv
Padrão no PythonSim (3.3+)Não
FacilidadeIntegrado e simplesMais recursos
CompatibilidadePython 3.3+Versões antigas também

venv (recomendado)

cd meu_projeto
python -m venv .venv
# ativar
# Linux/macOS:
source .venv/bin/activate
# Windows:
# .venv\Scripts\activate
pip install -r requirements.txt
deactivate

requirements.txt

numpy==2.1.0
pandas==2.2.2
requests==2.32.0

Performance: ideias rápidas

  • Escolha estruturas adequadas (list, set, dict)
  • Evite I/O em loops apertados
  • Use algoritmos eficientes (ex.: sorted)
nums = [1,2,3,4,5]
soma = sum(nums)          # em vez de loop manual
ordenado = sorted(nums)   # Timsort otimizado

Perfil e medição

import time

t0 = time.perf_counter()
# ... código ...
dt = time.perf_counter() - t0
print(f"Tempo: {dt:.6f}s")

Mensure antes de otimizar. Use cProfile para perfis detalhados.

Checklist de Boas Práticas

  • PEP 8 e nomes descritivos
  • Docstrings e comentários úteis
  • Validação de entrada e exceções bem tratadas
  • Testes unitários e estrutura modular
  • Imports explícitos; use pacotes e ambientes virtuais
  • Documentação e exemplos executáveis

Conclusões

  • Boas práticas tornam seu código sustentável e evolutivo.
  • Modularidade reduz acoplamento e aumenta reutilização.
  • Ambientes virtuais e gestão de dependências são essenciais.

Comece simples, automatize checagens e evolua continuamente.