• python笔记之装饰器


    装饰器

    装饰器的本质:一个闭包函数
    装饰器的功能:在不修改原函数及其调用方式的情况下对原函数功能进行扩展
    装饰器的原则:开放封闭原则, 对扩展是开放的,对修改是封闭的

    装饰器的固定格式

    普通版

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

    wrapers版

    from functools import wraps
    
    def deco(func):
        @wraps(func) #加在最内层函数正上方
        def wrapper(*args,kwargs):
            return func(*args,kwargs)
        return wrapper

    装饰器的形成过程

    import time
    
    
    def func1(func):  #装饰器函数
        def inner():
            start = time.time()
            time.sleep(2)
            ret = func() #被装饰的函数
            end = time.time()
            print(end - start)
            return ret
        return inner
    
    
    @func1  #语法糖 @装饰器函数名
    def func2():  #被装饰的函数
        time.sleep(3)
        print("nihao")
    
    
    func2()

    完善一下上面那个装饰器

    from functools import wraps
    
    
    def demo(func):
        @wraps(func)
        def wrapper(*args, kwargs):
            return func(*args, kwargs)
        return wrapper
    
    
    @demo
    def index():
        '''
        小姐姐,我想你了!
        '''
        print("hello,world")
    
    
    print(index.__doc__)
    print(index.__name__)
    装饰器完善

    带参数的装饰器

    def outer(flag):
        def func1(func):
            def inner(*args, kwargs):
                if flag:
                    print('''执行函数之前要做的''')
                ret = func(*args, kwargs)
                if flag:
                    print('''执行函数之后要做的''')
                return ret
            return inner
        return func1
    
    
    @outer(False)
    def func2():
        time.sleep(3)
        print("nihao")
    
    
    func2()
    带参数的装饰器

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

    def wrapper1(func):
        def inner():
            print('wrapper1 ,before func')
            func()
            print('wrapper1 ,after func')
        return inner
    
    def wrapper2(func):
        def inner():
            print('wrapper2 ,before func')
            func()
            print('wrapper2 ,after func')
        return inner
    
    @wrapper2
    @wrapper1
    def f():
        print('in f')
    
    f()
    多个装饰器装饰同一个函数

    装饰器函数

    装饰器函数—— 装饰器一定是闭包函数 装饰器的作用 : 在不改变原来函数的调用方式的情况下 在这个函数的前后添加新的功能 完美的符合了一个开发原则 :开放封闭原则 对扩展是开发的 对修改是封闭的 基础的装饰器

    from functools import wraps
    
    
    def wrapper(func):
        @wraps(func)
        def inner(*args, kwargs):
            '''在函数被调用之前添加的代码'''
            ret = func(*args, kwargs)   # func是被装饰的函数 在这里被调用
            '''在函数被调用之后添加的代码'''
            return ret
        return inner
        # 使用 —— @wrapper
    
    
    @wrapper
    def func():  # inner
        pass
    
    
    func.__name__
    View Code

    带参数的装饰器

    @wrapper -- > @warapper(argument)
    三层嵌套函数
    def outer(形参):
        def wrapper(func):
            def inner(*args,kwargs):
                '''在函数被调用之前添加的代码'''
                ret = func(*args,kwargs)   # func是被装饰的函数 在这里被调用
                '''在函数被调用之后添加的代码'''
                return ret
            return inner
        return wrapper
    @outer(True)
    def func():
        pass
    View Code

    多个装饰器装饰一个函数

    def wrapper1(func):
            @wraps(func)
            def inner(*args,kwargs):
                print('before 1')
                print('')
                ret = func(*args,kwargs)   # func是被装饰的函数 在这里被调用
                '''在函数被调用之后添加的代码'''
                return ret
    def wrapper2(func):
        @wraps(func)
        def inner(*args,kwargs):
            print('before 2')
            ret = func(*args,kwargs)   # func是被装饰的函数 在这里被调用
            '''在函数被调用之后添加的代码'''
            return ret
    @wrapper1
    @wrapper2
    def func():
        print('111')
    View Code

    装饰器进阶

    functools.wraps

    from functools import wraps
    
    
    def wrapper(func):
        @wraps(func)
        def inner(*args, kwargs):
            print("在被装饰的函数执行之前做的事情")
            ret = func(*args, kwargs)
            print("再被装饰的函数执行之后做的事情")
            return ret
        return inner
    
    
    @wrapper
    def holiday(day):
        '''
        这是一个放假通知
        '''
        print("全体放假%s天" % day)
        return "好开心"
    
    
    print(holiday.__name__)
    print(holiday.__doc__)
    ret = holiday(3)
    print(ret)
    View Code

    带参数的装饰器

    import time
    FLAGE = False
    def timmer_out(flag):
        def timmer(func):
            def inner(*args,kwargs):
                if flag:
                    start = time.time()
                    ret = func(*args,kwargs)
                    end = time.time()
                    print(end-start)
                    return ret
                else:
                    ret = func(*args, kwargs)
                    return ret
            return inner
        return timmer
    # timmer = timmer_out(FLAGE)
    @timmer_out(FLAGE)    #wahaha = timmer(wahaha)
    def wahaha():
        time.sleep(0.1)
        print('wahahahahahaha')
    
    @timmer_out(FLAGE)
    def erguotou():
        time.sleep(0.1)
        print('erguotoutoutou')
    
    wahaha()
    erguotou()
    View Code

    多个装饰器装饰一个函数

    def wrapper1(func):
        def inner1():
            print('wrapper1 ,before func')
            ret = func()
            print('wrapper1 ,after func')
            return ret
        return inner1
    
    def wrapper2(func):
        def inner2():
            print('wrapper2 ,before func')
            ret = func()
            print('wrapper2 ,after func')
            return ret
        return inner2
    
    def wrapper3(func):
        def inner3():
            print('wrapper3 ,before func')
            ret = func()
            print('wrapper3 ,after func')
            return ret
        return inner3
    
    @wrapper3
    @wrapper2
    @wrapper1
    def f():
        print('in f')
        return '哈哈哈'
    
    print(f())
    View Code

    装饰器小练习

    def wrapper(func): #qqxing
        def inner(*args, kwargs):
            ret = func(*args, kwargs) #被装饰的函数
            return ret
        return inner
    
    
    @wrapper  #qqxing = wrapper(qqxing)
    def qqxing():
        print(123)
    
    
    qqxing()
    View Code
    def qqxing():
        '''
        ni hao ,Bye
        '''
        print("哈哈哈!")
    
    
    print(qqxing.__name__) #查看字符串格式的函数名
    print(qqxing.__doc__)  #查看document
    qqxing()
    View Code
    def wrapper(func):
        def inner(*args,kwargs):
            print('在被装饰的函数执行之前做的事')
            ret = func(*args,kwargs)
            print('在被装饰的函数执行之后做的事')
            return ret
        return inner
    
    @wrapper   #holiday = wrapper(holiday)
    def holiday(day):
        print('全体放假%s天'%day)
        return '好开心'
    
    ret = holiday(3)
    print(ret)
    View Code
    def outer(*args):
        print(args)
        print(*args)
        def inner(*args):
            print('inner : ',args)
        inner(*args)
    
    
    outer(1,2,3,4)   #==outer(*[1,2,3,4])  #==outer(*(1,2,3,4))
    View Code

    装饰器作业

    1.编写装饰器,为多个函数加上认证的功能(用户的账号密码来源于文件),要求登录成功一次,后续的函数都无需再输入用户名和密码

    FLAG = False
    def login(func):
        def inner(*args,kwargs):
            global FLAG
            '''登录程序'''
            if FLAG:
                ret = func(*args, kwargs)  # func是被装饰的函数
                return ret
            else:
                username = input('username : ')
                password = input('password : ')
                if username == 'boss_gold' and password == '22222':
                    FLAG = True
                    ret = func(*args,kwargs)      #func是被装饰的函数
                    return ret
                else:
                    print('登录失败')
        return inner
    
    @login
    def shoplist_add():
        print('增加一件物品')
    
    @login
    def shoplist_del():
        print('删除一件物品')
    
    shoplist_add()
    shoplist_del()
    View Code

    2.编写装饰器,为多个函数加上记录调用功能,要求每次调用函数都将被调用的函数名称写入文件

    def log(func):
        def inner(*args,kwargs):
            with open('log','a',encoding='utf-8') as f:
                f.write(func.__name__+'
    ')
            ret = func(*args,kwargs)
            return ret
        return inner
    
    @log
    def shoplist_add():
        print('增加一件物品')
    
    @log
    def shoplist_del():
        print('删除一件物品')
    
    shoplist_add()
    shoplist_del()
    shoplist_del()
    shoplist_del()
    shoplist_del()
    shoplist_del()
    View Code

    1.编写下载网页内容的函数,要求功能是:用户传入一个url,函数返回下载页面的结果 2.为题目1编写装饰器,实现缓存网页内容的功能: 具体:实现下载的页面存放于文件中,如果文件内有值(文件大小不为0),就优先从文件中读取网页内容,否则,就去下载,然后存到文件中

    import os 
    from urllib.request import urlopen
    def cache(func):
        def inner(*args,kwargs):
            if os.path.getsize('web_cache'):
                with open('web_cache','rb') as f:
                    return f.read()
            ret = func(*args,kwargs)  #get()
            with open('web_cache','wb') as f:
                f.write(b'*'+ret)
            return ret
        return inner
    
    @cache
    def get(url):
        code = urlopen(url).read()
        return code
    
    
    # {'网址':"文件名"}
    ret = get('http://www.baidu.com')
    print(ret)
    ret = get('http://www.baidu.com')
    print(ret)
    ret = get('http://www.baidu.com')
    print(ret)
    View Code
  • 相关阅读:
    [数据结构] N皇后问题
    [2011山东ACM省赛] Sequence (动态规划)
    yaf 学习
    nginx 配置文件
    nginx.conf 理解
    fastcgi
    Nginx+FastCGI运行原理
    ssh-key 原理
    Git是个啥 ssh是个啥
    Git SSH Key 生成步骤
  • 原文地址:https://www.cnblogs.com/zhangcheng94/p/12182550.html
Copyright © 2020-2023  润新知