6.1 Decoradores para métodos de classe
Decoradores também podem ser usados para métodos de classes. É importante lembrar
que para métodos de classe é necessário passar os argumentos
self
ou cls
corretamente.
Nós ainda não vimos detalhes sobre classes, mas gostaria que você soubesse que essa possibilidade existe para decoradores.
def log_method_call(func):
def wrapper(self, *args, **kwargs):
print(f"Chamada do método {func.__name__}")
return func(self, *args, **kwargs)
return wrapper
class MyClass:
@log_method_call
def say_hello(self):
print("Hello from MyClass!")
obj = MyClass()
obj.say_hello()
Explicação
Decorador (log_method_call)
: Este decorador aceita o método
func
e retorna uma nova função wrapper
, que exibe uma mensagem antes
da chamada do método.
Método de classe com decorador (say_hello)
: O método say_hello
está envolvido pelo decorador log_method_call
, que adiciona comportamento extra
quando ele é chamado.
Saída:
Chamada do método say_hello
Hello from MyClass!
6.2 Vários decoradores
Você pode usar vários decoradores para uma única função, empilhando eles. Os decoradores são aplicados na ordem inversa à sua declaração.
def decorator1(func):
def wrapper():
print("Decorador 1")
func()
return wrapper
def decorator2(func):
def wrapper():
print("Decorador 2")
func()
return wrapper
@decorator1
@decorator2
def say_hello():
print("Hello!")
say_hello()
Explicação
Decoradores (decorator1 e decorator2)
: Esses decoradores
adicionam suas mensagens antes da chamada da função func
.
Função com decoradores (say_hello)
: A função say_hello
está envolvida por ambos os decoradores. Primeiro decorator2
é aplicado, em seguida
decorator1
.
Saída:
# Decorador 1
# Decorador 2
Hello!
6.3 Decoradores embutidos
Python fornece diversos decoradores embutidos para tarefas padrão, como métodos estáticos, métodos de classe e propriedades.
@staticmethod
O decorador @staticmethod
é usado para criar um método estático,
que não requer uma instância da classe para ser chamado.
class MyClass:
@staticmethod
def static_method():
print("Este é um método estático.")
MyClass.static_method()
@classmethod
O decorador @classmethod
é usado para criar um método de classe,
que aceita a classe (ao invés de uma instância) como o primeiro argumento.
class MyClass:
@classmethod
def class_method(cls):
print(f"Este é um método da classe {cls.__name__}.")
MyClass.class_method()
@property
O decorador @property
é usado para criar getters,
setters e deleters para atributos.
class MyClass:
def __init__(self, value):
self.hidden_value = value
@property
def value(self):
return self.hidden_value
@value.setter
def value(self, new_value):
self.hidden_value = new_value
obj = MyClass(10)
print(obj.value) # Saída: 10
obj.value = 20
print(obj.value) # Saída: 20
Estes são decoradores embutidos, seu funcionamento correto é garantido pelo próprio interpretador Python.
6.4 Exemplos de uso de decoradores
Log
Decoradores podem ser usados para registrar chamadas de funções e métodos.
def log_call(func):
def wrapper(*args, **kwargs):
print(f"Chamada da função {func.__name__} com argumentos {args} e {kwargs}")
return func(*args, **kwargs)
return wrapper
@log_call
def add(x, y):
return x + y
print(add(2, 3))
Controle de acesso
Decoradores podem ser usados para controlar o acesso a funções e métodos.
def require_authentication(func):
def wrapper(*args, **kwargs):
if not args[0].is_authenticated:
raise PermissionError("Usuário não autenticado.")
return func(*args, **kwargs)
return wrapper
class User:
def __init__(self, is_authenticated):
self.is_authenticated = is_authenticated
@require_authentication
def view_profile(self):
print("Perfil do usuário")
user = User(is_authenticated=True)
user.view_profile() # Chamada bem-sucedida
user2 = User(is_authenticated=False)
user2.view_profile() # PermissionError: Usuário não autenticado.
Cache
Decoradores podem ser usados para armazenar em cache os resultados de uma função.
def cache(func):
cached_results = {}
def wrapper(*args):
if args in cached_results:
return cached_results[args]
result = func(*args)
cached_results[args] = result
return result
return wrapper
@cache
def fib(n):
if n < 2:
return n
return fib(n - 1) + fib(n - 2)
print(fib(35))
GO TO FULL VERSION