• python装饰器


    1.1装饰器(decorator)

    什么是装饰器:

    器即函数

    1.装饰器可以理解为给一个函数,做修饰,而不修改函数本身。

    2.装饰器定义:本质就是函数,decorator功能就是为其他函数添加新的功能。

    装饰器的的原则

    装饰器=高阶函数+函数嵌套+闭包

    装饰器的前提原则:不能修改被装饰函数的源代码,和函数的调用方式

     1.1.1高阶函数

    高阶函数定义:

    1.函数接收的参数是一个函数名。

    2.函数的返回值是一个函数。

    3.满足上述条件任意一个,都是高阶函数

    1.1.2函数嵌套

    函数嵌套

    python语言中的嵌套:定义一个函数的时候,函数体还能定义另一个函数。

    在其他语言(例c语言),在一个函数调用另一个函数,叫嵌套

    1.1.3闭包

    存储在子封闭作用域(函数)的行为叫做闭包

    一个闭包就是一个函数,只不过函数内部带上了一个额外的变量。

    闭包关键特点就是它会记住自已被定义时的环境

     

    1.2一步一步理解装饰器

    1 def go():
    2     print("python")
    3 #该函数功能执行go() ,显示出python
    4 go()

    现在我们要增强go()这个自定义函数的功能,比如在函数调用前自动打印出python是什么样的语言,但有不想在修改go()函数,这种在代码运行期间动态为其添加功能,就称之为装饰器(decorator)。

     

     1.现在给go()函数加功能

     1 #一个装饰器的基本框架
     2 def deco(func):
     3     def wrapper():
     4         func()    #执行你传的go的函数
     5         print("一个高级语言")
     6     return wrapper
     7 def go():
     8     print("python")
     9 go = deco(go)  #得到结果wrappe的函数r
    10 go()  # 执行wrapper函数  ——执行函数func() 函数也就是的go()函数
    11 #结果
    12  python
    13  一个高级语言
    14 
    15 #上面就是一个装饰器功能的基本体现,没有修改go函数的源代码,也没有修改go()函数的执行方式,也给go函数加上了一个新功能(高级语言) ,
    但是上面每次执行,都需要做一个函数赋值操作,才能执行go() ,这是不完美的

    本质上:装饰器(decrator)就是一个返回函数的高阶函数,上面的deco,就是一个装饰器,接收函数做参数,并返回一个函数,需要借助python的@语法,@装饰器

     1 def deco(func):
     2     def wrapper():
     3         func()
     4         print("一个高级语言")
     5     return wrapper
     6 @deco
     7 def go():
     8     print("python")
     9 go()
    10 #结果
    11 python
    12 一个高级语言
    13 
    14 #现在才相当于一个合格的装饰器
    15 
    16 把@deco放到go()函数的定义处,相当于执行了go=deco(go)

    上面deco()是一个装饰器,返回一个函数,所以原来的go()函数仍然存在,

    只是现在同名的go变量指向了新的函数,于是调用go()函数将执行新函数,

    即在go()函数中返回的wrapper()函数

    2.给被装饰器函数加参数和返回值

     1 def deco(func):
     2     def wrapper(*args,**kwargs):
     3         res = func(*args,**kwargs)  #这里就相当于闭包
     4         print("一门高级语言")
     5         return res
     6     return wrapper
     7 
     8 @deco
     9 def go(x,y):
    10     print("python",x,y)
    11     return "done"
    12 go(3,5)
    13 # 结果
    14 python
    15 一个高级语言
    16 
    17 # 为什么要给装饰器加参数,如果被装饰的函数里面有参数,我们的装饰器是不是器也要加相应的参数,
    18 我们的装饰器为什么要给wrapper(*args,**kwargs) func(*args,**kwargs),可接收任意参数,因为我们被装饰的函数可能都是不同的的参数,而这个装饰器,需要给很多函数做装饰,但是很多函数的参数,功能都是不一样的,因此我们定义装饰器 的函数参数应该是加可变长参数
    19 
    20 #为什么给装饰里面加返回值
    21 我们被装饰的函数,一般是有返回值,而执行装饰器(@decorator)  所以需要给wrapper 加上返回值来return fun()的执行结果,来保持被装饰的函数的一致性。
    给被装饰函数加参数和返回值

    3.给装饰器加参数

     如果装饰器本身需要传入参数,那就需要编写一个返回装饰器的高阶函数,也就是在原来装饰器上,做闭包处理,在加上一层函数。

     1 def auth_book(auth=None):
     2     print(auth)
     3     def deco(func):
     4         def wrapper(*args,**kwargs):
     5             res = func(*args,**kwargs)  #这里就相当于闭包
     6             print("一门高级语言")
     7             return res
     8         return wrapper
     9     return deco
    10 @deco("book")  #装饰器加参数    跟go=deco("book")(go)类似
    11 def go(x,y):
    12     print("python",x,y)
    13 go(3,5)

    3层嵌套的装饰器的效果是这样的

    1 go=auth_book("book")(go)
     1 user_list=[
     2     {'name':'yj','passwd':'123'},
     3     {'name':'xixi','passwd':'123'},
     4     {'name':'xiha','passwd':'123'},
     5     {'name':'lala','passwd':'123'},
     6 ]
     7 
     8 current_user={'username':None,'login':False}
     9 def auth(auth_type='file'):
    10     def auth_deco(func):
    11         def wrapper(*args,**kwargs):
    12             if auth_type == 'file':
    13                 if current_user['username'] and current_user['login']:
    14                     res=func(*args,**kwargs)
    15                     return res
    16                 username=input('用户名: ').strip()
    17                 passwd=input('密码: ').strip()
    18 
    19                 for index,user_dic in enumerate(user_list):
    20                     if username == user_dic['name'] and passwd == user_dic['passwd']:
    21                         current_user['username']=username
    22                         current_user['login']=True
    23                         res=func(*args,**kwargs)
    24                         return res
    25 
    26                 else:
    27                     print('用户名或者密码错误,重新登录')
    28             elif auth_type == 'ldap':
    29                 print('巴拉巴拉小魔仙')
    30                 res=func(*args,**kwargs)
    31                 return res
    32         return wrapper
    33     return auth_deco
    34 
    35 
    36 #auth(auth_type='file')就是在运行一个函数,然后返回auth_deco,所以@auth(auth_type='file')
    37 #就相当于@auth_deco,只不过现在,我们的auth_deco作为一个闭包的应用,外层的包auth给它留了一个auth_type='file'参数
    38 @auth(auth_type='ldap')
    39 def index():
    40     print('欢迎来到主页面')
    41 
    42 @auth(auth_type='ldap')
    43 def home():
    44     print('这里是你家')
    45 @auth(auth_type="file")
    46 def shopping_car():
    47     print('查看购物车啊亲')
    48 
    49 def order():
    50     print('查看订单啊亲')
    51 
    52 # print(user_list)
    53 index()
    54 # print(user_list)
    55 home()
    56 shopping_car()
    demo 带参数的装饰器
  • 相关阅读:
    docker-compose写法收集
    【CodeForces】704 C. Black Widow 动态规划+模拟
    【BZOJ】2693: jzptab 莫比乌斯反演
    【BZOJ】2154: Crash的数字表格 莫比乌斯反演
    【CodeForces】915 G. Coprime Arrays 莫比乌斯反演
    【CodeForces】915 F. Imbalance Value of a Tree 并查集
    【CodeForces】915 E. Physical Education Lessons 线段树
    【CodeForces】915 D. Almost Acyclic Graph 拓扑排序找环
    【Atcoder】AGC 020 B
    【Atcoder】AGC 020 D
  • 原文地址:https://www.cnblogs.com/keme/p/6144121.html
Copyright © 2020-2023  润新知