***********************************************************************************************************************************
在python中,函数名也是一个变量,
例如:
def fun1():
#todo
def fun2()
#todo
def fun3(b)
if b: return fun1
else :return fun2
//
fun1 = fun3(true)
#这样子,就可以将fun1替换成fun2了
当然,fun1 = fun2也行;
************************************************************************************************************************************
基于上述,假如fun1需要登录后才能使用,fun2不需要,那么,只能有如下方式:
1.在调用fun1前,执行一下login,然后在决定要不要执行fun1。(弊端:每个调用fun1的地方都得改)
2.在fun1内,插入login,决定要不要继续下去(弊端:要修改fun1,不符合编程的设计思想)
3.使用fun1 = fun3(true)将fun1在一开始替换掉,做法:
def login(fun1):
def defineExcuteFun1():#再嵌套一个函数
hasLogin = #从缓存中查看有没有登录
if hasLogin : fun1()
else : print("跳转到其他地方")
return defineExcuteFun1
#fun1作为一个参数传到login 中,然后又成为defineExcuteFun1的一部分,那么
fun1 = login(fun1) #那么fun1 就是 defineExcuteFun1
fun2 = login(fun2) #那么fun1 就是 defineExcuteFun1 ,值得注意的是,两个defineExcuteFun1,分别以原来的fun1,原来的fun2作为自己的组成部分(闭包),是不同的。
#例子:
def seeMove():
#todo
seeMove = login(seeMove)
#调用还是一样,就在里头执行defineExcuteFun1(),由里头的逻辑,决定要不要执行最初的seeMove
seeMove()
#如果seeMove是带参数才能执行的话,上面的方式中,在defineExcuteFun1()中,调用的方式是fun1(),是以不带参数的方式来调用的,那么,可以:
def login(fun1):
def defineExcuteFun1(*
args
):#再嵌套一个函数
hasLogin = #从缓存中查看有没有登录
if hasLogin : return fun1(*
args
)
else : print("跳转到其他地方")
return defineExcuteFun1
以上这种方式,叫做装饰器,类似于MVC中的action的过滤器,其实就是attribute,由可以将上面 seeMove = login(seeMove)去掉,换成:
@login
def seeMove(a,b):
#todo
这时,调用seeMove(c,d),如果在登录状态下,实质是 login(seeMove(c,d))这样。
****************************************************************************************************************************************************************
#如果还有一个需要,这个seeMove不仅仅要login,而且要规定 某个身份特征的人,才能使用,那么
def alogin(Authority):
def login(fun1):
def defineExcuteFun1(*
args
):#再嵌套一个函数
hasLogin = #从缓存中查看有没有登录
isAuthority = #读出的authority is Authority //Authority又一次作为函数的元素了
if hasLogin and isAuthority :retrun fun1(*
args
)
else : print("跳转到其他地方"
return defineExcuteFun1
return login
@alogin("超级管理员")
def seeMove(a,b):
#todo
注意:这里跟上面 seeMove = login(seeMove)不一样了,这里def alogin(Authority)如果按上面套路走,起码要fun1这个形参,这里则没有了
也就说明,fun1这个形参被省了
那么,上面,其实还是 seeMove = login(seeMove) ,alogin 则是负责将 参数带到去最内边使用而已。
猜想, @alogin("超级管理员")的 结果,可以当做是执行了一条函数,其实就是将 " @Login“返回来,给seeMove做装饰器
@alogin("xxxx") 带参 和 @login 不带参是不同的, 前者是“返回装饰器”,然后装饰,后者是“装饰器”,直接装饰
*****************************************************************************************************************************************************************
(知识补充)非固定参数
若你的函数在定义时不确定用户想传入多少个参数,就可以使用非固定参数
def
stu_register(name,age,
*
args):
# *args 会把多传入的参数变成一个元组形式
print
(name,age,args)
stu_register(
"Alex"
,
22
)
#输出
#Alex 22 () #后面这个()就是args,只是因为没传值,所以为空
stu_register(
"Jack"
,
32
,
"CN"
,
"Python"
)
#输出
# Jack 32 ('CN', 'Python')
def
stu_register(name,age,
*
args,
*
*
kwargs):
# *kwargs 会把多传入的参数变成一个dict形式
print
(name,age,args,kwargs)
stu_register(
"Alex"
,
22
)
#输出
#Alex 22 () {}#后面这个{}就是kwargs,只是因为没传值,所以为空
stu_register(
"Jack"
,
32
,
"CN"
,
"Python"
,sex
=
"Male"
,province
=
"ShanDong"
)
#输出
# Jack 32 ('CN', 'Python') {'province': 'ShanDong', 'sex': 'Male'}