python装饰器的主要用途就是在不修改源代码以及不修改调用方式的状况下给本来的代码增长新的功能。python
举个栗子:你的眼睛近视一千度,这个时候在不给你作任何改动的状况下戴个眼镜你就能够看清世界了,眼镜就是你的装饰器,这里咱们要学会怎么给“近视”的代码加一个“眼镜”。闭包
但是.... 提及来简单... 怎么实现...函数
首先写个函数this
import time #导入时间模块
def func():
time.sleep(1)
print("run the func")
func() #调用函数
run the func #运行结果
如今若是咱们想给咱们的代码加上一个统计运行时间的功能,用装饰器的方式怎么加??spa
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
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_2g=closure_1()g()6 #执行结果,打印的是closure_1内部定义的x变量,这里打印的就是局部变量,这是一个正确的闭包函数,若是打印结果是全局变量定义的x=1,那确定是哪里错了,这就不是一个闭包函数。