zoukankan      html  css  js  c++  java
  • Python全栈开发之---装饰器

    1、装饰器的形成过程

     1 import time
     2 
     3 def func1():
     4     print('in func1')
     5 
     6 def timer(func):
     7     def inner():
     8         start = time.time()
     9         func()
    10         print(time.time() - start)
    11     return inner
    12 
    13 func1 = timer(func1)
    14 func1()

    碍眼的那句话就是还要在做一次赋值调用。。。

    你觉得碍眼,python的开发者也觉得碍眼,所以就为我们提供了一句语法糖来解决这个问题!

     1 import time
     2 def timer(func):
     3     def inner():
     4         start = time.time()
     5         func()
     6         print(time.time() - start)
     7     return inner
     8 
     9 @timer   #==> func1 = timer(func1)
    10 def func1():
    11     print('in func1')
    12 
    13 
    14 func1()
    15 
    16 装饰器——语法糖

    到这里,我们可以简单的总结一下:

      装饰器的本质:一个闭包函数

      装饰器的功能:在不修改原函数及其调用方式的情况下对原函数功能进行扩展

    还有一个问题要解决,刚刚我们讨论的装饰器都是装饰不带参数的函数,现在要装饰一个带参数的函数怎么办呢?

     1 import time
     2 def timer(func):
     3     def inner(*args,**kwargs):
     4         start = time.time()
     5         re = func(*args,**kwargs)
     6         print(time.time() - start)
     7         return re
     8     return inner
     9 
    10 @timer   #==> func1 = timer(func1)
    11 def func1(a,b):
    12     print('in func1')
    13 
    14 @timer   #==> func2 = timer(func2)
    15 def func2(a):
    16     print('in func2 and get a:%s'%(a))
    17     return 'fun2 over'
    18 
    19 func1('aaaaaa','bbbbbb')
    20 print(func2('aaaaaa'))
    21 
    22 装饰器——成功hold住所有函数传参

    我们还要在装饰器上加上一点来完善它:

     1 from functools import wraps
     2 
     3 def deco(func):
     4     @wraps(func) #加在最内层函数正上方
     5     def wrapper(*args,**kwargs):
     6         return func(*args,**kwargs)
     7     return wrapper
     8 
     9 @deco
    10 def index():
    11     '''哈哈哈哈'''
    12     print('from index')
    13 
    14 print(index.__doc__)
    15 print(index.__name__)
    16 
    17 装饰器——wraps demo

    2、开放封闭原则

      1.对扩展是开放的

        为什么要对扩展开放呢?

        我们说,任何一个程序,不可能在设计之初就已经想好了所有的功能并且未来不做任何更新和修改。所以我们必须允许代码扩展、添加新功能。

      2.对修改是封闭的

        为什么要对修改封闭呢?

        就像我们刚刚提到的,因为我们写的一个函数,很有可能已经交付给其他人使用了,如果这个时候我们对其进行了修改,很有可能影响其他已经在使用该函数的用户。

    装饰器完美的遵循了这个开放封闭原则。

    3、装饰器的主要功能和装饰器的固定结构

    装饰器的主要功能:

    在不改变函数调用方式的基础上在函数的前、后添加功能。

    装饰器的固定格式:

     1 def timer(func):
     2     def inner(*args,**kwargs):
     3         '''执行函数之前要做的'''
     4         re = func(*args,**kwargs)
     5         '''执行函数之后要做的'''
     6         return re
     7     return inner
     8 
     9 装饰器的固定格式
    10 
    11 from functools import wraps
    12 
    13 def deco(func):
    14     @wraps(func) #加在最内层函数正上方
    15     def wrapper(*args,**kwargs):
    16         return func(*args,**kwargs)
    17     return wrapper
    18 
    19 装饰器的固定格式——wraps版

    4、带参数的装饰器

    假如你有成千上万个函数使用了一个装饰器,现在你想把这些装饰器都取消掉,你要怎么做?

    一个一个的取消掉? 没日没夜忙活3天。。。

    过两天你领导想通了,再让你加上。。。

     1 def outer(flag):
     2     def timer(func):
     3         def inner(*args,**kwargs):
     4             if flag:
     5                 print('''执行函数之前要做的''')
     6             re = func(*args,**kwargs)
     7             if flag:
     8                 print('''执行函数之后要做的''')
     9             return re
    10         return inner
    11     return timer
    12 
    13 @outer(False)
    14 def func():
    15     print(111)
    16 
    17 func()
    18 
    19 带参数的装饰器

    5、多个装饰器装饰同一个函数

    有些时候,我们也会用到多个装饰器装饰同一个函数的情况。

     1 def wrapper1(func):
     2     def inner():
     3         print('wrapper1 ,before func')
     4         func()
     5         print('wrapper1 ,after func')
     6     return inner
     7 
     8 def wrapper2(func):
     9     def inner():
    10         print('wrapper2 ,before func')
    11         func()
    12         print('wrapper2 ,after func')
    13     return inner
    14 
    15 @wrapper2
    16 @wrapper1
    17 def f():
    18     print('in f')
    19 
    20 f()
    21 
    22 多个装饰器装饰同一个函数
  • 相关阅读:
    Java并发容器和线程池
    CountDownLatch、CyclicBarrier
    spring data jpa
    转换时间的工具类(1)
    swagger 报错: TypeError: Failed to execute 'fetch' on 'Window': Request with GET/HEAD method cannot h
    自动生成entry-mapper-service-controller
    Hutool工具包导出Excel文件异常 You need to add dependency of poi-ooxml to your project
    Java获取24小时制的时间方法
    查询全国城市行政区
    Java对象与Json字符串之间的转化
  • 原文地址:https://www.cnblogs.com/xuechaojun/p/10166897.html
Copyright © 2011-2022 走看看