Decoradores Python versus padrão de design de decorador: as principais diferenças
Compare os decoradores Python e o padrão de design clássico do decorador. Entenda as diferenças entre o agrupamento de funções em tempo de definição e a composição dinâmica de objetos em tempo de execução com código executável.
Embora os decoradores Python e o padrão de design do decorador compartilhem o mesmo nome e o conceito geral de "embrulhar" o código para estender o comportamento, eles representam construções e filosofias de programação completamente diferentes.
Um decorador Python é um recurso de linguagem – açúcar sintático que permite agrupar uma função, método ou classe no momento da definição. É uma forma de metaprogramação que é executada quando o módulo é importado ou definido, alterando o comportamento dessa função durante o restante da execução da aplicação.
O Decorator Design Pattern, originalmente definido pelo Gang of Four (GoF), é um padrão de design estrutural orientado a objetos. Ele foi projetado para adicionar responsabilidades a objetos individuais dinamicamente em tempo de execução, sem afetar outros objetos da mesma classe, usando classes wrapper e composição dinâmica.
Matriz de comparação de recursos
| Feature | Python | Other Language |
|---|---|---|
| Conceito Central | Açúcar sintático no nível da linguagem para agrupar funções/classes. | Padrão de design para adicionar comportamento dinamicamente a objetos individuais. |
| Tempo de execução | Tempo de definição (é executado uma vez quando o módulo é carregado). | Tempo de execução (instanciado dinamicamente durante a execução do programa). |
| Entidade Alvo | Funções, métodos ou classes inteiras (escopo estático). | Instâncias específicas de objetos (escopo dinâmico). |
| Método de implementação | Closures e funções auxiliares usando a sintaxe `@decorator`. | Herança de classe, alinhamento de interface e composição de objetos. |
Syntax & Idiom Comparisons
01.Decorador Python: Wrapper de Função (Tempo de Definição)
Os decoradores Python aproveitam funções de primeira classe para interceptar chamadas. Quando você escreve `@my_decorator`, Python passa a função decorada para sua função decoradora e vincula a função wrapper retornada ao nome da função original.
Neste exemplo, o decorador `@log_call` envolve uma função simples para rastrear quando ela é executada e o que retorna. Observe que esse envolvimento é definitivo no momento em que a função é definida.
def log_call(func):
def wrapper(*args, **kwargs):
print(f"[LOG] Executing '{func.__name__}' with args {args}")
result = func(*args, **kwargs)
print(f"[LOG] '{func.__name__}' returned: {result}")
return result
return wrapper
@log_call
def add(a, b):
return a + b
# The wrapping occurs once at definition time
print("Result of add(5, 7):", add(5, 7))// Decorators in Python are syntactic sugar for function wrappers:
// add = log_call(add)
// They exist primarily to avoid duplicate boilerplate for logging, timing, and auth.02.Padrão de design do decorador: Object Wrapper (composição de tempo de execução)
O clássico Decorator Design Pattern usa composição de classes. Você tem uma classe de componente base e classes de decorador que envolvem esse componente base. No tempo de execução, você encadeia esses construtores para construir um objeto personalizado dinamicamente.
Aqui, implementamos um sistema clássico de decoração de café. Podemos agrupar um objeto Coffee básico dentro de um MilkDecorator e envolvê-lo dentro de um SugarDecorator, calculando o custo final dinamicamente em tempo de execução.
class Coffee:
def get_cost(self):
return 5.0
def get_description(self):
return "Simple Coffee"
class MilkDecorator:
def __init__(self, coffee):
self.coffee = coffee
def get_cost(self):
return self.coffee.get_cost() + 1.5
def get_description(self):
return self.coffee.get_description() + ", Milk"
class SugarDecorator:
def __init__(self, coffee):
self.coffee = coffee
def get_cost(self):
return self.coffee.get_cost() + 0.5
def get_description(self):
return self.coffee.get_description() + ", Sugar"
# Chaining wrappers dynamically at runtime
my_drink = Coffee()
my_drink = MilkDecorator(my_drink)
my_drink = SugarDecorator(my_drink)
print("Drink description:", my_drink.get_description())
print("Total Cost: $", my_drink.get_cost())// Standard OO languages (like Java) require shared interfaces:
// interface Coffee { double getCost(); }
// class SimpleCoffee implements Coffee { ... }
// class MilkDecorator implements Coffee { ... }
// Python's duck typing allows dynamic composition without interfaces.Veredicto e Resumo
Use decoradores Python (@decorator) quando quiser aplicar preocupações transversais (como registro, tempo, autenticação, cache ou validação de entrada) a funções ou rotas uniformemente em seu aplicativo.
Use o Decorator Design Pattern quando precisar anexar ou desanexar comportamentos de instâncias de objetos individuais dinamicamente em tempo de execução, especialmente ao combinar várias classes wrapper opcionais em sequências arbitrárias.
Perguntas frequentes
Por que a página da Wikipedia diz que os decoradores Python não são o padrão do decorador?
Porque os decoradores Python padrão envolvem funções e definições de classe em tempo de compilação/definição, afetando todas as instâncias dessa função. O padrão de design clássico envolve instâncias de objetos individuais dinamicamente em tempo de execução.
O padrão GoF Decorator é útil em Python?
Sim, mas a digitação duck do Python torna sua implementação muito mais simples do que em linguagens de tipo estaticamente como Java ou C++, uma vez que os decoradores não precisam herdar de uma interface base formal.
Outras comparações
Recursos Python recomendados
Expanda seu conhecimento com tutoriais interativos relacionados, folhas de dicas e comparações de código.
Decoradores Python
Aprenda decoradores Python para modificar o comportamento da função dinamicamente. Entenda as funções do wrapper, a sintaxe @ e o tratamento de argumentos em decoradores.
Como criar e usar decoradores em Python
Aprenda como escrever e aplicar decoradores em Python. Domine funções de encapsulamento, modificando comportamento, manipulando argumentos e preservando metadados com encapsulamentos.
Folha de referências dos padrões Python Regex (remódulo)
Guia de referência para expressões regulares Python. Aprenda padrões de correspondência, pesquisa, findall, sub e regex essenciais.