0Pricing
Python Academy · Aula

Escrita de decoradores personalizados

Crie decoradores usando funções wrapper e functools.wraps.

Escrita de decoradores personalizados é uma aula grátis de Python Academy no CoddyKit. Esta é a aula 2 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Python Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Python Academy inclui 4 aulas no total.

Introdução

Decoradores são funções que envolvem outras funções, adicionando comportamento antes ou depois sem modificar a original.

O que é um decorador?

@decorator acima de uma função é um açúcar sintático para: func = decorator(func). O decorador recebe a função e retorna um wrapper.
def shout(func):
    def wrapper(*a, **kw):
        result = func(*a, **kw)
        return str(result).upper()
    return wrapper
@shout
def greet(name): return f'hello {name}'
print(greet('Alice'))

O padrão wrapper

A função wrapper tem a mesma assinatura da original. Ela chama a original internamente e adiciona comportamento ao redor dela.
def timer(func):
    import time
    def wrapper(*args, **kwargs):
        start = time.time()
        result = func(*args, **kwargs)
        print(f'{func.__name__} took {time.time()-start:.4f}s')
        return result
    return wrapper
@timer
def slow(): import time; time.sleep(0.01)
slow()

functools.wraps

@wraps(func) no wrapper preserva __name__, __doc__ e __annotations__ da função original.
from functools import wraps
def log(func):
    @wraps(func)
    def wrapper(*a, **kw):
        print(f'calling {func.__name__}')
        return func(*a, **kw)
    return wrapper
@log
def add(a, b): return a + b
print(add.__name__)
add(1, 2)

Decorador com argumentos

Um decorador com argumentos precisa de mais um nível de envolvimento: uma função-fábrica que recebe os argumentos e retorna o decorador.
def repeat(n):
    def decorator(func):
        from functools import wraps
        @wraps(func)
        def wrapper(*a, **kw):
            for _ in range(n): func(*a, **kw)
        return wrapper
    return decorator
@repeat(3)
def hi(): print('hi')
hi()

Encadeando decoradores

Vários decoradores são empilhados de baixo para cima: @d2 @d1 significa func = d2(d1(func)). O mais externo (no topo) é executado por último.
def bold(f):
    from functools import wraps
    @wraps(f)
    def w(*a,**k): return '<b>' + f(*a,**k) + '</b>'
    return w
def italic(f):
    from functools import wraps
    @wraps(f)
    def w(*a,**k): return '<i>' + f(*a,**k) + '</i>'
    return w
@bold
@italic
def text(): return 'hello'
print(text())

Decorador baseado em classe

Uma classe com __call__ pode ser um decorador. Ela mantém o estado entre as chamadas.
class Counter:
    def __init__(self, func): self.func,self.count=func,0
    def __call__(self, *a, **kw):
        self.count+=1
        return self.func(*a, **kw)
@Counter
def greet(name): return f'hi {name}'
greet('Alice'); greet('Bob')
print(greet.count)

Decorador de memorização

Armazene os resultados anteriores em cache para evitar recalculá-los: if args in cache: return cache[args]. functools.lru_cache faz isso de forma integrada.
from functools import lru_cache
@lru_cache(maxsize=None)
def fib(n):
    if n < 2: return n
    return fib(n-1) + fib(n-2)
print(fib(30))

Decorador de autorização

Decoradores são comuns no controle de acesso: verifique se o usuário está conectado antes de executar a função.
def requires_auth(func):
    from functools import wraps
    @wraps(func)
    def wrapper(user, *a, **kw):
        if not user.get('authenticated'):
            raise PermissionError('Not authenticated')
        return func(user, *a, **kw)
    return wrapper
@requires_auth
def dashboard(user): return 'Welcome!'
try: dashboard({'authenticated': False})
except PermissionError as e: print(e)

Decorador de repetição

Envolva uma função para repeti-la em caso de falha: for _ in range(retries): try: return func() except Exception: pass
import random
from functools import wraps
def retry(times=3):
    def dec(func):
        @wraps(func)
        def wrapper(*a, **kw):
            for i in range(times):
                try: return func(*a, **kw)
                except Exception as e:
                    if i==times-1: raise
        return wrapper
    return dec
@retry(3)
def flaky():
    if random.random()<0.7: raise ValueError
    return 'ok'
try: print(flaky())
except ValueError: print('failed')

Práticas recomendadas para decoradores

Sempre use @functools.wraps. Mantenha os decoradores com uma única finalidade. Documente o que eles adicionam. Teste o decorador separadamente da função decorada.
from functools import wraps
def validate_positive(func):
    @wraps(func)
    def wrapper(x, *a, **kw):
        if x <= 0: raise ValueError(f'{x} must be positive')
        return func(x, *a, **kw)
    return wrapper
@validate_positive
def sqrt(x): return x**0.5
print(sqrt(9))

Verificação rápida

O que @functools.wraps(func) faz quando é aplicado a um wrapper?

Recapitulação

Decoradores: func = decorator(func). Use wrapper(*args, **kwargs). @wraps preserva os metadados. Decoradores parametrizados adicionam mais um nível. Empilhe-os com vários @decorators.

Continue

Excelente progresso! Continue para dominar o próximo conceito.

Perguntas Frequentes

A aula “Escrita de decoradores personalizados” é grátis?

Sim — o texto completo de “Escrita de decoradores personalizados” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Python Academy, atualize para CoddyKit PRO. O curso de Python Academy inclui 4 aulas no total.

O que vou aprender em “Escrita de decoradores personalizados”?

Crie decoradores usando funções wrapper e functools.wraps. Você pratica Python Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.

Preciso ter experiência prévia para começar Python Academy?

Nenhuma experiência prévia é necessária. Python Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 2 de 4.

Quanto tempo leva a aula “Escrita de decoradores personalizados”?

A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.

Posso escrever e executar código nesta aula de Python Academy?

Sim. Cada aula de Python Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.

Todas as aulas deste curso

  1. Funções como objetos de primeira classe
  2. Escrita de decoradores personalizados
  3. O decorador @property
  4. @classmethod e @staticmethod
← Voltar para Python Academy