Python中的闭包和装饰器(二)老男孩Python培训

    /    2019-06-26

上面的写法写死了func = index,我们还可以优化下:

def timer(func):  # 传一个func参数和下面func = index一样都是在my_index函数内部定义了一个局部变量
    # func = index  # 在外部函数定义一个局部变量
    def wrapper():  # 设置一个参数
        start_time = time.time()
        func()  # 在这个函数内部调用下func
        stop_time = time.time()
        print("耗时{}秒。".format(stop_time - start_time))
    return wrapper好了,我们刚刚就已经写好了一个装饰器。

验证一下,我们的成果:

index = timer(index)
index()

输出:

欢迎访问首页。
耗时1.0029211044311523秒。

没有修改原函数的源代码。

没有修改原函数的调用方式。(虽然此时的index已不再是原来的index,但是并没有修改调用index的方式。)

现在我们来验证下我们的成果:

import time
import random

def index():
    time.sleep(random.randrange(15))  # 随机sleep几秒
    print("欢迎访问首页。")

def home():
    time.sleep(random.randrange(15))  # 随机sleep几秒
    print("欢迎访问个人主页。")

def timer(func):  # 传一个func参数和下面func = index一样都是在my_index函数内部定义了一个局部变量
    def wrapper():  # 设置一个参数
        start_time = time.time()
        func()  # 在这个函数内部调用下func
        stop_time = time.time()
        print("耗时{}秒。".format(stop_time - start_time))
    return wrapper

index = timer(index)
home = timer(home)
index()
home()

输出:

欢迎访问首页。
耗时3.0008788108825684秒。
欢迎访问个人主页。
耗时3.00280499458313秒。

简直完美,功能实现可以装饰任意函数。就是写起来有点麻烦。Python中支持更简便的写法,往下看。

装饰器的语法

在被装饰对象的正上方单独的一行写上@装饰器名即可,即:

用装饰器的语法修改一下我们上面的代码:

def timer(func):  # 传一个func参数和下面func = index一样都是在my_index函数内部定义了一个局部变量
    def wrapper():  # 设置一个参数
        start_time = time.time()
        func()  # 在这个函数内部调用下func
        stop_time = time.time()
        print("耗时{}秒。".format(stop_time - start_time))
    return wrapper

@timer  # 相当于做了 index = timer(index) 操作
def index():
    time.sleep(random.randrange(15))  # 随机sleep几秒
    print("欢迎访问首页。")

让我们练习写一个装饰器来巩固下上面学习的内容:给 index 和 home 函数加一个验证功能,用户名和密码正确才打印欢迎信息。否则打印“验证失败”。

先写一个用于验证的装饰器:

def auth(func):
    def wrapper():
        name = input("用户名:").strip()
        password = input("密码:").strip()
        if name == "Andy" and password == "123":
            print("验证成功!")
            func()
        else:
            print("验证失败!")
    return wrapper

测试一下:

@auth
def index():
    time.sleep(random.randrange(15))  # 随机sleep几秒
    print("欢迎访问首页。")

index()

输出:

用户名:Andy
密码:123
验证成功!
欢迎访问个人主页。

基本的装饰器介绍到这里就结束了。后面还会有多个装饰器及带参数的装饰器。

(0)

分享至