English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Tutorial Básico do Python

Controle de Fluxo do Python

Função no Python

Tipos de Dados no Python

Operações de Arquivos do Python

Objetos e Classes do Python

Data e Hora do Python

Conhecimento Avançado do Python

Manual de Referência do Python

Decorator no Python

O decorador aceita uma função, adiciona algumas funcionalidades e retorna-a. Neste artigo, você aprenderá como criar um decorador e por que usar ele.

O que são decoradores em Python?

Python tem uma funcionalidade interessante chamadaDecoradores, pode adicionar funcionalidades ao código existente.

Também chamado deMeta-programaçãoPorque parte do programa tenta modificar outra parte do programa no tempo de compilação.

Prerequisitos para aprender decoradores

Para entender os decoradores,我们必须 primeiro entender algumas noções básicas do Python.

Devemos aceitar o fato de que tudo em Python éObjeto. Os nomes que definimos são apenas identificadores ligados a esses objetos.FunçãoTambém não excepcional, elas são objetos (com atributos). Você pode ligar nomes diferentes ao mesmo objeto funcional.

Este é um exemplo.

def first(msg):
    print(msg)    
first("Hello")
second = first
second("Hello")

Quando você executar o código, essas duas funções first e second fornecem a mesma saída. Aqui, os nomes first e second se referem ao mesmo objeto funcional.

Agora, a situação não parece um pouco mais complexa, você pode passar funções como parâmetros para outras funções.

Se você já usou funções como map, filter e reduce em Python, então você já sabe isso.

Essas funções que aceitam outras funções como parâmetros também são chamadas deFunções de ordem superior. Isso é um exemplo desse tipo de função.

def inc(x):
    return x + 1
def dec(x):
    return x - 1
def operate(func, x):
    result = func(x)
    return result

Nós chamamos a função da seguinte forma.

>>> operate(inc,3)
4
>>> operate(dec,3)
2

Além disso, uma função pode retornar outra função.

def is_called():
    def is_returned():
        print("Hello")
    return is_returned
new = is_called()
# Saída "Hello"
new()

Aqui, is_returned() é uma função aninhada que é definida e retornada toda vez que chamamos is_drawn().

Por fim, devemos entenderEncerramento em Python.

Voltando aos decoradores

Funções e métodos são chamados deCallable,Porque podem ser chamados.

Na verdade, qualquer objeto que implemente o método especial __call__() é chamado de callable. Portanto, no sentido mais básico, os decoradores são chamáveis e podem retornar chamáveis.

Basicamente, os decoradores aceitam uma função, adicionam algumas funcionalidades e retornam-a.

def make_pretty(func):
    def inner():
        print("Fui decorado")
        func()
    return inner
def ordinary():
    print("Sou uma função comum")

Quando rodarmos o seguinte código no shell:

>>> ordinary()
Sou uma função comum
>>> # Vamos decorar essa função comum
>>> pretty = make_pretty(ordinary)
>>> pretty()
Fui decorado
Sou uma função comum

No exemplo mostrado acima, make_pretty() é um decorador. No passo de atribuição.

pretty = make_pretty(ordinary)

A função ordinary() foi decorada, e a função retornada foi nomeada pretty.

Podemos ver que o decorador adiciona algumas novas funcionalidades ao função original. Isso é semelhante a embalar um presente. O decorador atua como a embalagem. A natureza do item decorado (o presente dentro) não muda. Mas agora, parece bonito (desde que foi decorado).

Normalmente, decoramos uma função e a reatribuímos como

ordinary = make_pretty(ordinary).

Isso é uma construção comum, então o Python tem uma sintaxe simplificada para isso.

Podemos usar o símbolo @ junto com o nome do decorador e colocá-lo na definição da função a ser decorada. Por exemplo:

@make_pretty
def ordinary():
    print("Sou uma função comum")

is equivalent to

def ordinary():
    print("Sou uma função comum")
ordinary = make_pretty(ordinary)

Isso é apenas um açúcar sintático para a implementação do decorador.

Decorar função com parâmetros

O decorador acima é simples e se aplica apenas a funções sem parâmetros. E se nossa função tiver os seguintes parâmetros?

def divide(a, b):
    return a/b

Essa função tem dois parâmetros:aandbNós sabemos, se我们将bSe passar zero, ocorrerá erro.

>>> divide(2,5)
0.4
>>> divide(2,0)
Traceback (última chamada mais recente):
...
ZeroDivisionError: divisão por zero

Agora vamos fazer um decorador para verificar se isso causará erro.

def smart_divide(func):
   def inner(a,b):
      print("Vou fazer divisão", a, "e", b)
      if b == 0:
         print("Aiya! Nao pode dividir")
         return
      return func(a,b)
   return inner
@smart_divide
def divide(a,b):
    return a/b

If an error occurs, this new implementation will return None.

>>> divide(2,5)
I want to do division 2 and 5
0.4
>>> divide(2,0)
I want to do division 2 and 0
Oh no! Cannot divide

In this way, we can decorate functions with parameters.

A keen observer will notice that the parameters of the nested function inside the inner() decorator are the same as those of the function it decorates. Considering this, now we can make the universal decorator usable with any number of parameters.

In Python, this magic is achieved by the completed function(*args, **kwargs). In this way, args is the positional argumentstuplewhere kwargs is instead of keyword argumentsdictionary. An example of such a decorator is.

def works_for_all(func):
    def inner(*args, **kwargs):
        I can decorate any function
        return func(*args, **kwargs)
    return inner

Python linked decorators

Multiple decorators can be linked in Python.

This means that a function can be decorated multiple times (or the same) with different decorators. We just need to place the decorators above the required function.

def star(func):
    def inner(*args, **kwargs):
        print(""*" * 30)
        func(*args, **kwargs)
        print(""*" * 30)
    return inner
def percent(func):
    def inner(*args, **kwargs):
        print("%%") * 30)
        func(*args, **kwargs)
        print("%%") * 30)
    return inner
@star
@percent
def printer(msg):
    print(msg)
printer("Hello")

This will give the output.

******************************
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Hello
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
******************************

the above syntax,

@star
@percent
def printer(msg):
    print(msg)

is equivalent to

def printer(msg):
    print(msg)
printer = star(percent(printer))

The order of the link decorators is important. If we reverse the order,

@percent
@star
def printer(msg):
    print(msg)

The execution will occur

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
******************************
Hello
******************************
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%