VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > temp > python入门教程 >
  • python--高级语法 9

day14:

1、开放封闭原则:

装饰器:装饰,装修,房子就可以住,如果装修,不影响你住,而且体验更加,让你生活中增加了很多功能:洗澡,看电视,沙发。
器:工具。
开放封闭原则:
开放:对代码的拓展开放的, 更新地图,加新枪,等等。
封闭:对源码的修改是封闭的。闪躲用q。就是一个功能,一个函数。 别人赤手空拳打你,用机枪扫你,扔雷.....这个功能不会改变。

装饰器:完全遵循开放封闭原则。
所以装饰器最终最完美的定义就是: 在不改变原函数的代码以及调用方式的前提下,为其增加新的功能。
装饰器就是一个函数。(装饰器就是一个闭包)

2、装饰器的初识:

  • 版本一: Mike 写一些代码,测试一下index()函数的执行效率。

    #
    import time
    #print(time.time())  # 格林威治时间。
    
    def index():
        '''有很多代码.....'''
        time.sleep(2)  # 模拟的网络延迟或者代码效率
        print('欢迎登录博客园首页')
    
    def dariy():
        '''有很多代码.....'''
        time.sleep(3) # 模拟的网络延迟或者代码效率
        print('欢迎登录日记页面')
    
    start_time=time.time()
    index()
    end_time=time.time()
    print(end_time-start_time)
    
    start_time=time.time()
    dariy()
    end_time=time.time()
    print(end_time-start_time)
    
    欢迎登录博客园首页
    2.0008764266967773
    欢迎登录日记页面
    3.0002834796905518
    
    Process finished with exit code 0
    

版本一的问题:如果测试别人的代码,必须重新复制粘贴。

  • 版本二:利用函数,解决代码重复使用的问题(解决版本一问题)

    #版本二:利用函数,解决代码重复使用的问题(解决版本一问题)
    
    import time
    def index():
        '''有很多代码.....'''
        time.sleep(2) # 模拟的网络延迟或者代码效率
        print('欢迎登录博客园首页')
    
    def dariy():
        '''有很多代码.....'''
        time.sleep(3) # 模拟的网络延迟或者代码效率
        print('欢迎登录日记页面')
    
    def timmer(f):
        start_time = time.time()
        f()
        end_time = time.time()
        print(f'测试本函数的执行效率:{end_time-start_time}')
    
    timmer(index)
    
    #版本二还是有问题: 原来index函数源码没有变化,给原函数添加了一个新的功能测试原函数的执行效率的功能。
    #满足开放封闭原则么?原函数的调用方式改变了。
    
    欢迎登录博客园首页
    测试本函数的执行效率:2.0008556842803955
    
    Process finished with exit code 0
    
  • 版本三:不能改变原函数的调用方式。

    #版本三:不能改变原函数的调用方式。
    import time
    def index():
        '''有很多代码.....'''
        time.sleep(2) # 模拟的网络延迟或者代码效率
        print('欢迎登录博客园首页')
    
    
    def timmer(f):   # f = index  (funciton index123)
        def inner():   # inner :(funciton inner123)
            start_time = time.time()
            f()   #index() (funciton index123)
            end_time = time.time()
            print(f'测试本函数的执行效率:{end_time-start_time}')
        return  inner    # (funciton inner123)
    
    # ret=timmer(index)
    # ret()   #相当于inner()
    index=timmer(index)   # inner (funciton inner123)
    index()  # inner()
    
  • 版本四:具体研究(装饰器的本质就是闭包)

    import time
    def index():
        '''有很多代码.....'''
        time.sleep(2) # 模拟的网络延迟或者代码效率
        print('欢迎登录博客园首页')
    
    def timmer(f):
        f = index
        # f = <function index at 0x0000023BA3E8A268>
        def inner():
            start_time = time.time()
            f()
            end_time = time.time()
            print(f'测试本函数的执行效率{end_time-start_time}')
        return inner
    
    index = timmer(index)
    index()
    
  • 版本五:python做了一个优化;提出了一个语法糖的概念。 标准版的装饰器

    (@timmer #等于index = timmer(index))

    #版本五:python做了一个优化;提出了一个语法糖的概念。 标准版的装饰器
    import time
    
    #timmer装饰器
    def timmer(f):
    
        def inner():
            start_time = time.time()
            f()
            end_time = time.time()
            print(f'测试本函数的执行效率:{end_time-start_time}')
        return inner
    
    
    @timmer    #等于index = timmer(index)
    def index():
        '''有很多代码.....'''
        time.sleep(2) # 模拟的网络延迟或者代码效率
        print('欢迎登录博客园首页')
    
    @timmer
    def dariy():
        '''有很多代码.....'''
        time.sleep(3) # 模拟的网络延迟或者代码效率
        print('欢迎登录日记页面')
    
    
    # index = timmer(index)
    # index()
    #
    # dariy = timmer(dariy)
    # dariy()
    
    index()
    dariy()
    
  • 版本六:被装饰函数带返回值

    #版本六:被装饰函数带返回值
    import time
    
    #timmer装饰器
    def timmer(f):
    
        def inner():
            start_time = time.time()
            r=f()
            #print(f'这个是f():{f()}!!!')
            end_time = time.time()
            print(f'测试本函数的执行效率:{end_time-start_time}')
            return r
        return inner
    
    @timmer    #等于index = timmer(index)
    def index():
        '''有很多代码.....'''
        time.sleep(0.6) # 模拟的网络延迟或者代码效率
        print('欢迎登录博客园首页')
        return 666
    
    # 加上装饰器不应该改变原函数的返回值,所以666 应该返回给我下面的ret,
    # 但是下面的这个ret实际接收的是inner函数的返回值,而666返回给的是装饰器里面的
    # f() 也就是 r,我们现在要解决的问题就是将r给inner的返回值。
    ret=index()
    print(ret)
    
    欢迎登录博客园首页
    测试本函数的执行效率:0.6006889343261719
    666
    
    Process finished with exit code 0
    
  • 版本七:被装饰函数带参数

    #版本七:被装饰函数带参数
    import time
    
    #timmer装饰器
    def timmer(f):
    
        def inner(*args,**kwargs):
            #  函数的定义:* 聚合  args = ('李舒淇',18)
            start_time = time.time()
            r=f(*args,**kwargs)
            # 函数的执行:* 打散:f(*args) --> f(*('李舒淇',18))  --> f('李舒淇',18)
            #print(f'这个是f():{f()}!!!')
            end_time = time.time()
            print(f'测试本函数的执行效率:{end_time-start_time}')
            return r
        return inner
    
    @timmer
    def index(name):
        '''有很多代码.....'''
        time.sleep(0.6) # 模拟的网络延迟或者代码效率
        print(f'欢迎{name}登录博客园首页')
        return 666
    
    @timmer
    def dariy(name,age):
        '''有很多代码.....'''
        time.sleep(0.5) # 模拟的网络延迟或者代码效率
        print(f'欢迎{age}{name}登录日记页面')
    
    dariy('李舒淇',18)  # inner('李舒淇',18)
    index('吴亦凡')  #相当于  inner('吴亦凡')
    
    欢迎18岁李舒淇登录日记页面
    测试本函数的执行效率:0.5007114410400391
    欢迎吴亦凡登录博客园首页
    测试本函数的执行效率:0.6006894111633301
    
    Process finished with exit code 0
    
标准版的装饰器;

def wrapper(f):
    def inner(*args,**kwargs):  #  函数的定义:* 聚合  args = ('李舒淇',18)
        '''添加额外的功能:执行被装饰函数之前的操作'''
        ret = f(*args,**kwargs) #* 打散:f(*args) --> f(*('李舒淇',18))  --> f('李舒淇',18)
        ''''添加额外的功能:执行被装饰函数之后的操作'''
        return ret
    return inner

3、装饰器的执行过程(步骤详解)

  • 图片详解:

  • 文字详解:
1.第一步执行@wrapper装饰器,相当于执行 func=wrapper(func);

2.第二步把被装饰函数的函数名当做参数,带入到装饰器参数,即f=func,执行装饰器;

3.第三步返回 inner ,即wrapper(fun)的结果是得到 inner   即func=inner ;

4.第三步执行func(),等同于执行inner(),所以会执行装饰器的的内嵌函数,先执行print('此处代码执行在被装饰函数调用之前'),然后执行被装饰函数func(),执行print('in func'),在执行print('此处代码执行在被装饰函数调用之后'),并且把被装饰函数的执行结果(print('in func'))返回给执行者func()
  • 具体代码:
def wrapper(f):
    def inner(*args,**kwargs):
        print('此处代码执行在被装饰函数调用之前')
        ret=f(*args,**kwargs)
        print('此处代码执行在被装饰函数调用之后')
        return ret
    return inner

@wrapper   #相当于 func=wrapper(fun)
def func():
    print('in func')

func()

此处代码执行在被装饰函数调用之前
in func
此处代码执行在被装饰函数调用之后

Process finished with exit code 0

4、python 中多个装饰器的执行顺序:

  • 装饰器函数在被装饰函数定义好后立即执行。多个装饰器的调用顺序是自下往上的。
  • 被装饰函数执行时,装饰器的执行顺序是从上往下的。
def wrapper1(f1):
    print('in wrapper1')
    def inner1(*args,**kwargs):
        print('in inner1')
        ret = f1(*args,**kwargs)
        return ret
    return inner1
 
def wrapper2(f2):
    print('in wrapper2')
    def inner2(*args,**kwargs):
        print('in inner2')
        ret = f2(*args,**kwargs)
        return ret
    return inner2
 
def wrapper3(f3):
    print('in wrapper3')
    def inner3(*args,**kwargs):
        print('in inner3')
        ret = f3(*args,**kwargs)
        return ret
    return inner3
 
@wrapper1
@wrapper2
@wrapper3
def func():
    print('in func')
func()
# in wrapper3
# in wrapper2
# in wrapper1
# in inner1
# in inner2
# in inner3
# in func
#装饰器函数在被装饰函数定义好后立即执行。多个装饰器的调用顺序是自下往上的。
# 被装饰函数执行时,装饰器的执行顺序是从上往下的。

分析:

分析:
 func = wrapper3(func)  ---> 先打印'in wrapper3', func = inner3 ,f3 = func
 func = wrapper2(func) --->即 inner3 = wrapper2(inner3) ---> 先打印'in wrapper2', inner3 = 			inner2 ,f2 = inner3  --> func = inner2
 func = wrapper1(func) --->即  inner2 = wrapper1(inner2) --->先打印'in wrapper1',  inner2 			= inner1 ,f1 = inner2  --> func = inner1
 执行 func() 即执行执行 inner1() ,先打印 'in inner1',再执行 f1(),即执行inner2()
 即执行inner2() ,先打印 'in inner2',再执行 f2(),即执行inner3()
 即执行inner3() ,先打印 'in inner3',再执行 f3(),即执行func(),打印 'in func '

5、装饰器的应用

# 装饰器的应用:登录认证
# 这周的周末作业:模拟博客园登录的作业。装饰器的认证功能。
  • 基本框架
def login():
    pass
def register():
    pass

status_dict={
    'username':None,
    'status':False
}

def auth(f):
    '''
    你的装饰器完成:访问被装饰函数之前,写一个三次登录认证的功能。
    登录成功:让其访问被装饰得函数,登录没有成功,不让访问。
    :param f:
    :return:
    '''
    def inner(*args,**kwargs):
        '''访问函数之前的操作,功能'''

        ret = f(*args,**kwargs)
        '''访问函数之后的操作,功能'''
        return ret

    return inner

def article():
    print('欢迎访问文章页面')

def comment():
    print('欢迎访问评论页面')

def dariy():
    print('欢迎访问日记页面')

article()
comment()
dariy()
def login():
    dic = {}
    username = input('请输入用户名').strip()
    password = input('请输入密码').strip()
    if username  in  register() and password == register()[username]:
        dic[username] = password
        print('登录成功')
    else:
        print('用户名或者密码错误')
    return  dic

def register():
    dic_1 = {}
    with open('a',encoding='utf-8') as f:
        for line in f:
            a,b = line.strip().split()
            dic_1[a] = b
        return  dic_1

status_dict = {'username':None,'status':False}

def auth(f):
    def inner(*args,**kwargs):
        if status_dict['status']:
            ret = f(*args,**kwargs)
            return ret
        else:
            status_dict['username'] = login()
            status_dict['status'] = True
            ret = f(*args, **kwargs)
            return ret
    return inner


出处:https://www.cnblogs.com/wushaofan/p/17156647.html

相关教程