装饰器:
    1.装饰器定义:在不改变函数的内容和调用的前提下,对函数进行功能扩展

    2.装饰器本质就是闭包,通过闭包来实现

    3.闭包实现功能扩展分析步骤
        """这是闭包实现功能扩展"""
        #
        # def task(func):
        #     def inner():
        #         print("我是扩展的功能---")
        #         func()
        #     return inner
        #
        # def f1():
        #     print("我是基础代码----")
        #
        # f1 = task(f1)
        # f1()

        """闭包实现功能扩展分析步骤
        1.函数从上到下执行,先定义task函数,再定义f1函数
        2.执行f1=task(f1):先算等号右边,task(f1):调用task函数,把f1赋值给func,即func指向基础函数的代码块;等号左边:把执行完task(func)的返回再给f1重新赋值,f1指向了内部函数的代码空间
        3.执行f1(),也就是调用内部的inner函数
        """
    4.装饰器执行过程分析
        def task(func):
            def inner():
                print("我是扩展的功能---")
                func()
            return inner

        @task#这一句就相当于f1 = task(f1)
        def f1():
            print("我是基础代码----")

        f1()

        """装饰器执行过程分析:
        1.函数从上到下执行,先定义task函数
        2.执行@task#这一句就相当于f1 = task(f1),这里尚未定义f1函数,即等待f1被装饰函数
        3.定义f1()即被装饰函数
        4.执行@task #这一句就相当于f1 = task(f1):先算等号右边,task(f1):调用task函数,把f1赋值给func
            ,即func指向基础函数的代码块;
            等号左边:把执行完task(func)的返回再给f1重新赋值,f1指向了内部函数的代码空间
        5.执行f1(),也就是调用内部的inner函数

        """

    5.装饰器装饰不同类型的函数:
        """
        装饰器装饰不同类型的函数
            a>装饰器装饰的函数没有参数,没有返回值
            b>装饰器装饰的函数有参数,没有返回值
            c>装饰器装饰的函数没参数,有返回值
            d>装饰器装饰的函数有参数,有返回值
        """



        #a>装饰器装饰的函数没有参数,没有返回值
        def w1(func):
            def inner():
                print("我是扩展的函数..")
                func()
            return inner
        @w1
        def f1():
            print("我是基础函数....")
        f1()


        #b>装饰器装饰的函数有参数,没有返回值
        def w1(func):
            def inner(num):
                print("我是扩展的函数..")
                func(num)
            return inner
        @w1
        def f1(num):
            print("我是基础函数....",num)
        f1(1)



        #c>装饰器装饰的函数没参数,有返回值
        def w1(func):
            def inner():
                print("我是扩展的函数..")
                # result = func()
                # return result
                return func()#简化代码,跟上面两句一样
            return inner
        @w1
        def f1():
            print("我是基础函数....")
            return "123456"
        s = f1()
        print(s)



        #d>装饰器装饰的函数有参数,有返回值
        def w1(func):
            def inner(num):
                print("我是扩展的函数..")
                # result = func()
                # return result
                return func(num)#简化代码,跟上面两句一样
            return inner
        @w1
        def f1(num):
            print("我是基础函数....")
            return num
        s = f1(231)
        print(s)

    6.多个装饰器装饰一个函数的执行顺序:
        """
        多个装饰器装饰一个函数的执行顺序:
            1.装饰的顺序:由里到外,先装饰w2,再到w1
            2.执行顺序:由外到里,从上到下依次执行

        """
        def w1(func):
            print(  "我是w1")
            def inner():
                print("我是扩展的功能模块1")
                func()
            return inner
        def w2(func):
            print("我是w2")
            def inner():
                print("我是扩展的功能模块2")
                func()
            return inner

        @w1
        @w2
        def f1():
            print("我是被装饰的函数")
        f1()   

    7.万能装饰器:
        """
        1.装饰器定义:
            在不改变函数的内容和调用的前提下,对函数进行功能扩展
        2.万能装饰器
            可以接收多个或着一个也不接收的 可以有返回值也可以没有返回值
        """
        #万能装饰器
        def w1(func):
            def inner(*args,**kwargs):
                print("我是扩展的功能")
                return  func(*args,**kwargs)
            return inner
        @w1
        def f1(*args,**kwargs):
            print("我是被装饰的函数...")
            print(args)
            print(kwargs)
            return "11111"
        s= f1(2)
        print(s)  

    8.类装饰

        """
        通过定义类的方式实现装饰器
            装饰器定义: 在不改函数的内容和调用的前提下,对函数进行功能拓展
        """
        class Foo(object):
            def __init__(self,func):
                self.func = func
            def __call__(self, *args, **kwargs):
                print("我是扩展的功能")
                self.func()

        @Foo#这一句等于pay=Foo(pay) pay指向的是实例对象
        def pay():
            print("我是被装饰的函数")
        #这里的pay是实例对象,如果加了括号来调用,则需要在类中添加__call__魔法方法
        #所以在这里将要扩展的功能放到这
        pay()  

    9.带有参数的装饰器对函数进行装饰:
        """
        带参数的装饰器对函数进行装饰
        装饰器的定义:在不改变函数的内容和调用的前提下,对函数进行功能扩展
        需求: 希望再装饰函数时额外传一个参数flag:
             flag==1: 执行装饰的功能.执行身份验证
             flag==0: 不执行装饰的功能,不执行身份验证
          小结: 通过装饰器工厂实现对装饰器传递额外的参数
        """

        def outer(flag):
            def task(func):
                def inner():
                    if flag == 1:
                        print("我是扩展的功能---")
                    func()
                return inner
            return task
        # 这里在装饰器的外部再套了一个函数,同时也返回了task这个函数,
        # 也就相当于@outer=@task,最终还是装饰器@task
        @outer(0)  # 表示手动调用函数 @outer(1)=@task
        # @task  pay=task(pay)
        def f1():
            print("我是基础代码----")
        f1()  

    10.装饰器的总结:
        1.装饰器函数只有一个参数,该参数就是被装饰的函数的引用
        2.装饰器能够将一个函数的功能在不修改代码的情况下进行扩展
        3.在函数定义的上方@装饰器的函数名 即可直接使用装饰器对下面的函数进行装饰
        4.装饰器的应用场景;
            1.引入日志
            2.函数执行时间的统计
            3.执行函数前预备处理
            4.执行函数后的清理功能
            5.权限校验等场景
            6.缓存