为什么装饰器函数里面要这么多层???
def use_logging(level):
def decorator(func):
def wrapper(*args, **kwargs):
if level == "warn":
logging.warn("%s is running" % func.__name__)
return func(*args)
return wrapper
return decorator
@use_logging(level="warn")
def foo(name='foo'):
print("i am %s" % name)
foo()
一层一层剖析:
1、首先基本函数调用:
def demo():
print("this is demo")
a = demo
a = demo()
上文代码两个都正常运行,只是下面一行运行后会直接出结果,并且print(a)返回的值是None。
这里就体现一个观点,函数的调用问题要注意后面带括号和不带括号的区别
2、两层函数的调用:
def demo1():
def demo():
print("this is demo")
a = demo1
a = demo1()
思考一下内部嵌套的demo函数是否有意义
答案:毫无意义,函数内部的函数只能内部调用,跟局部变量是一样的
python中函数不调用,它永远只是个占用内存的文字,不是程序
def demo1():
def demo():
print("this is demo")
return demo
a = demo
a = demo()
不加括号就是函数的引用,引用在python中就可以理解为函数多加了个名字
加括号就表示调用,就是从头到尾的执行一遍,如果有return,返回来什么,上文中的a变量就是什么
所以可以分析出第一个a变量就是demo1函数,第二个a变量是demo函数
def demo1():
def demo():
print("this is demo")
return demo
a = demo
a = demo()
python装饰器一定是接受函数,返回的必须是函数!!(所以函数嵌套至少是两层)理解!
def my_decorator(func):
def warpper(*args, **kwargs):
print('wrapper of decorator',func)
func()
return warpper
@my_decorator
def demo():
print("this is a demo")
demo()
3、三层函数是因为什么?(装饰器自带参数,更加灵活)
考虑一个问题,如果迭代器函数自己要有个参数,怎么在两层中加?
当然我们自己写的话很简单!
def my_decorator(param,func):
def warpper(*args, **kwargs):
print('wrapper of decorator',func)
func()
return warpper
def demo():
print("this is a demo")
demo = my_decorator("haha",demo)
demo()
但是!!
你用不了语法糖!!不知道看我上一篇啥子是语法糖
python装饰器特意采用了语法糖的结构来简化使用流程
demo = my_decorator("haha",demo)
这句话就不用自己写,所以因为要用语法糖@,所以就不能按照我们自定义的格式来写,得遵守他们的规矩!
我总结一下:三层迭代器自身参数->函数名->函数参数
现在对比一下下文代码与最开始代码的区别:
def my_decorator(level):
def add(func):
def wrapper():
print('wrapper of decorator', level)
func()
return wrapper
return add
def greet():
print('hello world')
decorated_greet = my_decorator("warn")(greet)
decorated_greet()
你就知道语法糖是什么作用了,他干了什么!