Day 12
闭包函数 = 函数对象 + 函数嵌套定义 + 函数名与空间作用域
闭包函数
1、闭:指的是该函数是定义在一个函数内部的函数
2、包:指的是该函数访问了一个来自于外层函数的变量
闭包就是能够读取其他函数内部变量的函数,由于在 Python 语言中,只有函数内部的子函数才能读取局部变量,因此可以把闭包简单理解成 “定义在一个函数内部的函数”。所以,在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。
闭包的用途:
- 可以在函数外部读取函数内部成员
- 让函数内成员始终存活在内存中
装饰器
1.什么是装饰器
器:工具
装饰:为被装饰者添加额外功能
2.为何要有装饰器
一旦软件上线运行之后,就应该遵循开放封闭的原则:
1、开放是指对拓展新功能的开放封
2、封闭指的是对修改源码的封闭
定义装饰器的目的:
电话艺装饰器就是为了在遵循1和2的前提下,来为其他函数添加新的功能
ps:
不修改被装饰对象指的是定义与调用都不能修改所以下述行为都违反了开放封闭原则:
1、修改被装饰对象定义时的源代码
2、修改被装饰对象的调用方式
3、如何用装饰器
首先我们先写一个基本函数
import time
def SayHai(name):
time.sleep(0.2)
print("%s你好啊!" % name)
SayHai("孙悟空")
现在我们要给这个函数计时,我们可以这样写
# 1
start = time.time()
SayHai("孙悟空")
end = time.time()
print("该程序的运行时间为%s" % (end-start))
# 2
def SayHai(name):
start = time.time()
time.sleep(0.2)
print("%s你好啊!" % name)
end = time.time()
print("该程序运行的时间为%s" % (end-start))
# 3
def RunSH(name):
start = time.time()
time.sleep(0.2)
SayHai(name)
end = time.time()
print("该程序运行的时间为%s" % (end - start))
这两种方法都有问题,如果SayHai
的函数调用次数过多,我们需要写很多的(end-start)
,第一种十分的不方便,第二种方法虽然省了很多代码但是违背了不修改源码的原则第三种方法类似于第二种但是不灵活
我们迫切的需要一种不修改源码又能为旧函数赋值新功能的方法,于是装饰器就产生了。
def timing(func):
def wrapper(*args, **kwargs):
start = time.time()
time.sleep(0.2)
result = func(*args, **kwargs)
end = time.time()
print("该程序运行的时间为%s" % (end - start))
return result
return wrapper
sayhai = timing(SayHai)
sayhai("孙悟空")
这样一个装饰器就完成了
我们可以用更简单的方法来描述它
def timing(func):
def wrapper(*args, **kwargs):
start = time.time()
time.sleep(0.2)
result = func(*args, **kwargs)
end = time.time()
print("该程序运行的时间为%s" % (end - start))
return result
return wrapper
@timing
def SayHai(name):
time.sleep(0.2)
print("%s你好啊!" % name)
SayHai("孙悟空")
这里的 @timing
相当于sayhai = timing(SayHai)
无参装饰器
1、无参装饰器的模板
def outter(func):
def wrapper(*args,**kwargs):
res=func(*args,**kwargs)
return res
return wrapper
前面已经定义一个无参装饰器此处不再定义
2、叠加多个装饰器
2.1 加载顺序:自下而上
2.2 执行顺序:自上而下运行内层的wrapper函数
有参装饰器
有参装饰器的模板:
def outter2(x,y,z,a,b):
def outter1(func):
def wrapper(*args,**kwargs):
res=func(*args,**kwargs)
return res
return wrapper
return outter1
举个栗子
def outter(engine = 'file'):
def deco2(func2):
def wrapper2(*args,**kwargs):
inp_name = input('username>>>: ').strip()
inp_pwd = input('password>>>: ').strip()
if engine == "file":
print('基于file的认证')
if inp_name == "egon" and inp_pwd == "123":
print('login successful')
res2=func2(*args,**kwargs)
return res2
else:
print('username or password error')
elif engine == 'mysql':
print('基于mysql的认证')
elif engine == 'ldap':
print('基于ldap的认证')
else:
print('未知的engine')
return wrapper2
return deco2
@outter(engine='mysql') # @deco2 # index=deco2(index)
def index(x,y):
print('index=>',x,y)
index(1,2) # index=>wrapper
print('未知的engine')
return wrapper2
return deco2
@outter(engine=‘mysql’) # @deco2 # index=deco2(index)
def index(x,y):
print(‘index=>’,x,y)
index(1,2) # index=>wrapper