秋招--1、装饰器

寻技术 Python编程 2024年01月04日 79

一、装饰器

参考:https://zhuanlan.zhihu.com/p/87353829
https://blog.csdn.net/zhh763984017/article/details/120072425
将函数作为对象

闭包概念

def outer(x):
  def inner(y):
    return x+y
  return inner        # 返回一个函数对象

装饰器就是一个闭包,是在原有函数功能上的一个拓展

1、无参数的装饰器:
def cost_time(func):
  def inner():
    print(f'start time{time.time()}')
    func()
  return inner

@ cost_time
def time_sleep():
  time.sleep(5)  # 在函数中加入新的功能实现
2、装饰器传参:

被装饰的函数带有参数

def cost_time(func):
  def inner(*args, **kwargs):
    print(time.time())
    func(*args, **kwargs)

@cost_time
def time_sleep(name):
  print(f'进程名字:{name}')
  time.sleep(5)
3、带参数的装饰器

装饰器函数带有参数,在@的时候需要传入一些必要的参数

import time
 
 
def count_time_args(msg=None):   # 需要多加一层函数,引入传参
    def count_time(func):
        def wrapper(*args, **kwargs):
            t1 = time.time()
            func(*args, **kwargs)
            print(f"[{msg}]执行时间为:", time.time() - t1)
 
        return wrapper
 
    return count_time
 
 
@count_time_args(msg="baiyu")
def fun_one():
    time.sleep(1)
 
 
@count_time_args(msg="zhh")
def fun_two():
    time.sleep(1)
 
 
@count_time_args(msg="mylove")
def fun_three():
    time.sleep(1)
 
 
if __name__ == '__main__':
    fun_one()
    fun_two()
    fun_three()

二、类装饰器

当我们将类作为一个装饰器,工作流程:
通过__init__()方法初始化类
通过__call__()方法调用真正的装饰方法

1、不带参数的类装饰器
import time
 
 
class BaiyuDecorator:
    def __init__(self, func):
        self.func = func
        print("执行类的__init__方法")
 
    def __call__(self, *args, **kwargs):
        print('进入__call__函数')
        t1 = time.time()
        self.func(*args, **kwargs)
        print("执行时间为:", time.time() - t1)
 
 
@BaiyuDecorator
def baiyu():
    print("我是攻城狮白玉")
    time.sleep(2)
 
 
def python_blog_list():
    time.sleep(5)
    print('''【Python】爬虫实战,零基础初试爬虫下载图片(附源码和分析过程)
    https://blog.csdn.net/zhh763984017/article/details/119063252 ''')
    print('''【Python】除了多线程和多进程,你还要会协程
    https://blog.csdn.net/zhh763984017/article/details/118958668 ''')
    print('''【Python】爬虫提速小技巧,多线程与多进程(附源码示例)
    https://blog.csdn.net/zhh763984017/article/details/118773313 ''')
    print('''【Python】爬虫解析利器Xpath,由浅入深快速掌握(附源码例子)
    https://blog.csdn.net/zhh763984017/article/details/118634945 ''')
 
 
@BaiyuDecorator
def blog(name):
    print('进入blog函数')
    name()
    print('我的博客是 https://blog.csdn.net/zhh763984017')
 
 
if __name__ == '__main__':
    baiyu()
    print('--------------')
    blog(python_blog_list)
2、带参数的装饰器:

当装饰器有参数的时候,init() 函数就不能传入func(func代表要装饰的函数)了,而func是在__call__函数调用的时候传入的。

class BaiyuDecorator:
    def __init__(self, arg1, arg2):  # init()方法里面的参数都是装饰器的参数
        print('执行类Decorator的__init__()方法')
        self.arg1 = arg1
        self.arg2 = arg2
 
    def __call__(self, func):  # 因为装饰器带了参数,所以接收传入函数变量的位置是这里
        print('执行类Decorator的__call__()方法')
 
        def baiyu_warp(*args):  # 这里装饰器的函数名字可以随便命名,只要跟return的函数名相同即可
            print('执行wrap()')
            print('装饰器参数:', self.arg1, self.arg2)
            print('执行' + func.__name__ + '()')
            func(*args)
            print(func.__name__ + '()执行完毕')
 
        return baiyu_warp
 
 
@BaiyuDecorator('Hello', 'Baiyu')
def example(a1, a2, a3):
    print('传入example()的参数:', a1, a2, a3)
 
 
if __name__ == '__main__':
    print('准备调用example()')
    example('Baiyu', 'Happy', 'Coder')
    print('测试代码执行完毕')

三、装饰器的执行顺序是从里到外的。

关闭

用微信“扫一扫”