再讲装饰器之前先说一下函数,首先看下面的例子(只适合初学者阅读):
def func():
pass
print('in func')
#可以把函数内存地址赋值给另一个对象,导致另一个对象也指向了函数代码
f=func
f()
输出的结果为:in func
结果说明可以把内存地址传给别的对象
def func():
print('in func')
def func_in():
print('in func_in')
func()
结果为 in func
此时内函数的in func_in并没有输出说明内函数并没有执行,此时可以得要只有函数名+()才能调用函数 所以 func_in 并没有被调用的结论
那么什么是闭包呢?
闭包就是函数的返回值是另一个函数的名称。
举例:
def func():
print('in func')
def func_in():
print('in func_in')
return func_in
f = func()
结果为:in func
此时函数func_in也并没有调用所以不输出结果in func_in,那如果想要in func_in该如何做,看下面的例子:
def func():
print('in func')
def func_in():
print('in func_in')
return func_in
f = func()
print(f)
f()
结果为:
in func
<function func.<locals>.func_in at 0x00000216C65AAA60>
in func_in
在上面例子的基础上输出f函数即可,咱们打印了一下f,此时可以看到在未调用的时候打印的结果是f函数的内存地址。只有真正调用了函数名+()才能执行, 只有函数名的话只有地址
在看函数的最后一个案例:
def func(number1): #外部函数
print('in func')
def func_in(number2): #内部函数
print('in func_in %d'%(number1 + number2))
return func_in
f = func(99)
f(1001)
输出结果为:
in func
in func_in 1100
此结果可以说明内部函数可以直接调用外部函数的变量
接下来说一下装饰器是如何实现的,实现装饰器的方法有闭包、类。接下来咱们主要讲闭包是如何实现装饰器的
#闭包小案例
def ToSomeBody(name):
#外部函数作用:创建内部函数,并未内部函数提供相应的运行环境
pass
def say(data):
#内部函数
print("对%s 说%s"%(name,data))
return say
zhangsan = ToSomeBody('张三')
zhangsan('今晚吃鸡')
此时会得到结果:
对张三 说今晚吃鸡
正如上面的结论:内部函数可以调用外部函数的变量,而ToSomeBody(‘张三’)返回的结果是say函数,所以函数名+()就会执行函数返回结果。
def ToSomeBody(name):
def say(data):
print("对%s 说%s"%(name,data))
return say
# zhangsan = ToSomeBody('张三')
# zhangsan('今晚吃鸡')
print(ToSomeBody('234'))
print(ToSomeBody('234')('56789'))
结果为:
<function ToSomeBody.<locals>.say at 0x0000029FF4DFAA60>
对234 说56789
None
此时可以得到什么结论呢?
正如上面的结论直接打印ToSomeBody(‘234’)返回的是say函数,直接打印一个函数会返回这个函数的内存地址,而ToSomeBody(‘234’)(‘56789’)在这个函数的基础上+()就会调用,那最后的None是为什么呢,因为say函数没有返回值,不像ToSomeBody函数有返回值say函数, say函数没有返回值只能返回一个None。
什么是装饰器
就是给已有函数增加额外功能的函数,它本质上就是一个闭包函数。
装饰器的功能特点:
- 不修改已有函数的源代码
- 不修改已有函数的调用方式
- 给已有函数增加额外的功能
可以这样说:再不改变源函数的情况下增加新的功能
接下来看一下装饰器是如何编写的
def check(func): #装饰器函数
def inner():
print('请及时登录系统,在查询数据')
func()
return inner
@check
def select_user_info(): #被装饰的函数
print('正在查询用户信息')
if __name__ == '__main__':
select_user_info()
输出结果为
请及时登录系统,在查询数据
正在查询用户信息
此时我们可以看到,装饰器函数是check,被装饰的函数是select_user_info,在被装饰的函数头上加@装饰器函数的名称就可以了,这种写法叫做语法糖,语法糖的书写格式是: @装饰器名字
接下来看一下不用语法糖该如何书写
def check(func):
def inner():
print('请及时登录系统,在查询数据')
func()
return inner
def select_user_info():
print('正在查询用户信息')
if __name__ == '__main__':
select_user_info = check(select_user_info)
select_user_info()
输出结果为
请及时登录系统,在查询数据
正在查询用户信息
此时可以得出结果:@check == select_user_info = check(select_user_info)
本次装饰器的讲解就到这里,装饰器进阶将放到下次内容