8-20---装饰器及应用(附实例)

 什么是装饰器:

  • 装饰器他人的器具,本身可以是任意可调用对象,被装饰者也可以是任意可调用对象。
    强调装饰器的原则

  • 1 不修改被装饰对象的源代码。 2 不修改被装饰对象的调用方式

  • 装饰器的目标:在遵循1和2的前提下,为被装饰对象添加上新功能

 装饰器需要的知识储备为:高阶函数+函数嵌套+闭包

  • 装饰器的框架(函数内加上了统计时间的功能):

  • 下图为无参数装饰器:
  • 注意看第一个代码和这个代码的区别,在原函数中增加了形参和return返回值后,装饰器中的变化。
import time
#装饰器的框架
def timer(func):
    print(func)
    def wrapper(*args,**kwargs):
        starttime = time.time()
        func()  #func()<==>test()
        stoptime = time.time()
        print("函数运行时间为 %s" % (stoptime-starttime))
    return wrapper

@timer #test = timer(test)   timer(test)返回的是wrapper的地址,所以test<==>wrapper

def test():
    time.sleep(3)
    print("程序已经运行完毕")
test()
  •  有参数装饰器:只需在将@timer 改为@timer( driver='file' ),注意装饰器后面为关键字参数(可参考下面的登录+认证功能的代码)
  • 加上返回值和参数

 

def timer(func):
    print(func)
    def wrapper(*args,**kwargs):
        starttime = time.time()
        res = func("张三",18)  #func()<==>test()
        stoptime = time.time()
        print("函数运行时间为 %s" % (stoptime-starttime))
        return res
    return wrapper


@timer #test = timer(test)   timer(test)返回的是wrapper的地址,所以test<==>wrapper

def test(name,age):
    time.sleep(3)
    print("程序已经运行完毕,姓名是%s,年龄为%s " % (name,  age))
    return "这是test的返回值"
res = test()
print(res)

 

 装饰器的应用:

  •  登录功能
  1. 函数里加上了统计时间的功能
  2. 模拟登录京东首页
import datetime

def test(func):
    def wrapper():
        name = input("请输入姓名:")
        now_time = datetime.datetime.now()
        print("尊敬的%s先生,现在时间为%s" % (name, now_time))
        res = func()
        return res

    return wrapper


@test  # index = test(index)
def index():
    print("欢迎来到京东主页")

  •  登录+认证功能
  1. 用的一个很有用的知识点,通过用全局变量,保存登录的状态,代码中有清楚的表示,
  2. 下面的代码用的是有参数的装饰器,参数用来表示登录的认证类型(可以通过下面的代码了解带参装饰器的用法)
# 具有认证功能
# 只需要登陆一次,可保存登陆状态


# 全局变量(检测登陆状态)
func_auth = {'user': None, 'login': False}


def test_auth(auth_type='file'):
    def test(func):
        def wrapper():
            print("认证类型是:", auth_type)
            auth_dict = {'alex': 123, "段亚运": 123, 'lin': 123}

            if auth_type == "file":

                # 判断当前是否为登陆状态
                if func_auth['user'] and func_auth['login']:
                    print("当前为登陆状态")
                    res = func()
                    return res

                name = input("请输入用户名:")
                password = input("请输入密码:")
                print("尊敬的%s先生," % name)

                # 切记input()得出的结果是"str"
                if auth_dict[name] == eval(password):
                    #print("第一次登陆成功")
                    func_auth['user'] = name
                    func_auth['login'] = True
                    res = func()
                    return res
            elif auth_type == 'mongodb':
                print("认证方式不正确")

        return wrapper

    return test


@test_auth(auth_type="file")  # index = test(index)
def index():
    print("欢迎来到京东主页")


@test_auth(auth_type="mongodb")
def home():
    print("欢迎进入您的个人中心")


index()
home()
  • 下面这个代码是复制的老男孩教育中,linhaifeng老师博客中的一段关于

  • 登录一次后会保存状态,但是保存的时间有限定,超时后须重新登录(方法不难,不过感觉实现的不是特别好,仅供参考)

# 编写装饰器,为多个函数加上认证功能,要求登录成功一次,
# 在超时时间内无需重复登录,超过了超时时间,则必须重新登录

# 全局变量(检测登陆状态)
import time
import random

user = {'user': None, 'login_time': None, 'timeout': 0.000003}


def timmer(func):
    def wrapper(*args, **kwargs):
        s1 = time.time()
        res = func(*args, **kwargs)
        s2 = time.time()
        print('%s' % (s2 - s1))
        return res

    return wrapper


def auth(func):
    def wrapper(*args, **kwargs):
        if user['user']:
            timeout = time.time() - user['login_time']
            if timeout < user['timeout']:
                return func(*args, **kwargs)
        name = input('name>>: ').strip()
        password = input('password>>: ').strip()
        if name == 'egon' and password == '123':
            user['user'] = name
            user['login_time'] = time.time()
            res = func(*args, **kwargs)
            return res

    return wrapper


@auth
def index():
    time.sleep(random.randrange(3))
    print('welcome to index')


@auth
def home(name ):
    time.sleep(random.randrange(3))
    print('welcome %s to home ' % name)


index()
home('egon')

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值