装饰器的概念
装饰器是 Python 的一个重要部分。简单地说:就是用于拓展原来函数功能的一种函数,目的是在不改变原函数名(或类名)的情况下,给函数增加新的功能。
这个函数的特殊之处在于它的返回值也是一个函数,这个函数是内嵌 “原” 函数的函数。
将函数作为参数传给另一个函数
def yanzheng():
return "--- 正在验证 ---"
def login(func):
print(func())
print("--- 正在登陆 ---")
login(yanzheng)
运行结果:
--- 正在验证 ---
--- 正在登陆 ---
写代码要遵循开放封闭原则,虽然在这个原则是用的面向对象开发,但是也适用于函数式编程,简单来说,它规定已经实现的功能代码不允许被修改,但可以被扩展,即:
封闭:已实现的功能代码块
开放:对扩展开发
现在你已经具备所有必需知识,接下来进一步学习什么是真正的装饰器。
你的第一个装饰器
def func_out(func):
def func_in():
print("--- 正在验证 ---")
func()
return func_in
@func_out
def login():
print("--- 正在登陆 ---")
login()
运行结果:
--- 正在验证 ---
--- 正在登陆 ---
@函数名称 是 Python 的一种语法糖。简而言之,语法糖就是程序语言中提供[奇技淫巧]的一种手段和方式而已。 通过这类方式编写出来的代码,即好看又好用,好似糖一般的语法。固美其名曰:语法糖
装饰器下面正好是个函数,则默认执行:login = func_out(login)
装饰器的流程图
装饰有返回值的函数
上面的案例,被装饰的 login() 函数并没有返回值,那么接下来咱们看看有返回值的函数如何装饰。
首先,先看第一个案例:
def func_out(func):
def func_in():
print("--- 正在验证 ---")
func()
return func_in
@func_out
def login():
return "--- 正在登陆 ---"
result = login()
print(result)
运行结果:
--- 正在验证 ---
None
思考一下,为什么我调用 login() 函数,并且使用 result 变量来接收返回值,为什么结果是 None 呢?
如果想不明白,就看看第二个案例:
def func_out(func):
def func_in():
print("--- 正在验证 ---")
data = func()
return data
return func_in
@func_out
def login():
return "--- 正在登陆 ---"
result = login()
print(result)
运行结果:
--- 正在验证 ---
--- 正在登陆 ---
大家仔细观察代码,这两个案例有哪些不同?
发现了吗?我在 func_in() 函数的里面多写了两句代码:
1、当我们调用被装饰的 login() 函数时,实际执行的是 func_in() 函数的代码,此时会调用 print() 函数打印 "--- 正在验证 ---"。郑州人流医院 http://rl.zyfuke.com/
2、代码执行到 data = func() 时,会先执行右侧的 func() 函数,而这个函数是原始的 login() 函数,所以会 return 返回一个值,此时这个值被等号左侧的 data 变量接收。
3、代码执行到 return data,此时会将 data 值返回更上一层,而这个值被 result 变量接收。
4、最终打印 result 变量就输出了原始 login() 函数的值。
在这里最需要注意的就是 return 返回数据,只能返回一层函数,多层时,就需要在上层同时使用 return。
装饰有参数的函数
demo1:
def func_out(func):
def func_in():
func()
return func_in
def login(a):
prin
print(a)
login(10)
运行结果:
10
demo2:
def func_out(func):
def func_in():
func()
return func_in
@func_out
def login(a):
print(a)
login(10)
运行结果:
TypeError: func_in() takes 0 positional arguments but 1 was given
类型错误:func_in()接受0个位置参数,但给出了1个
demo3:
def func_out(func):
def func_in(data):
func(data)
return func_in
@func_out
def login(a):
print(a)
login(10)
运行结果:
10
demo4:
def func_out(func):
def func_in(*args,**kwargs):
func(*args,**kwargs)
return func_in
@func_out
def login(*args,**kwargs):
print(args)
print(kwargs)
login(10,20,c=1,b=2)
运行结果:
(10, 20)
{'c': 1, 'b': 2}
总结
装饰器函数只有一个参数就是被装饰的函数的引用
装饰器能够将一个函数的功能在不修改代码的情况下进行扩展
在函数定义的上方@装饰器函数名 即可直接使用装饰器对下面的函数进行装饰