栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

Python 修饰器的用法和技巧以及应用

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Python 修饰器的用法和技巧以及应用

装饰器(decorator):

  1. 定义了一个函数,想在运行时动态增加功能,又不想改动函数本身的代码。可以起到复用代码的功能,避免每个函数重复性编写代码,简言之就是拓展原来函数功能的一种函数。
  2. 在python中,装饰器(decorator) 分为函数装饰器和类装饰器两种。
  3. python中内置的@语言就是为了简化装饰器调用。

列出几个装饰器函数:import functools

  1. 打印日志:@log
  2. 检测性能:@performance
  3. 数据库事务:@transaction
  4. URL路由:@post(‘/register’)
例子

注意

  1. wrapper函数的参数传入就是func的参数传入, 既可以使用通用的*args, **kw 一星大斗师和二星大斗师入场, 也可以直接定义
a. 二层套娃

fun执行流程是 Decorator→wrapper→fun

# 先执行log(now), 返回wrapper
# 调用wrapper, 打印函数名
# 在调用now, 就是wrapper的输入信息
def log(func):
    def wrapper(*args, **kw): # 这里得到func的参数
        print("call %s():", func.__name__)
        return func(*args, **kw) # 调用原始函数
    return wrapper

# 相当于  now = log(now), 
@log
def now():
    print("123")

if __name__ == "__main__":
    now()
b. 三层套娃

fun执行流程是 Log→Decorator→wrapper→fun

# 先执行log("execute"), 返回Decorator函数, 
# 在调用Decorator函数返回wrapper, 
# 在调用wrapper打印信息, 返回func, 
# 在调用func, 执行func
# 相当于三层嵌套
def log(text):
    def decorator(func):
        def wrapper(*args, **kw):
            print('%s %s():' % (text, func.__name__))
            return func(*args, **kw)
        return wrapper
    return decorator


@log('execute')
def now():
    print('2015-3-25')

if __name__ == '__main__':
    now()
c. fun信息传给wrapper后返回的函数对象成了wrapper

@functools.wraps(func)

import functools
def log(text):
    def decorator(func):
        def wrapper(*args, **kw):
            print('%s %s():' % (text, func.__name__))
            return func(*args, **kw)
        return wrapper
    return decorator


@log('execute')
def now():
    print('2015-3-25')
    print(now.__name__) 
    # wrapper 这是因为这个函数执行完, 最终返回的是wrapper的函数指针, 
    # 逻辑就是log(text)(now), log(text)返回decorator再返回wrapper, 因此这里就成这了, 
    # 解决的方法就是把原始函数now的__name__等属性完全赋值到wrapper()函数中即可, 

# 解决方案见下面

def log3(func):
    @functools.wraps(func) # 把func的信息放入wrapper中
    def wrapper(*args, **kw):
        print('%s():' % (func.__name__))
        return func(*args, **kw)
    return wrapper

def log2(text):
    def decorator(func):
        @functools.wraps(func) # 把func的信息放入wrapper中
        def wrapper(*args, **kw):
            print('%s %s():' % (text, func.__name__))
            return func(*args, **kw)
        return wrapper
    return decorator

@log2('execute')
@log3
def now2():
    print('hello world')
    print(now2.__name__) 

if __name__ == '__main__':
    now()
    print("------------------")
    now2()
应用 a. 函数执行时间
import time
import functools

# 不带参数的二层套娃
def timeCost(func):
    @functools.wraps(func)
    def log_time(*args, **kw):
        t0 = time.time()
        func(*args, **kw)
        t1 = time.time()
        print(f"function:{func.__name__}, time cost :{t1-t0}")
        return t1-t0
    return log_time

# 带参数的三层套娃
def timeCost2(unit):
    def decorator(func):
        @functools.wraps(func)
        def log_time(*args, **kw):
            t0 = time.time()
            func(*args, **kw)
            t1 = time.time()
            print(f"function:{func.__name__}, time cost :{t1-t0} {unit}")
            return t1-t0
        return log_time
    return decorator

@timeCost
@timeCost2("s") # 多修饰时, 先执行接近函数的, 因此先带ms, 然后在带
def test(t):
    time.sleep(t)
if __name__ == '__main__':
    test(3)
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/499113.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号