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