zoukankan      html  css  js  c++  java
  • Python函数之—— 装饰器(Day13)

    一.什么是装饰器

    顾名思义,装饰器指为其他函数添加新功能

    装饰器定义:本质就是函数,功能是为其他函数添加新功能

    二.装饰器需要遵循的原则

    1.不修改被装饰函数的源代码(开放封闭原则)

    2.为被装饰函数添加新功能后,不修改被修改函数的调用方式

    3.装饰器的本质 :闭包函数

    功能:就是在不改变原函数调用方式的情况下,在这个函数前后加上扩展功能

    示例1:

    import time
    def timmer(func):
        #函数名可以当做函数的参数
        def inner():
            start = time.time()
            func()
            end = time.time()
            print(end - start)
        return inner
    
    def hahaha():
        time.sleep(0.1)
        print('aaaa')

    示例2:

    def timmer(func):  #---> hahaha
        def inner(x,y):
            func(x,y)  # --->hahaha
        return inner
    
    def hahaha(a,b):
        time.sleep(0.1)
        print(a,b)
    
    def kkk(a):
        print(a)

    三.装饰器的主要功能和装饰器的固定结构

    装饰器的主要功能:

    在不改变函数调用方式的基础上在函数的前、后添加功能。

    装饰器的固定格式:

    def timer(func):
        def inner(*args,**kwargs):
            '''执行函数之前要做的'''
            re = func(*args,**kwargs)
            '''执行函数之后要做的'''
            return re
        return inner

    语法糖

    import time
    def wrapper(func):  # 装饰
        def inner(*args, **kwargs):
            start = time.time()
            ret = func(*args, **kwargs)
            end = time.time()
            print(end - start)
            return ret
        return inner
    
    @wrapper
    def lll():
        time.sleep(0.1)
        print('hello')
    
    lll()

     四.

      1.带参数的装饰器

    def outer(flag):
        def timer(func):
            def inner(*args,**kwargs):
                if flag:
                    print('''执行函数之前要做的''')
                re = func(*args,**kwargs)
                if flag:
                    print('''执行函数之后要做的''')
                return re
            return inner
        return timer
    
    @outer(False)
    def func():
        print(111)
    
    func()
    View Code
    F = False
    def outer(flag):
        def wrapper(func):
            def inner(*args,**kwargs):
                if flag:
                    print('before')
                    ret = func(*args,**kwargs)
                    print('after')
                else:
                    ret = func(*args, **kwargs)
                return ret
            return inner
        return wrapper
    
    @outer(F)  #-->@wrapper  -->hahaha = wrapper(hahaha)  #-->hahaha == inner
    def hahaha():
        print('hahaha')
    
    @outer(F)   #shuangww = outer(shuangww)
    def shuangww():
        print('shuangwaiwai')
    
    shuangww()
    hahaha()
    View Code

    2.多个装饰器装饰同一个函数

    def qqxing(func):  #func = pipixia_inner
        def qqxing_inner(*args,**kwargs):
            print('in qqxing:before')
            ret = func(*args,**kwargs)  #pipixia_inner
            print('in qqxing:after')
            return ret
        return qqxing_inner
    
    def pipixia(func):  #dapangxie
        def pipixia_inner(*args,**kwargs):
            print('in pipixia:before')
            ret = func(*args,**kwargs)      #dapangxie
            print('in pipixia:after')
            return ret
        return pipixia_inner
    
    #qqxing(pipixia_inner)  -->dapangxie = qqxing_inner()
    @qqxing    #dapangxie = qqxing(dapangxie)  -->dapangxie = qqxing(pipixia(dapangxie)) -->
    @pipixia   #dapangxie = pipixia(dapangxie)
    def dapangxie():
        print("饿了么")
    dapangxie()
    View Code

     3.开放封闭原则

    (1)对扩展是开放的

    我们说,任何一个程序,不可能在设计之初就已经想好了所有的功能并且未来不做任何更新和修改。所以我们必须允许代码扩展、添加新功能。

    (2)对修改是封闭的

    就像我们刚刚提到的,因为我们写的一个函数,很有可能已经交付给其他人使用了,如果这个时候我们对其进行了修改,很有可能影响其他已经在使用该函数的用户。

    装饰器完美的遵循了这个开放封闭原则。

    练习:

    '''
    编写装饰器,为多个函数加上认证的功能(用户的账号密码来源于文件),
    要求登录成功一次,后续的函数都无需再输入用户名和密码
    注意:从文件中读出字符串形式的字典,
    可以用eval('{"name":"egon","password":"123"}')转成字典格式
    '''
    # user_dict = {
    #     'pang':'123456',
    #     'panda':'binbin',
    #     'nezha':'101010'
    # }
    # print(type(user_dic))
    auth_status = {
        'user':None,          #设置全局的字典
        'status':False
    }
    def auth(func):
        def inner(*args,**kwargs):
            if auth_status['status']:     #如果auth_status为真,直接调用就行
                ret = func(*args, **kwargs)  # index/home
                return ret
            else:
                username = input('username : ').strip()#.strip()避免用户输入带有空格的用户名
                password = input('password : ').strip()
                # 读文件获取用户信息
                f = open('conf')  #文件句柄
                user_info = f.read()  #读取user用户信息
                user_dic = eval(user_info)   #通过eval转换成字典
                if user_dic.get(username) and user_dic[username] == password:#获取字典的k,确认有存在的用户名并找到对应的密码
                    print('login successful')
                    auth_status['user'] = username
                    auth_status['status'] = True
                    ret = func(*args,**kwargs)  #index/home  如果登录成功执行func
                    return ret
                else:
                    print('login failed')
        return inner
    
    @auth   #装饰器
    def index():
        print("欢迎来到首页")
    
    @auth
    def home():
        print("欢迎回家")
    
    index()
    index()
    home()
    index()
    # #认证功能
    # #获取用户名和密码
    # username = input('username : ').strip()
    # password = input('password : ').strip()
    # #读文件获取用户信息
    # f = open('conf')
    # user_info = f.read()
    # user_dic = eval(user_info)
    # if user_dic.get(username) and user_dic[username] == password:
    #     print('login successful')
    # else:
    #     print('login failed')
    '''
    进阶练习:
    1.编写下载网页内容的函数,要求功能是:用户传入一个url,函数返回下载页面的结果
    2.编写装饰器,实现缓存网页内容的功能:
    具体:实现下载的页面存放于文件中,如果文件内有值(文件大小不为0),
    就优先从文件中读取网页内容,否则,就去下载,然后存到文件中
    '''
    url_l = []
    from urllib.request import urlopen
    
    def get_cache(func):
        def inner(*args,**kwargs):
            url = args[0]
            filename = str(hash(url))
            if url in url_l:
                f = open(filename,'rb')
                ret = f.read()
            else:
                url_l.append(url)
                ret = func(*args, **kwargs)
                f = open(filename,'wb')
                f.write(ret)
            f.close()
            return ret
        return inner
    
    @get_cache
    def get(url):
        return urlopen(url).read()
    
    print(get('http://www.cnblogs.com/linhaifeng'))
    有一种能力,是持续不断的努力
  • 相关阅读:
    CORS详解
    JBoss 系列九十九:Rest WebService jBPM 6 集成演示样例
    atitit。浏览器缓存机制 and 微信浏览器防止缓存的设计 attilax 总结
    4G时代来临,运营商为谁搭台献唱?
    Pascal's Triangle II
    cocos2d-x 3.6版连连看载入资源
    SlidingMenu导入编译用法--Eclipse和IDEA
    【解决】hive动态添加partitions不能超过100的问题
    AngularJS clone directive 指令复制
    AndroidStudio文件夹结构视图讲解
  • 原文地址:https://www.cnblogs.com/shaojiafeng/p/7245423.html
Copyright © 2011-2022 走看看