IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Python知识库 -> Python 修饰器的用法和技巧以及应用 -> 正文阅读

[Python知识库]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)
  Python知识库 最新文章
Python中String模块
【Python】 14-CVS文件操作
python的panda库读写文件
使用Nordic的nrf52840实现蓝牙DFU过程
【Python学习记录】numpy数组用法整理
Python学习笔记
python字符串和列表
python如何从txt文件中解析出有效的数据
Python编程从入门到实践自学/3.1-3.2
python变量
上一篇文章      下一篇文章      查看所有文章
加:2021-11-15 15:49:40  更:2021-11-15 15:50:10 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 23:38:58-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码