• python----装饰器


                                                                                              装饰器

    一:楔子

              假如有一个函数,实现返回两个数的较大值:

          

    ef my_max(x,y):
        m = x if x>y else y
        return m
    bigger = my_max(10,20)
    print(bigger)

    20

    二:装饰器的形成

                  装饰器的本质:一个闭包函数(自由变量就是装饰的函数名)。

                 装饰器的功能:在不修改原函数及其调用的方式的情况下对原函数功能进行扩展。

                 装饰器的格式:

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

    三:语法糖      

    mport time                             #1
    def timer(func2):                       #2
        def inner(*args,**kwargs):          #4
            start=time.time()                #5
            re =func2(*args,**kwargs)        #7
            print(time.time()-start)         #8
            return re                        #11
        return inner                         #12
    @timer              #--func2=timer(func2) #3
    def func2(a):
        print('in func2 and get a:%s'%(a))    #9
        return 'func2 over'                   #10
    func2()                                       #6

    四:开放闭封原则。

             1:对扩展开放

                        允许代码扩展,添加新功能。

             2:对修改封闭

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

                         装饰器完美遵循开放闭封原则。

    五:带参数的装饰器。

                

    # 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('')

    六;多个装饰器装饰同一函数。

         

    ef wrapp1(func):
        def inner():
            print('----------')
            func()
        return inner
    def wrapp2(func):
        def inner():
            print('-------')
            func()
        return inner()
    
    def func():
        print('------')
    func()

           作业:

    编写装饰器,为多个函数加上认证的功能(用户的账号密码来源于文件),
    要求登录成功一次,后续的函数都无需再输入用户名和密码
    注意:从文件中读出字符串形式的字典,
    可以用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']:
                ret = func(*args, **kwargs)  # index/home
                return ret
            else:
                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')
                    auth_status['user'] = username
                    auth_status['status'] = True
                    ret = func(*args,**kwargs)  #index/home
                    return ret
                else:
                    print('login failed')
        return inner
    
    @auth
    def index():
        print("欢迎来到首页")
    
    @auth
    def home():
        print("欢迎回家")
    
    index()
    index()
    home()
    index()
    '''
    进阶作业(选做):
    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'))
    print(get('http://www.cnblogs.com/linhaifeng'))
    print(get('http://www.cnblogs.com/linhaifeng'))
    print(get('http://www.cnblogs.com/linhaifeng'))
    print(get('http://www.cnblogs.com/linhaifeng'))
  • 相关阅读:
    [WPF 自定义控件]好用的VisualTreeExtensions
    [UWP]从头开始创建并发布一个番茄钟
    [WPF 自定义控件]使用TextBlockHighlightSource强化高亮的功能,以及使用TypeConverter简化调用
    [WPF 自定义控件]排序、筛选以及高亮
    《写给大家看的设计书》,推荐给想了解设计的程序员
    [WPF 自定义控件]使用WindowChrome自定义RibbonWindow
    [书籍]通过《番茄工作法图解》复习番茄工作法
    [WPF 自定义控件]使用WindowChrome的问题
    [WPF 自定义控件]使用WindowChrome自定义Window Style
    时时监听input内容的改变
  • 原文地址:https://www.cnblogs.com/w-s-l123/p/7250721.html
Copyright © 2020-2023  润新知