装饰器———就是名称空间与作用域和闭包函数的综合运用。
名称空间分为:内置名称空间,示例: print、input等这些内置函数属于内置名称
全局名称空间,示例: x=1,变量名在函数定义中或函数外的就是全局名称。
局部名称空间,示例: f=666,在函数定义里面的,嵌套在函数内的事局部名称
名称查找顺序是由局部==》全局==》内置
闭包函数:就是你调用了一个函数A,这个函数A返回了一个函数B给你。这个返回的函数B就叫做闭包.
1、装饰器定义:修饰别人的工具,修饰添加功能,工具指的是函数,装饰器可以运用于各种函数对象。简单的来说就是一个人经过某个空间(函数)穿了一件新衣服,变帅了。本质还是一个普通的人,只是被装饰了
2、装饰器分为:无参装饰器(常用)和有参装饰器,本质区别就是无参装饰器只有两层函数嵌套,而有参装饰器有三层或者是多个变量名需要定义。
基于以上对名称空间和闭包函数以及装饰器概念的了解,接下来做一个示例来分析:
一般的简单函数:
def func():
f=666
func()
当我有需求需要在给一个函数里面的体代码(f=666),添加一个新功能且不更改源代码和原本的调用方式,这时就需要用带装饰器,如我需要给其添加一个验证功能如示例:
def func():
name=input('请输入你的账号====>')
pwd=input('请输入你的密码====>')
if name == 'yeqing' and pwd =='123':
print('登录成功,开始装饰')
f=666
return f
else:
print('账号密码错误')
func()
#因为需要让f=666 不固定死,由此将f=666,改为f=ff(*args,**kwargs),又因为需要得要ff的赋值,所以用到了闭包.
#最终需要返回原来的值,所以用到return。
def out(ff):
def func(*args,**kwargs):
name=input('请输入你的账号====>')
pwd=input('请输入你的密码====>')
if name == 'yeqing' and pwd =='123':
print('登录成功,开始装饰')
f=ff(*args,**kwargs)
return f
else:
print('账号密码错误')
return func
#此时我需要装饰一下(x,y),验证成功后开始装饰,装饰成功后打印牛逼
def index(x,y):
print('牛逼的 %s %s' %(x,y))
def out(ff): #全局名称的作用域
def func(*args,**kwargs):
name=input('请输入你的账号====>') #内置名称的作用域
pwd=input('请输入你的密码====>')
if name == 'yeqing' and pwd =='123':
print('登录成功,开始装饰')
f=ff(*args,**kwargs) #局部名称的作用域
return f
else:
print('账号密码错误')
return func
index=out(index)
res=index(1,2)
print(res)
#由此得到得到一个装饰后的牛逼,既没有更改原来定义的(x,y),也没改调用方式,从而得到装饰后的牛逼的1和2
这就是无参装饰器。
有参装饰器:和无参装饰器原理一样,但是在某些特定的场景我们函数体内需要定义多种值,这是因为函数体内条件增加了,需要多一个或多个变量值进行传参。由此需要有参装饰器,如函数体内新增了db_type的条件判断示例:
def index(x,y):
print('牛逼的 %s %s' %(x,y))
def out(ff,dbtype): #全局名称的作用域
def func(*args,**kwargs):
if dbtype =='file':
print('基于文件格式')
name=input('请输入你的账号====>') #内置名称的作用域
pwd=input('请输入你的密码====>')
if name == 'yeqing' and pwd =='123':
print('登录成功,开始装饰')
f=ff(*args,**kwargs) #局部名称的作用域
return f
else:
print('账号密码错误')
else:
print('格式不对')
return func
index=out(index,'file')
index(1,2)
#由此得到一个基于文件格式打开的一个装饰后的牛逼,既没有更改原来定义的(x,y),也没改调用方式,从而得到装饰后的牛逼的1和2
明天将对装饰器进行优化和简单化,将引用语法糖,重新改造上面的示例