# 首先介绍闭包(理解闭包是理解装饰器的前提) # 什么是闭包呢?在函数内部再定义一个函数,并且这个函数用到了外边函数的变量,那么将这个函数以及用到的一些变量称之为闭包 def test01(num): def test02(): print("num is %d" % num) return test02 ret = test01(20) ret() print("*" * 60) # 装饰器的理解 # 需求:在不更改源代码的情况下,对原来的方法添加一些验证。比如:flag==1 才执行 test01()等等 # 装饰器的应用场景: # 1、引入日志 # 2、函数执行时间统计(这个可以常用啊) # 3、执行函数前预备处理 # 4、执行函数后清理功能 # 5、权限校验等场景 # 6、缓存 # 无参数的装饰器 def test03(func): print("-----1-----") def test04(): print("-----2-----") func() return test04 # @test03 等价于下面这两句话 # test05 = test03(test05) # test05() @test03 def test05(): print("-----3-----") test05() print("*" * 60) # 注意:装饰的函数是带参函数时,返回的test07()也必须是代参函数,用来接收 # 被装饰的函数有参数 def test06(func): print("-----1-----") def test07(name, age): print("-----2-----") func(name, age) return test07 @test06 def test08(name, age): print("-----3-----") print("name is %s, %d" % (name, age)) test08("张三", 15) print("*" * 60) # 通用的装饰器函数,不论它是有参还是无参,有返回值还是无返回值,都是通用的 # args——存放元组参数,前面有一个* # kwargs——存放字典参数,前面有两个* # 补充:元组和字典的拆包:如果希望将一个元组或者字典直接传给函数,可在参数名前面加一个*或者两个* def test09(func): print("-----1-----") def test10(*args, **kwargs): print("-----2-----") ret = func(*args, **kwargs) return ret return test10 @test09 def test11(*args, **kwargs): print("-----3-----") return args, kwargs print(test11(*("腾讯", "阿里巴巴", "谷歌"), **{"张三": 15, "李四": 16, "王五": 17})) print("*" * 60) # 两个装饰器,首先看到第一个@test12,但是呢?发现下面还有一个@test14,而装饰器是用来装饰函数的,不能用来装饰@test14 # 所以要等下面的@test14装饰完了之后,@test12才能再装饰 # 两个装饰器(理解) def test12(func): print("-----1-----") def test13(): print("-----2-----") return "hello " + func() return test13 def test14(func): print("-----3-----") def test15(): print("-----4-----") return "python " + func() return test15 @test12 @test14 def test16(): print("-----5-----") return "world" print(test16()) print("*" * 60) # 1、因为装饰器带了参数,首先是直接调用timefun_arg(),返回了timefun,此时的@timefun_arg("itcast")就变成了@timefun # 2、然后才装饰foo()函数 # 3、后面的步骤如上 def test17(str="hello"): def test18(func): def test19(): print("%s" % str) return func() return test19 print(str) return test18 @test17("hello world") def test20(): print("this is python world") test20() print("*" * 60) # 类装饰器(了解) # 要想理解类装饰器,首先需要理解下面这段代码 class test21(object): def __call__(self): print('call me!') t = test21() t() # t是一个对象,又不是一个方法,怎么可以t()呢? # 原来t()会默认调用__call__(self)方法,因为类test21重写了__call__(self)方法,所以调用重写后的 print("*" * 60) # 接下来才是类装饰器(不得不说动态语言真是花里胡哨) class test22(object): def __init__(self, func): print("---初始化---") print("func name is %s" % func.__name__) self.__func = func def __call__(self): print("---装饰器中的功能---") self.__func() @test22 def test(): print("----test---") test()