学习笔记61_装饰器理解

 ***********************************************************************************************************************************

在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'}
 ********************************************************************************************************************************************
 
 
 
 
 
 
 
 
 
原文地址:https://www.cnblogs.com/pylblog/p/8270513.html