在学习python中,刚开始没重视闭包函数和装饰器,后来发现装饰器非常重要,在这重新梳理一下,也让自己再加深下印象。
一、函数闭包:
什么是闭包函数,其实就是必须满足以下三点的函数:
1,必须要有一个内嵌函数
2,嵌套函数必须引用封闭函数中的变量
3,闭包函数必须要返回内嵌函数
比如求一个y = kx +b;这种求一次函数直线上任意一个x值的y值;
传统函数定义可能如下:
def line(k,x,b):
return k*x+b
res = line(1,2,3)
print(res)
# 5
这种函数当然可是实现,但是就是输入形参太多,而且,加入一条直线固定,只需要输入一个x即可:所以可是重新定义一个闭包函数,如下:
def lineOut(k,b):
def line(x):
return k*x+b
return line
line = lineOut(1,2)
res = line(3)
print(res)
# 5
这样的话,就可以只调用line这个函数返回函数,进行直传一个参数就可以了。
二、闭包函数的用途:
1,装饰器:其中一个应用写了一个登录功能,需要统计这个功能执行花费的时间,可以使用装饰器实现;还有可以实现打印日志
2,实现面向对象,比如JavaScript中使用闭包函数实现面向对象的功能,属性办法
3,实现单利模式,单利类,一个类只有一个实例。'''
下面有这个实例是定义一个求和函数,然后用闭包函数调用,并判断条件是否满足是整型,满足条件就执行求和函数,本身求和函数代码不做任何修改,更加模块化,更方便维护和调用,耦合性降低不少,具体代码如下:
def mySum(*args):
return sum(args)
def dec(fun):
def inDec(*args):
if len(args) ==0:
return 0
for i in args:
if not isinstance(i,int):
return 0
return fun(*args)
return inDec
res = dec(mySum)
# res1 = res(1,2,3,89)
# res1 = res("99",9)
res1 = res()
print(res1)
三、装饰器:
其实上面那个求和函数已经用到了装饰器的作用,就是执行指定函数时还能执行其他操作,并不影响原函数的代码,装饰器本质就是一个函数,但是它有特殊作用,它用来装饰别的函数,给其他函数附加新的功能
特点,原则:
1,不能修改被装饰的函数的源代码
2,不能改变装饰器函数的调用方式'''
装饰器和闭包函数最大的区别是在于它的引用方式,使用"@"写在装饰器函数之前,并整体放在需要装饰的函数前面一行,这样在调用功能函数时,系统就会自动执行装饰器函数,并且执行返回的嵌套函数,说白了就是省略了之前自己手动调用返回嵌套函数的步骤,并且在嵌套函数内部,调用了功能函数。其中有几点需要强调:
1,装饰器函数必须要有形参,且传入的是函数名;
2,嵌套函数会自动执行,且会自动把功能的实参复制一份到自己的实参列表,并且在执行其他功能外,会调用功能函数;
3,装饰器给人感觉是先执行装饰器函数功能,后执行功能函数,其实不然,它是在装饰器内部及已经调用功能函数,所以调用功能函数时,其实是值执行装饰器函数,只不过是执行中会调用功能函数;(不知道大家有没有看懂。。。。。。看下面代码,自己运行,就能理解)
4,最后注意装饰器函数的返回值设计
实例一:测试函数执行顺序
def log(func):
def wrapper(*args,**kwargs):
print("begin call %s"%func.__name__)
tem = func(*args,**kwargs)
print("after call %s"%func.__name__)
return tem
return wrapper
@log
def new():
print("正在执行。。。。")
new = new()
print(new)
实例二:#定义一个装饰器,用来测试一个函数的执行时间
import os
import time
#定义一个装饰器,用来测试一个函数的执行时间
def getTime(func):
def wrapper(*args,**kwargs):
startTime = time.time()
func(*args, **kwargs)
endTime = time.time()
print("%s执行了%s秒"%(func.__name__,endTime-startTime))
return wrapper
@getTime
def f1():
print("正在执行。。。。。。。")
time.sleep(1)
f1()
实例三:高阶装饰器,其实就是闭包函数里面还是一个闭包函数,就是高阶装饰器:
def outLog(text):
def log(func):
def wrapper(*args,**kwargs):
print(text)
print("%s执行了"%func.__name__)
res = func(*args,**kwargs)
return res
return wrapper
return log
@outLog("这是打印的text")
def f3(x,y):
return x+y
res = f3(1,898)
print(res)