Python decorator example application and examples - learning version

417405201afcc160581aa9636951c076.png

Example 1: Plain decorator

def name(n):
    def func(x):
        res = n(x+x)
        return res
    return func

@name
def run(x):     # run = name(run)
    print(x)

if __name__ == '__main__':
    run(1)
# 2
def name(n):
    def func(*x):
        res = n(x+x)
        return res
    return func

@name
def run(x):     # run = name(run)
    print(x)

if __name__ == '__main__':
    run(1)
# (1, 1)

For the comparison between the above two, pay attention to the parameter passing. One is an ordinary value pass, and the other is the addition of two tuples.

Example 2: Common decorator pass value

def name(n):
    def func(x, y):
        res = n(x,y)
        return res
    return func

@name
def run(x, y):  # run = name(run)
    print(x, y)

if __name__ == '__main__':
    run(1, 2)
# 1 2

Just imagine, how to achieve 1+2, in the run function or in the name function

def name(n):
    def func(x, y):
        res = n(x,y)
        return res
    return func

@name
def run(x, y):  # run = name(run)
    print(x + y)

if __name__ == '__main__':
    run(1, 2)

Implemented in the run function, the name function is similar to the call operation, and can also be implemented in the name function

def name(n):
    def func(x, y):
        res = n(x,y)
        print(x + y)
        return res
    return func

@name
def run(x, y):  # run = name(run)
    # print(x + y)
    pass

if __name__ == '__main__':
    run(1, 2)

Example 3 - Advanced: Logging

import logging

def name(n):
    def func(x, y):
        res = n(x,y)
        logging.basicConfig(format='%(asctime)s  %(name)s  %(levelno)s %(filename)s '
                                   '%(lineno)d    %(message)s', level=logging.DEBUG)
        logging.info("执行了{},{},结果是{}".format(x,y,res))
        return res
    return func

@name
def run(x, y):  # run = name(run)
    return x+y

if __name__ == '__main__':
    run(1, 2)
# 2023-03-01 12:24:10,474  root  20 ceshi_test.py 10    执行了1,2,结果是3

The result here does not seem to specify a function, and the impact is not great. You can look at the logging module, or you can add it yourself.

import logging

def name(n):
    def func(x, y):
        res = n(x,y)
        logging.basicConfig(format='%(asctime)s  %(name)s  %(levelno)s %(filename)s '
                                   '%(lineno)d  %(funcName)s %(message)s', level=logging.DEBUG)
        logging.info("执行了{},{},{},结果是{}".format(n.__name__,x,y,res))
        return res
    return func

@name
def run(x, y):  # run = name(run)
    return x+y

if __name__ == '__main__':
    run(1, 2)
# 2023-03-01 12:35:15,283  root  20 ceshi_test.py 9  func 执行了run,1,2,结果是3

It can be seen that the obtained running functions are actually different. For accurate access, handwriting is recommended

Example 4 - Advanced: Time Timer

import time
def timer(clock):
    def func(*args,**kwargs):
        start = time.time()
        res = clock(*args,**kwargs)
        print("耗时 {} S".format(time.time() - start))
        return res
    return func

@timer
def run(x, y): 
    time.sleep(1)
    print(x + y)

if __name__ == '__main__':
    run(1, 2)
# 3
# 耗时 1.0103626251220703 S

The above is simply used to calculate the running time of the program without any operation.

Example 5 - Advanced - with parameters

def outwapper(out):
    def country(cont):
        def inwapper(*args,**kwargs):
            if out == '中国':
                print("你好啊,兄弟")
            else:
                print("你是哪个国家的")
            cont(*args,**kwargs)
        return inwapper
    return country

@outwapper("中国")
def people():
    pass

if __name__ == '__main__':
    people()

Does it look like a lot of trouble, but it actually takes a long time to look at it carefully. Pass a parameter, the returned value still has to be returned.

def outwapper(out):
    def country(cont):
        def inwapper(*args,**kwargs):
            if out == '中国':
                print("你好啊,兄弟")
            else:
                print("你是哪个国家的")
            cont(*args,**kwargs)
        return inwapper
    return country

@outwapper("中国")
@outwapper("俄罗斯")
def people():
    pass

if __name__ == '__main__':
    people()
# 你好啊,兄弟
# 你是哪个国家的

Multiple decorators can be applied to the same function and can be reused.

Example 6 - Higher Order - Class Decorator

class Time(object):
    def __init__(self, func):
        self.func = func

    def __call__(self, *args, **kwargs):
        print(args,kwargs)

@Time
def name():
    pass

if __name__ == '__main__':
    name()

Just apply the format, and the parameters in __init__ are necessary because the function needs to be passed.

class Time(object):
    def __init__(self, func):
        self.func = func

    def __call__(self, *args, **kwargs):
        print(args,kwargs)

@Time
def name(x,y):
    pass

if __name__ == '__main__':
    name('清安',age=18)
# ('清安',) {'age': 18}

Obviously, __call__ is used to receive and process values.

pass parameters

class Time(object):
    def __init__(self, func):
        self.func = func

    def __call__(self, evt):
        def wapper(*args, **kwargs):
            print(self.func, args, kwargs)
        return wapper

@Time("中国")
def name(x, y):
    pass

if __name__ == '__main__':
    name('清安', age=18)
# 中国 ('清安',) {'age': 18}

What is evt?

class Time(object):
    def __init__(self, func):
        self.func = func

    def __call__(self, evt):
        def wapper(*args, **kwargs):
            print(evt.__name__, args, kwargs)
        return wapper

@Time("中国")
def name(x, y):
    print(x,y)

if __name__ == '__main__':
    name('清安', age=18)
# name ('清安',) {'age': 18}

It is the function address of the name function, how to use the evt parameter?

class Time(object):
    def __init__(self, func):
        self.func = func

    def __call__(self, evt):
        def wapper(*args, **kwargs):
            evt(args,kwargs)
            # print(evt.__name__, args, kwargs)
        return wapper

@Time("中国")
def name(x, y):
    print(x,y)

if __name__ == '__main__':
    name('清安', age=18)

It's that simple.

Example 7 - Higher Order - Decorator for Decorator Classes

def func(cls):
    def inwapper(*args,**kwargs):
        print(cls.__name__)
        print(args)
    return inwapper

@func
class User:
    def __init__(self,name):
        self.name = name

if __name__ == '__main__':
    User("清an")
# User
# ('清an',)

Functions in classes use decorators

def func(cls):
    def inwapper(x, *args, **kwargs):
        logging.basicConfig(format='%(asctime)s  %(name)s  %(levelno)s %(filename)s '
                                   '%(lineno)d  %(funcName)s %(message)s', level=logging.DEBUG)
        logging.info("执行了{},结果是{},{},{}".format(cls.__name__,x, args, kwargs))

    return inwapper

# @func
class User:
    @func
    def name(self, name, name1, age):
        # return name, name1, age
        pass
if __name__ == '__main__':
    u = User()
    u.name("清安","ANAN",age=18)
2023-03-01 18:36:36,310  root  20 ceshi_test.py 74  inwapper 执行了name,结果是<__main__.User object at 0x0000020A11DABE50>,('清安', 'ANAN'),{'age': 18}

Why there is an x, because self will be passed as a parameter, and the memory address will be passed directly together, either the subscript value or another parameter to receive this self. Either self is not used in the class

Since self is used, can it be used to call properties in decorators? The answer is of course.

def func(cls):
    def inwapper(x, *args, **kwargs):
        logging.basicConfig(format='%(asctime)s  %(name)s  %(levelno)s %(filename)s '
                                   '%(lineno)d  %(funcName)s %(message)s', level=logging.DEBUG)
        x.info = 1
        logging.info("执行了{},结果是{},{},{}".format(cls.__name__,x, args, kwargs))

    return inwapper


class User:
    info = None
    
    @func
    def name(self, name, name1, age):
        # return name, name1, age
        pass
if __name__ == '__main__':
    u = User()
    u.name("清安","ANAN",age=18)
    print(u.info)
# 1
# 2023-03-02 09:15:36,640  root  20 ceshi_test.py 75  inwapper 执行了name,结果是<__main__.User object at 0x0000021B20A2F5B0>,('清安', 'ANAN'),{'age': 18}

Obviously, the assignment was successful. Let's look at assigning values ​​​​to other functions.

def func(cls):
    def inwapper(x, *args, **kwargs):
        logging.basicConfig(format='%(asctime)s  %(name)s  %(levelno)s %(filename)s '
                                   '%(lineno)d  %(funcName)s %(message)s', level=logging.DEBUG)
        x.Info("QA",18)
        logging.info("执行了{},结果是{},{},{}".format(cls.__name__,x, args, kwargs))

    return inwapper

class User:
    info = None

    @func
    def name(self, name, name1, age):
        # return name, name1, age
        pass

    def Info(self,name,age):
        print("我是{},今年{}".format(name,age))

if __name__ == '__main__':
    u = User()
    u.name("清安","ANAN",age=18)
# 2023-03-02 09:19:26,910  root  20 ceshi_test.py 75  inwapper 执行了name,结果是<__main__.User object at 0x00000232FF01F5B0>,('清安', 'ANAN'),{'age': 18}
# 我是QA,今年18

Example 8 - Masquerade

from functools import wraps

def timer(value):
    def func(fun):
        # @wraps(fun)
        def inner(*args,**kwargs):
            res = fun()
            print(value)
            print(inner.__name__)
            return res
        return inner
    return func

@timer("QA")
def run():
    pass

if __name__ == '__main__':
    run()

Disguise the decorator so that the decorator function name points to the running function name.

In addition, there are some usages, which will not be elaborated here. After learning the above examples, can you write a decent decorator yourself?

Guess you like

Origin blog.csdn.net/weixin_52040868/article/details/129373975