一,函数知识点回顾
def func(): pass print(func) #函数名对应内存地址 a = func #可以赋值给变量 a() def func2(arg): #可以做参数 arg() func2(func) def func3(): #可以做返回值 def fun4(): pass return func4 lis = [func,func2,func3,func4] #可以做容器对象的元素 for i in lis: i()
二,闭包
定义:如果一个内层函数包含了对外层函数变量的引用,那这个内层函数就是闭包
def wrapper(name): def inner(): print(name) #相当内层函数的空间里保留了name变量的引用并且指向当初传入的实参 return inner ret = wrapper('123') #当函数执行时,Python解释器会开辟一块内存(局部名称空间)来储存这个函数里面的内容,这个时候,Python解释器才关注函数里面变量名和值之间对应的关系,包括内层函数内的内容 del wrapper ret() # 指向inner的内存地址 wrapper('123') #报错:NameError: name 'wrapper' is not defined
#灵魂三问1 def func1(): num = 100 def func2(arg): print(arg) func2(num) #通过传参的方式,向内层函数传递数据 func1() #灵魂三问2 def func1(): num = 100 def func2() print(num) #内层函数的作用域里没有num,会自动往外层函数的作用域去找 func2() func1() #灵魂三问3 def func1(num): def func2(): print(num) #内层函数的作用域路没有num,会自动往外层函数的作用域去找 func2() func1()
#内层函数+其外层函数变量的引用 def func1(name): def func2(): print(name) return func2 ret = func1('alex') ret() #非闭包 def func1(): def func2(): def func3(): def func4(): pass return func4 return func3 return func2 ret1 = func1() #func2 ret2 = ret1() #func3 ret3 = ret2() #func4 ret3()
三,装饰器初识
#装饰器的定义:
既不想直接修改原来的函数,也不想修改函数的调用方式,还要加新功能的时候,可以使用装饰器 def wrapper(func): def inner(*args,**kwargs): print('新功能') func(*args,**kwargs) return inner
#global_func = wrapper(global_func) 内层的inner函数,引用了func,func -指向-> global_func
@wrapper #相当于把被装饰的函数当成参数传给a,然后把返回值再赋值给被装饰的函数名
def global_func(): pass
global_func() #相当于调用了内层函数inner
四,装饰器进阶
1.装饰带参数的函数
# 装饰带参数的函数 def wrapper(func): def inner(*args, **kwargs): # 实际执行函数的参数 print('开始') r = func(*args, **kwargs) print(r) print('结束') return r return inner @wrapper def my_sum(x, y): print('我是my_sum函数') return x + y ret = my_sum(10, 20) # inner(10, 20) print(ret)
2.装饰带返回值的函数
# 装饰带返回值的函数 def wrapper(func): def inner(): print('开始') r = func() # 拿到原来函数的返回值 print('结束') return r return inner @wrapper def f1(): print('我是f1') return 100 ret = f1() #实际上是执行了inner内层函数,如果inner内层没用renturn返回值,则f1也没用返回值
3.带参数的装饰器 *****
def mougehanshu(arg): def wrapper(func): def inner(*args, **kwargs): print('欢迎VIP用户进入{}专栏!'.format(arg)) func(*args, **kwargs) return inner return wrapper # wrapper = mougehanshu() #@mougehans(参数) 相当于 @wrapper @mougehanshu('电影') # 相当于mougehanshu()执行后返回wrapper def movie(): print('这是电影专栏!') @mougehanshu('体育') # @wrapper def sport(): print('这是体育专栏!')
4.多个装饰器装饰同一个函数 *****
def foo1(func): print("d1") def inner1(): print("inner1") return "<i>{}</i>".format(func()) return inner1 def foo2(func): print("d2") def inner2(): print("inner2") return "<b>{}</b>".format(func()) return inner2 @foo1 #f1 = foo1(foo2(f1))=foo1(inner2,打印d2) = inner1 打印'd1' @foo2 #执行foo2(f1) =inner2 打印'd2' def f1(): return "我是f1" ret = f1() print(ret) # f1 = foo2(f1) --> inner2 # f1 = foo1(inner2) --> inner1 ↓↓ #执行流程分析: #f1() == inner1()->打印'inner1'->return "<i>{}</i>".format(inner2()) #inner2() -> 打印'inner2'->return "<b>{}</b>".format(f1()) #f1() -> return "我是f1" ↓↓ print(ret) ---> '<i><b>我是f1</b></i>'
5.装饰器修复技术 ****
# 装饰器修复技术 from functools import wraps # Flask框架的时候用得上 def wrapper(func): @wraps(func) def inner(*args, **kwargs): print('这是新功能') func(*args, **kwargs) return inner @wrapper def f1(arg1, arg2): """ 这里写这个函数是做什么的 :param arg1: 这个参数是什么类型的 :param arg2: 这个参数是什么类型 :return: None """ print('嘿嘿嘿') print(f1.__doc__) print(f1.__name__) #若不修复的话,f1实际是指向inner的内存空间, #f1.__doc__ 相当于 inner.__doc__中的内容 #f1.__name__ 相当于 inner.__name__中的内容
五,装饰器究极进阶
1.类装饰器
2.装饰类