Manufaturação industrial
Internet das coisas industrial | Materiais industriais | Manutenção e reparo de equipamentos | Programação industrial |
home  MfgRobots >> Manufaturação industrial >  >> Industrial programming >> python

Decoradores Python

Decoradores Python


Um decorador recebe uma função, adiciona alguma funcionalidade e a retorna. Neste tutorial, você aprenderá como criar um decorador e por que deve usá-lo.

Vídeo:@Decorators em Python

Decoradores em Python


Python tem um recurso interessante chamado decoradores para adicionar funcionalidade a um código existente.

Isso também é chamado de metaprogramação porque uma parte do programa tenta modificar outra parte do programa em tempo de compilação.

Pré-requisitos para aprender decoradores


Para entender sobre decoradores, devemos primeiro conhecer algumas coisas básicas em Python.

Devemos estar confortáveis ​​com o fato de que tudo em Python (Sim! Mesmo classes), são objetos. Os nomes que definimos são simplesmente identificadores vinculados a esses objetos. As funções não são exceções, elas também são objetos (com atributos). Vários nomes diferentes podem ser vinculados ao mesmo objeto de função.

Aqui está um exemplo.
def first(msg):
    print(msg)


first("Hello")

second = first
second("Hello")

Saída
Hello
Hello

Quando você executa o código, ambas as funções first e second dar a mesma saída. Aqui, os nomes first e second referem-se ao mesmo objeto de função.

Agora as coisas começam a ficar mais estranhas.

Funções podem ser passadas como argumentos para outra função.

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

Essas funções que recebem outras funções como argumentos também são chamadas de funções de ordem superior . Aqui está um exemplo de tal função.
def inc(x):
    return x + 1


def dec(x):
    return x - 1


def operate(func, x):
    result = func(x)
    return result

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()

# Outputs "Hello"
new()



Saída
Hello

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

Finalmente, devemos saber sobre Closures em Python.

Voltando aos Decoradores


Funções e métodos são chamados de chamáveis como podem ser chamados.

Na verdade, qualquer objeto que implemente o __call__() especial método é denominado callable. Então, no sentido mais básico, um decorador é um callable que retorna um callable.

Basicamente, um decorador recebe uma função, adiciona alguma funcionalidade e a retorna.
def make_pretty(func):
    def inner():
        print("I got decorated")
        func()
    return inner


def ordinary():
    print("I am ordinary")

Quando você executa os seguintes códigos no shell,
>>> ordinary()
I am ordinary

>>> # let's decorate this ordinary function
>>> pretty = make_pretty(ordinary)
>>> pretty()
I got decorated
I am ordinary

No exemplo mostrado acima, make_pretty() é um decorador. Na etapa de atribuição:
pretty = make_pretty(ordinary)

A função ordinary() foi decorado e a função retornada recebeu o nome pretty .

Podemos ver que a função decoradora adicionou algumas novas funcionalidades à função original. Isso é semelhante a embalar um presente. O decorador atua como um wrapper. A natureza do objeto que foi decorado (presente real dentro) não se altera. Mas agora, está bonito (já que foi decorado).

Geralmente, decoramos uma função e a reatribuímos como,
ordinary = make_pretty(ordinary).

Essa é uma construção comum e, por esse motivo, o Python possui uma sintaxe para simplificar isso.

Podemos usar o @ símbolo junto com o nome da função do decorador e coloque-o acima da definição da função a ser decorada. Por exemplo,
@make_pretty
def ordinary():
    print("I am ordinary")

é equivalente a
def ordinary():
    print("I am ordinary")
ordinary = make_pretty(ordinary)

Este é apenas um açúcar sintático para implementar decoradores.

Decorando funções com parâmetros


O decorador acima era simples e só funcionava com funções que não tinham nenhum parâmetro. E se tivéssemos funções que recebessem parâmetros como:
def divide(a, b):
    return a/b

Esta função tem dois parâmetros, a e b . Sabemos que dará um erro se passarmos b como 0.
>>> divide(2,5)
0.4
>>> divide(2,0)
Traceback (most recent call last):
...
ZeroDivisionError: division by zero

Agora vamos fazer um decorador para verificar este caso que causará o erro.
def smart_divide(func):
    def inner(a, b):
        print("I am going to divide", a, "and", b)
        if b == 0:
            print("Whoops! cannot divide")
            return

        return func(a, b)
    return inner


@smart_divide
def divide(a, b):
    print(a/b)

Esta nova implementação retornará None se a condição de erro ocorrer.
>>> divide(2,5)
I am going to divide 2 and 5
0.4

>>> divide(2,0)
I am going to divide 2 and 0
Whoops! cannot divide

Desta forma, podemos decorar funções que recebem parâmetros.

Um observador atento notará que os parâmetros do inner() aninhado função dentro do decorador é o mesmo que os parâmetros das funções que ele decora. Levando isso em consideração, agora podemos fazer decoradores gerais que funcionam com qualquer número de parâmetros.

Em Python, essa mágica é feita como function(*args, **kwargs) . Dessa forma, args será a tupla de argumentos posicionais e kwargs será o dicionário de argumentos de palavras-chave. Um exemplo de tal decorador será:
def works_for_all(func):
    def inner(*args, **kwargs):
        print("I can decorate any function")
        return func(*args, **kwargs)
    return inner

Encadeando Decoradores em Python


Vários decoradores podem ser encadeados em Python.

Ou seja, uma função pode ser decorada várias vezes com decoradores diferentes (ou iguais). Simplesmente colocamos os decoradores acima da função desejada.
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")

Saída
******************************
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Hello
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
******************************

A sintaxe acima de,
@star
@percent
def printer(msg):
    print(msg)

é equivalente a
def printer(msg):
    print(msg)
printer = star(percent(printer))

A ordem em que encadeamos os decoradores é importante. Se tivéssemos invertido a ordem como,
@percent
@star
def printer(msg):
    print(msg)

A saída seria:
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
******************************
Hello
******************************
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

python

  1. Tipos de dados Python
  2. Operadores Python
  3. Instrução de passagem do Python
  4. Argumentos da função Python
  5. Função anônima/Lambda do Python
  6. Funções do Python Lambda com EXEMPLOS
  7. Função Python abs():exemplos de valor absoluto
  8. Função Python round() com EXEMPLOS
  9. Função range() do Python:Float, List, For loop Exemplos
  10. Função Python map() com EXEMPLOS