• day14 装饰器


    装饰器

      本质上就是函数,功能是为其他函数添加附加功能
      原则:不修改被修饰函数的源代码,以及调用方式,即完全不能有任何改变
      装饰器 = 高阶函数+ 函数嵌套+ 闭包
    高阶函数:函数作为参数或者返回一个函数
        闭包:必须要有函数嵌套,内部函数调用外部函数的变量


    利用现有的姿势用高阶函数来实现装饰器的效果
      并没有更改foo函数的源代码,也实现了foo函数计算运算时间的附加功能
      但是却改变了foo函数的调用方式,以后都要用test(foo)才能调用
     1 import time
     2 def foo():
     3     time.sleep(3)
     4     print('你好啊林师傅')
     5 
     6 def test(func):
     7     # print(func)
     8     start_time=time.time()
     9     func()
    10     stop_time = time.time()
    11     print('函数运行时间是  %s' % (stop_time-start_time))
    12 # foo()  
    13 test(foo)  # 改变了调用方式了
      高阶函数的特性可以返回函数,可以实现不更改调用方式的问题
     1 def foo():
     2     print('from the foo')
     3 def test(func):
     4     return func
     5 
     6 res=test(foo)
     7 print(res)
     8 res()
     9 
    10 foo=test(foo)
    11 print(res)
    12 foo()
      不修改foo源代码,不修改foo调用方式,但是函数多运行了一次,废物
     1 import time
     2 def foo():
     3     time.sleep(3)
     4     print('来自foo')
     5 
     6 def timer(func):
     7     start_time=time.time()
     8     func()
     9     stop_time = time.time()
    10     print('函数运行时间是  %s' % (stop_time-start_time))
    11     return func
    12 foo=timer(foo)  #timer()运行了一次得出结果又赋值给foo
    13 foo()        # foo()又重新运行一遍,,,,
      没有修改被修饰函数的源代码,也没有修改被修饰函数的调用方式,但是也没有为被修饰函数添加新功能
    1 def timer(func):
    2     start_time=time.time()
    3     return func
    4     stop_time = time.time()
    5     print('函数运行时间是  %s' % (stop_time-start_time))
    6 
    7 foo=timer(foo)
    8 foo()
      由此可见,高端函数仁义尽致依然做不到我们想要的那种透明而又不加大负担的效果因此需要装饰器

    
    
    装饰器的框架
     1 def nnn(func):
     2     def inner(*args,**kwargs):
     3         """在这里我做了一些什么操作"""
     4         ret = func(*args,**kwargs)
     5         """在这里我又做了一些什么操作"""
     6         return ret  # 被装饰的函数的返回值
     7     return inner  
     8 @nnn
     9 def big():
    10     print("这是一个超级大源码")
    11 big()  # 本质上big() == nnn(big),但是装饰器不改变函数的调用方式,简化为big()



    一个基本的计算运行时间的装饰器的例子
     1 import time
     2 def timmer(func):
     3         def    wrapper(*args,**kwargs):
     4             start_time = time.time()
     5             res = func(*args,**kwargs)
     6             stop_time = time.time()
     7             print("函数的运行时间是%s" %(stop_time - start_time))
     8             return res
     9         return wrapper
    10 
    11 @timmer
    12 def cal(l):
    13     res = 0
    14     for i in l:
    15         time.sleep(0.1)
    16         res += i
    17     return  res
    18 
    19 print(cal(range(20)))



    带参数,返回值的装饰器使用
     1 import time
     2 def timmer(func):
     3     def    wrapper(*args,**kwargs):                # *args,**kwargs 模拟一切参数
     4         start_time = time.time()
     5         res = func(*args,**kwargs)                # 实际上就是运行test() ,将test() 的结果拿出来赋值
     6                                                 # 和上面的wrapper的参数进行一一对应的解压
     7         stop_time = time.time()
     8         print("运行时间: %s " %(stop_time - start_time))
     9         return res                    # 将赋值后的变返回值在通过wrapper再返回
    10     return wrapper
    11 
    12 
    13 @timmer # test = timmer(test)
    14 def test(name,age):
    15     time.sleep(1)
    16     print("我是天才,名字是%s ,年领是 %s" %(name,age))
    17     return "我是天才返回值"
    18 
    19 # res = test("yangtuo",18)  # 就是在运行wrapper
    20 # print(res)
    21 test("yangtuo",18)
    22 
    23 @timmer # test1 = timmer(test1)
    24 def test1(name,age,gender):
    25     time.sleep(1)
    26     print("我是天才一号,名字是%s ,年领是 %s,性别是 %s" %(name,age,gender))
    27     return "我是天才一号返回值"
    28 
    29 test1("shijieli",19,"man")

  • 相关阅读:
    网格视图
    使用box-shadow 属性用来可以创建纸质样式卡片:
    css 按钮动画
    vue父组件向自定义组件传递参数过程
    vue中如何使用 v-model 实现双向数据绑定?
    vue中是如何实现响应键盘回车事件
    vue中如何实现 样式绑定?
    webpack require.Context功能作用
    Personal tips for success
    my blog frist
  • 原文地址:https://www.cnblogs.com/shijieli/p/9705934.html
Copyright © 2020-2023  润新知