• Python基础-----装饰器


    一、装饰器定义

    器即函数;装饰即修饰,意指为其他函数添加新功能;

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

    二、装饰器的原则

    1.不修改被装饰函数的源代码(开放封闭原则)

    2.为被装饰函数添加新功能后,不修改被修饰函数的调用方式

    三、高阶函数

    满足如下条件之一就可称之为高阶函数

    1.函数接收的参数是一个函数名
    2.函数的返回值是一个函数名

    高阶函数总结

    1.函数接收的参数是一个函数名
      作用:在不修改函数源代码的前提下,为函数添加新功能,
      不足:会改变函数的调用方式
    2.函数的返回值是一个函数名
      作用:不修改函数的调用方式
      不足:不能添加新功能

    四、闭包
    闭包:在一个作用域里放入定义变量(或嵌套函数),相当于打了一个包
    想要给内部传入参数,用闭包的话只需要在最外部传入即可
    1 def father(name):
    2    def son():
    3         def grandson():
    4             print('from %s'%name)
    5         grandson()
    6    son()
    7 
    8 father('Meanwey')

    五、装饰器框架实现
     1 import time
     2 def timmer(func):    #func = test
     3    def wrapper():
     4       start_time = time.time()
     5       func()       #执行test函数
     6       stop_time = time.time()
     7       print('运行时间%s'%(stop_time - start_time))
     8    return wrapper
     9 
    10 def test():
    11    time.sleep(3)
    12    print('函数运行完毕')
    13 
    14 test = timmer(test)   #返回的是wrapper的函数地址
    15 test()           #执行wrapper函数,内部再运行test函数
      上面代码符合装饰器的基本原则,但是调用test函数之前进行了赋值操作

    六、装饰器语法糖
    @装饰函数 (将该句代码放置于修饰函数前即可)
    就上例来讲,@timmer 就相当于 test = timmer(test)
     1 import time
     2 def timmer(func):    #func = test
     3    def wrapper():
     4       start_time = time.time()
     5       func()       #执行test函数
     6       stop_time = time.time()
     7       print('运行时间%s'%(stop_time - start_time))
     8    return wrapper
     9 
    10 @timmer   #等同于test = timmer(test)
    11 def test():
    12    time.sleep(3)
    13    print('函数运行完毕')
    14 
    15 test()

    七、加上返回值
     1 import time
     2 def timmer(func):    #func = test
     3    def wrapper():
     4       start_time = time.time()
     5       res = func()       #执行test函数
     6       stop_time = time.time()
     7       print('运行时间%s'%(stop_time - start_time))
     8       return res
     9    return wrapper
    10 
    11 @timmer   #等同于test = timmer(test)
    12 def test():
    13    time.sleep(3)
    14    print('函数运行完毕')
    15    return '这是test的返回值'
    16 a = test()   #实际执行wrapper函数
    17 print(a)

    八、加上参数
     1 import time
     2 def timmer(func):    #func = test
     3    def wrapper(name,age):
     4       start_time = time.time()
     5       res = func(name,age)       #执行test函数,参数来自wrapper接收的参数
     6       stop_time = time.time()
     7       print('运行时间%s'%(stop_time - start_time))
     8       return res
     9    return wrapper
    10 
    11 @timmer   #等同于test = timmer(test)
    12 def test(name,age):
    13    time.sleep(3)
    14    print('我叫%s,年龄%d'%(name,age))
    15    return '这是test的返回值'
    16 a = test('alex',18)   #实际执行wrapper函数

      但是参数是固定的,不适用于所有函数,则改变如下:
     1 import time
     2 def timmer(func):    #func = test
     3    def wrapper(*args,**kwargs):        #可以用*  **来传入多参数
     4       start_time = time.time()
     5       res = func(*args,**kwargs)       #执行test函数,参数来自wrapper接收的参数
     6       stop_time = time.time()
     7       print('运行时间%s'%(stop_time - start_time))
     8       return res
     9    return wrapper
    10 
    11 @timmer   #等同于test = timmer(test)
    12 def test(name,age):
    13    time.sleep(3)
    14    print('我叫%s,年龄%d'%(name,age))
    15    return '这是test的返回值'
    16 
    17 @timmer
    18 def test1(name,age,gender):
    19    time.sleep(3)
    20    print('我叫%s,年龄%d,性别%s'%(name,age,gender))
    21    return '这是test的返回值'
    22 a = test('alex',18)   #实际执行wrapper函数
    23 b = test1('tony',22,'male')   #该处将'tony',22,'male'参数放入*args == *('tony',22,'male')(一一对应,相当于解压)

    九、列表解压
      如要获取列表的第一个和最后一个值,不用索引来取
    1 l = [10,2,3,4,5,7,5,4,2,32]
    2 first_num,*other_num,last_num = l   #  *+变量名   表示中间的所有元素
    3 print(first_num,last_num)
    4 print(*other_num)

      如需互换两个变量的值
    1 a = 1
    2 b = 2
    3 a,b = b,a
    4 print(a,b)

    十、实例(验证功能装饰器)
     1 user_list = [
     2          {'name':'a','password':'123'},
     3          {'name':'b','password':'123'},
     4          {'name':'c','password':'123'},
     5          {'name':'d','password':'123'}
     6 ]   #所有用户信息列表(值为字符串类型)
     7 
     8 current_user = {'username':None,'login':False}    #记录用户当前登录状态
     9 
    10 def auth_func(func):
    11    def wrapper(*args,**kwargs):
    12       if current_user['username'] and current_user['login']:   #如果已经登录,则无需登陆
    13          res = func(*args,**kwargs)
    14          return res
    15       username = input('用户名:').strip()   #上面if不成立,则登录
    16       password = input('密码:').strip()
    17       for user_dic in user_list:    #for遍历的是用户列表的中用户信息字典
    18          if username == user_dic['name'] and password == user_dic['password']: #登录验证
    19             current_user['username'] = username   #登录成功,更改用户状态
    20             current_user['login'] = True
    21             res = func(*args,**kwargs)
    22             return res
    23       else:   #该处else没放在if下是因为,要遍历所有的用户列表才能判断是否真的有错
    24          print('用户名或密码错误,请重新登录!')
    25    return wrapper
    26 
    27 @auth_func
    28 def home(name):
    29    print('欢迎 %s 来到主页'%name)
    30 
    31 @auth_func
    32 def shopping_car(name):
    33    print('%s 的购物车里有:学习用品,生活用品!'%name)
    34 
    35 home('Jerry')
    36 print(current_user)
    37 shopping_car('Jerry')
  • 相关阅读:
    滚轮事件的防冒泡、阻止默认行为的代码(效果是:只让当前div滚动,连当前文档都不滚动的效果)
    js原生封装getClassName()方法-ie不支持getElementsByClassName,所以要自己实现获取类名为className的所有元素
    使用 RequireJS 优化 Web 应用前端
    javascript的页面加载及性能优化(兼容IE7)
    JavaScript中的this陷阱的最全收集--没有之一
    mysql 配置MHA
    mysql 在linux下的完整安装过程
    vue 开发系列(八) 动态表单开发
    vue 开发系列(七) 路由配置
    vue 开发系列(六) 企业微信整合
  • 原文地址:https://www.cnblogs.com/Meanwey/p/9741285.html
Copyright © 2020-2023  润新知