python 装饰器
Posted 九月
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python 装饰器相关的知识,希望对你有一定的参考价值。
python装饰器的主要用途就是在不修改源代码以及不修改调用方式的情况下给原本的代码增加新的功能。
举个栗子:你的眼睛近视一千度,这个时候在不给你做任何改动的情况下戴个眼镜你就可以看清世界了,眼镜就是你的装饰器,这里我们要学会怎么给“近视”的代码加一个“眼镜”。
可是.... 说起来简单... 怎么实现...
首先写个函数
import time #导入时间模块
def func():
time.sleep(1)
print("run the func")
func() #调用函数
run the func #运行结果
无参函数
现在如果我们想给我们的代码加上一个统计运行时间的功能,用装饰器的方式怎么加??
import time
def f1(parameter): #2
def f2(*args,**kwargs): #3
start_time=time.time()
parameter(*args,**kwargs)
stop_time=time.time()
print("the func run time is %s" %(stop_time-start_time))
return f2
@f1 #1
def func(): #源代码并没有变
time.sleep(1)
print("run the func")
func()
run the func #执行结果
the func run time is 1.0000569820404053
#1: @f1 为装饰器的默认语法,,装饰器传的参数是正下方函数的名字,调用结果在重新赋值给下面的函数名字,实际上这句的意思就是 func=f1(func),赋值之后实际上只是一个内存地址,所以调用的时候要加()运行,也就是func()。
#2: 装饰器是利用嵌套函数+闭包函数的方式实现,在这里f1(parameter) 中parameter在这里实际上传的参数就是func,而这个f1函数的代码仅仅就是定义了一个f2函数以及return f2的内存地址,so实际上f1 就是f2,只不过在f2 里面引用了f1传进来的参数,接下来我们看f2函数。
闭包函数下面有个简单的介绍
#3: f2(*args,**kwargs) 这里*args和**kwargs包含了所有可以传递进来的参数,在f2函数内写我们需要增加的功能,然后把对应的parameter函数(注意这里parameter实际上是func函数)放在我们需要的位置,函数前面写上时间,后面写上时间,最后用运算方式相减,就得到了我们想要的运行时间。
有参函数
可是如果我们的源代码有传值的话怎么办,上面的装饰器我们用就不够了。
再次写个需要传参的函数:
def func(x):
time.sleep(1)
print("this parameter is %s" %x)
func(1)
this parameter is 1 #运行结果
这个如果统计时间应该怎么统计??让我们把刚才无参函数的装饰器拿过来,稍微改一下。
import time
def f3(par):
def f1(parameter):
def f2(*args,**kwargs):
start_time=time.time()
parameter(*args,**kwargs)
stop_time=time.time()
print("the func run time is %s" %(stop_time-start_time))
return f2
return f1
@f3(1)
def func(x):
time.sleep(1)
print("this parameter is %s" %x)
func(1)
this parameter is 1 #运行结果
the func run time is 1.0000569820404053
可以看到 f1函数和f2函数并没有改动,只是在外面多嵌套了一层函数f3,但是装饰器的调用方式相比有点小小的区别,这里装饰器使用的时候是@f3(1),这里的这个1就是给我们的源代码传的值。这就是有参函数的使用方式,接下来我们就可以根据外面传进来的值做我们相对应的代码处理。
闭包函数:
内置变量:只有打开python 就可以用的,写入到python语言内部,定义好的变量,例如print函数我们用的时候可以直接调用。
全局变量:就是我们在py文件中顶头写的变量或者函数,比如x=1,作用域是当前py文件。
局部变量:在函数内部定义的,作用域是当前函数。
我们在使用一个变量的时候查找方式,现在局部变量找,如果没有就找全局变量,如果在没有就找内置变量,如果还没有就会给你提示错误了,首先找到哪个,就返回哪个给你调用,这也是我们设置变量的时候为什么不能用关键字定义,因为一旦定义了就会覆盖内置变量,接下来如果需要使用就会报错,
闭包函数定义:内部函数的代码,包含对外部函数的引用,但一定不是对全局作用域的引用。(说明闭包函数最起码会嵌套两层)
闭包函数例子:
x=1
def closure_1():
x=6
def closure_2():
print(x)
return closure_2
g=closure_1()
g()
6 #执行结果,打印的是closure_1内部定义的x变量,这里打印的就是局部变量,这是一个正确的闭包函数,如果打印结果是全局变量定义的x=1,那肯定是哪里错了,这就不是一个闭包函数。
以上是关于python 装饰器的主要内容,如果未能解决你的问题,请参考以下文章