15、装饰器


```# 一装饰器介绍
# 1.1为何要用装饰器
"""
软件的设计应该遵循开放封闭原则,即对扩展是开放的,而对修改是封闭的。
对扩展开放,意味着有新的需求或变化时,可以对现有代码进行扩展,以适
应新的情况。对修改封闭,意味着对象一旦设计完成,就可以独立完成其工
作,而不要对其进行修改。软件包含的所有功能的源代码以及调用方式,都
应该避免修改,否则一旦改错,则极有可能产生连锁反应,最终导致程序崩溃
,而对于上线后的软件,新需求或者变化又层出不穷,我们必须为程序提供扩
展的可能性,这就用到了装饰器。
"""
# 1.2什么是装饰器
"""
’装饰’代指为被装饰对象添加新的功能,’器’代指器具/工具,装饰器与
被装饰的对象均可以是任意可调用对象。概括地讲,装饰器的作用就是在不
修改被装饰对象源代码和调用方式的前提下为被装饰对象添加额外的功能。
装饰器经常用于有切面需求的场景,比如:插入日志、性能测试、事务处理
、缓存、权限校验等应用场景,装饰器是解决这类问题的绝佳设计,有了装
饰器,就可以抽离出大量与函数功能本身无关的雷同代码并继续重用。

提示:可调用对象有函数,方法或者类,此处我们单以本章主题函数为例,
来介绍函数装饰器,并且被装饰的对象也是函数。
"""
# 二装饰器的实现
"""
函数装饰器分为:无参装饰器和有参装饰器,两者的实现原理一样,都是'函数嵌套+
闭包+函数对象'的组合产物。
"""
# 2.1无参装饰器的实现
# 如果想为下面函数添加统计其执行时间的功能
import time
# def timer(func):
#     def wrapper(*args,**kwargs):
#         start_time = time.time()
#         func(*args,**kwargs)
#         end_time = time.time()
#         print('run time is %s' %(end_time-start_time))
#
#     return wrapper
# @timer
# def home(name):
#     time.sleep(5)
#     print('welcome to home page %s' %(name))
#
# home('egon')









# def timer(func):  # 获取程序运行的时间+
#     def wrapper(*args, **kwargs):
#         start_time = time.time()
#         res = func(*args, **kwargs)
#         stop_time = time.time()
#         print('run time is %s' % (stop_time - start_time))
#         return res
#
#     return wrapper

# def timer(func):
#     def wrapper(*args,**kwargs):
#         start_time = time.time()
#         res = func(*args,**kwargs)
#         stop_time = time.time()
#         print('run time is %s' %(start_time-stop_time))
#         return res
#     return wrapper


# def home(name):
#     time.sleep(5)
#     print('welcome to the home page',name)
# h=timer(home)
# h('egon')
# 之所以会抛出异常,是因为home('egon')调用的其实是wrapper('egon'),而函数wrapper
# 参数。wrapper函数接受的参数其实是给最原始的func用的,为了能满足被装饰函数参数的所
# 有情况,使用上args+*kwargs组合,于是修正装饰器timer如上

"""
此时我们就可以用timer来装饰带参或者不带参的函数了,但是为了简洁而优雅的使用装饰器,
python 提供了专门的装饰器语法来取代index=timer(index)的形式,需要在被装饰对象的正上方
单独一行添加@time,当解释器解释到@time时就会调用timer函数,且把它正下方的函数名当做
实参传入,然后将返回值的结果重新赋值给元函数名
"""
def timer(func):
    def wrapper(*args,**kwargs):
        start_time = time.time()
        res = func(*args,**kwargs)
        stop_time = time.time()
        print('run time is %s' %(stop_time-start_time))
        return res
    return wrapper
@timer  # index=timer(index)
def index(name):
    time.sleep(3)
    print('wlecome to the index page', name)
    return 200

o = index('egon')
print(o)


# print(index.__name__)
@timer
def home(name):
    time.sleep(5)
    print('welcome to the home page', name)


# ======================================================================
# 2.2有参装饰器的实现
"""
了解无参装饰器的实现原理后,我们可以再实现一个用来被装饰对象添加认证功能的装饰器,
实现的基本形式如下
"""
# def foo(func):
#     def wrapper(*args,**kwargs):

# def a_new_decorator(a_func):

#装饰器,为函数添加认证和时间纪录功能
# 装饰器模板
# def auth(func):
#     def wrapper(*args,**kwargs):
#         # 添加新函数
#         # ------------
#         res = func(*args,**kwargs) # 调用原来函数
#         return res
#     return wrapper
#
import time
# timer 是一个具有计时功能的修饰器
def timer(func):
    def wrapper1(*args,**kwargs):
        start_time = time.time()
        res1 = func(*args,**kwargs)
        stop_time = time.time()
        print('run time is %s' %(stop_time-start_time))
        return res1
    return wrapper1


# auth 是一个具有认证功能的修饰器
def auth(func):
    def wrapper(*args, **kwargs):
        # 添加新函数
        # ------------
        # 认证功能
        with open(r'C:\python_test\demo1\pythonweek3\day17\user_res.txt', mode='rt', encoding='utf-8') as f:
            go = 3
            data = f.read().split('\n')
            while go:
                input_name = input('name--')
                input_password = input('password')
                for line in range(len(data) - 1):

                    name, password = data[line].split(':')
                    if name == input_name and password == input_password:
                        print('登录成功')
                        res = func(*args, **kwargs)  # 调用原来函数
                        return res
                else:
                    go -= 1
                    print('登录失败,还有{}次机会'.format(go))

    return wrapper  #

@timer
@auth
def max(x, y):
    res = x if x > y else y
    print('最大值为',res)
max(1,2)




    
上一篇:Requests库入门(学习笔记)


下一篇:python3函数可变输入参量