Home  >  Article  >  Backend Development  >  What are decorators in Python? Introduction to decorators in Python

What are decorators in Python? Introduction to decorators in Python

不言
不言Original
2018-09-13 16:50:242859browse

This article brings you what is a decorator in Python? The introduction of decorators in Python has certain reference value. Friends in need can refer to it. I hope it will be helpful to you.

1. What is a decorator?

A decorator, decorator, is essentially a Python function that allows other functions to function without any code changes. To add additional functionality, the return value of the decorator is also a function object.

Decorators enhance the functionality of the core code part without modifying the core code. For example, insert logs, permission verification, transaction processing and other scenarios before functions.
And you can extract a large amount of similar code that has nothing to do with function functions and reuse it.

2. Early implementation: Decorators that are not decorators

  • A function in Python can also be regarded as an object and can be assigned to a variable , and call the function through the variable.

For example:

def foo():
   print("2017-06-08")
f = foo    # 将函数赋值给变量,f为函数对象
f()
# 返回结果:
2017-06-08

3. Syntactic sugar@ Implement a simple decorator

Suppose now you want to enhance foo() Functionality, for example, printing logs before function calls. But I don't want to modify the definition of the foo() function. This way of dynamically adding functionality while the code is running is called a "decorator".
is as follows:

def testfunc(func):
    print('testfunc')
    def wrapper():
        print("%s %s() called" %(time.ctime(),func.__name__))
        return func()
    return wrapper
@testfunc 
def foo():
    print('foo1()')

foo()  # 相当于执行testfunc(foo) ->wrapper(foo) -> foo()

Execution result:

testfunc
Wed Sep 12 15:01:13 2018 foo() called
foo1()

Description: Before executing foo(), first execute testfunc(foo), and then Execute wrapper(), calling foo() itself on return.

4. Decorators that receive specific types of parameters

  • The decorator can receive parameters. When the function returned by the decorator is called, that is The wrapping function is called, passing the parameters into the wrapping function, which passes the parameters to the decorated function.

is as follows:

def testfunc_with_args(func):
    def wrapper_argus(arg1, arg2):
        print("I got args! Look:", arg1, arg2)
        func(arg1, arg2)
    return wrapper_argus
@testfunc_with_args
def full_name(first_name, last_name):  # 带参数,将参数传给被装饰的函数
    print("My name is", first_name, last_name)

full_name("Peter", "Venkman")  # 调用

Execution result:

I got args! Look: Peter Venkman
My name is Peter Venkman

5. Decorator with indefinite parameters

When there are multiple functions that need to call the decorator, but the parameters of the functions are different, how to implement it? There can't be one function corresponding to one decorator. At this time, it can be implemented using a decorator with variable parameters.
is as follows:

def log(func):
    def wrapper(*args,**kwargs):        # 可接受各种参数
        print('call %s():'% func.__name__)
        return func(*args,**kwargs)     # 返回一个函数
    return wrapper                      # 装饰器返回一个函数,进入到wrapper()

@log      # @log放到now()的定义处,相当于执行语句:now = log(now)
def now_1(a,b):
    print('now()1:a+b = ',a+b)
@log
def now_2(a,b,c):
    print('now_2():a+b+c = ',a+b+c)

now_1(1,2)
now_2(1,2,3)

Run it~

6. Multiple decorators

When a function wants to add multiple functions , you can consider using multi-layer decorators, but you need to pay attention to the execution order of the decorators.
Give a chestnut:

# 注意代码的执行顺序
def deco_1(func):
    print('------111111------')
    def wrapper(*args,**kwargs):    # 包裹函数,参数与原函数的参数一致
        print('start: this is deco_1.')
        func(*args,**kwargs)
        print('end: deco_1.')
    return wrapper  # 返回值是一个包裹函数
def deco_2(func):
    print('------222222------')
    def wrapper(*args,**kwargs):
        print('start: this is deco_2.')
        func(*args,**kwargs)
        print('end: deco_2.')
    return wrapper

@deco_1
@deco_2
def now_1(a,b):
    print('now()1:a+b = ',a+b)

now_1(1,2)

Running results:

# 结果,注意执行顺序:
------222222------
------111111------
start: this is deco_1.
start: this is deco_2.
now()1:a+b =  3
end: deco_2.
end: deco_1.

7. The decorator itself takes parameters

In addition to bringing parameters to the decorated function Parameters, the decorator itself can also take parameters.

def logging(level):
    def wrapper(func):
        def inner_wrapper(*args, **kwargs):
            print("[{level}]: enter function {func}()".format(level=level, func=func.__name__))
            return func(*args, **kwargs)
        return inner_wrapper
    return wrapper
    
@logging(level='INFO')
def say(something):
    print("say {}!".format(something))

@logging(level='DEBUG')
def do(something):
    print("do {}...".format(something))

say('hello')
do("my work")

Execution result:

# 执行结果:
[INFO]: enter function say()
say hello!
[DEBUG]: enter function do()
do my work...

Related recommendations:

Detailed explanation of decorators in python

Detailed explanation of various decorators in Python

The above is the detailed content of What are decorators in Python? Introduction to decorators in Python. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn