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装饰器

装饰器是python一个重要的部分,由它的名称我们就可以大致了解到它的功能:拓展其他函数。装饰器可以让我们的代码更加简洁,也更加pythonic。

首先,我们先回顾一下基础概念。

、在python中,如果调用一个函数不带括号时,调用的是这个函数本身,无需等待该函数执行完毕;如果调用一个函数带括号时,调用的是这个函数return的结果,需要等待函数执行完毕的结果。实例展示如下:

def demo1():
    print("hello 2022")
demo1()
print(demo1)
#结果依次如下:
#hello 2022
#<function demo1 at 0x015E77C0>

二、函数闭包

闭包就是引用自由变量的函数,这个函数保存了执行的上下文,可以脱离原本的作用于存在。

def dec():
    para = 'closure'

    # 嵌套一层 形成闭包
    def wrapper():
        print(para)
    return wrapper

# 获取一个闭包
closure =  dec()

# 执行
closure()

para是一个局部变量,在dec中执行后即被回收。在嵌套函数中使用了这个变量,也就是将局部para变量封闭在嵌套函数中,形成闭包。

三、python装饰器

介绍了以上基础概念之后,我们再来介绍python装饰器的详细用法。

现在有如下代码:

def func():
    print("hello")
    sleep(5)
    print(2022)

现在需求来了,我们想拓展一下原来的函数,在原有的基础下增加一个计算函数执行时间的模块。

我们首先想到的便是编写一个计时函数,可以直接完成我们的需求。代码如下:

from time import time, sleep
def timer():
    start = time()
    func()
    end = time()
    res = end - start
    print("执行时间为{:.3f}".format(res))
def func():
    print("hello")
    sleep(5)
    print(2022)
if __name__  == "__main__":
    timer()

#执行结果如下
#hello
#2022
#执行时间为5.000

现在我们已经完成了对func()函数执行时间的计算,值得庆幸的是我们现在只有一个函数需要计算它的运行时间,如果一个代码中有成千上万计像func()函数都需要计算他们的运行时间该怎么办?总不能为每一个函数添加一个计时器或者不断地修改timer函数,这样不仅对操作员还是机器都是一个巨大的折磨。这时我们便选用@装饰器来解决我们这些问题。

代码展示如下:

from time import time, sleep
def timer(c):
    print("this is timer")
    def wrapper():
        start = time()
        c()
        end = time()
        res = end - start
        print("执行时间为{:.3f}".format(res))
    return wrapper
@timer
def func():
    print("hello")
    sleep(5)
    print(2022)
if __name__  == "__main__":
    func()
"""
执行结果如下
this is timer
hello
2022
执行时间为5.000
"""

通过对比,我们发现timer函数中增加了wrapper函数,timer函数的返回值是wrapper函数,可以粗暴的理解为timer()=wrapper()。

现在来分析一下以上代码的工作流程:@timer及其一下四行为装载装饰器的过程,装饰器timer的参数是一个函数,返回值也是一个函数,作为参数的函数c()就在闭包函数内执行;在func()前使用@timer,就相当于为func()注入了新的功能,我们既不需要入侵原函数,也不用重复执行原函数。

接下来我们继续分析func()有参数的情况。

代码如下:

from time import time, sleep
def timer(c):
    print("this is timer")
    def wrapper(a, b):
        start = time()
        c(a, b)
        end = time()
        res = end - start
        print("执行时间为{:.3f}".format(res))
    return wrapper
@timer
def func(a, b):
    sleep(5)
    print("a+b=%d" % (a + b))
if __name__ == "__main__":
    func(4, 5)

"""
this is timer
a+b=9
执行时间为5.001
"""

需要注意的是,func()与wrapper()中的参数必须一致。

接下来我们要思考的问题便是:如果func()有无穷多个参数怎么办呢?有没有一个简单的方法可以传递参数?我们想到的是利用位置参数*args和关键字参数**kwargs。(*args与**kwargs的用法不在赘述)具体是怎么实现的呢?我们来看代码。

from time import time, sleep
def timer(c):
    print("this is timer")
    def wrapper(*args, **kwargs):
        start = time()
        c(*args, **kwargs)
        end = time()
        res = end - start
        print("执行时间为{:.3f}".format(res))
    return wrapper
@timer
def func(a, b):
    sleep(2)
    print("a+b=%d" % (a + b))
if __name__ == "__main__":
    func(4, 5)
"""
this is timer
a+b=9
执行时间为2.000

"""

显而易见,我们大大简化了代码。

接下来有两个例子供大家更好的掌握装饰器的用法。

import time
def timer(func):
    print("this is timer")
    def wrapper(*args, **kwargs):
        start = time.time()
        func(*args, **kwargs)
        end = time.time()
        cha_zhi = end - start
        print("运行时间为%d" % cha_zhi)
    return wrapper
def login(func):
    print("this is login")
    def wrapper1(*args, **kwargs):
        user = input("please input your name:")
        password = input("please input your password:")
        if user == 'root' and password == 'root':
            print("login successful!")
            res = func(*args, **kwargs)
            return res
        else:
            print("error!")
    return wrapper1
@login
@timer
def index():
    time.sleep(0.5)
    print("from index")
index()
"""
this is timer
this is login
please input your name:root
please input your password:root
login successful!
from index
运行时间为0
"""
def dec1(func):
    print("1")
    def one():
        print("2")
        func()
        print("3")
    return one
def dec2(func):
    print("a")
    def two():
        print("b")
        func()
        print("c")
    return two
@dec1
@dec2
def test():
    print("test")
test()
"""
a
1
2
b
test
c
3
进程已结束,退出代码为 0

"""

?来看这块代码:当遇到两个装饰器时,执行的顺序是有下往上,即test=dec1(dec2(test)),先执行dec2(test),输出a,此时dec2()中的参数func指向test,返回two(),然后dec1(two), 输出1,dec1()中func指向two,返回one()。test()是实际被装载的函数,此时实际执行的是one(), 运行到func()时再执行two()。

  Python知识库 最新文章
Python中String模块
【Python】 14-CVS文件操作
python的panda库读写文件
使用Nordic的nrf52840实现蓝牙DFU过程
【Python学习记录】numpy数组用法整理
Python学习笔记
python字符串和列表
python如何从txt文件中解析出有效的数据
Python编程从入门到实践自学/3.1-3.2
python变量
上一篇文章      下一篇文章      查看所有文章
加:2022-01-30 18:53:50  更:2022-01-30 18:55:28 
 
开发: 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/16 1:50:03-

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