zoukankan      html  css  js  c++  java
  • day3-python之装饰器(四)

    一、简单的装饰器

    装饰器本质上就是一个python函数,可以让其他函数在不需要任何代码变动的前提下,增加额外的功能,装饰器的返回值也是一个函数对象。

    简单来讲,在原有的函数前后增加功能,且不改变原函数的调用方式。

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

    装饰器的应用场景:插入日志、性能测试、事务处理、缓存等等场景。

    实现计算每个函数的执行时间的功能:

     1 import time
     2 def timmer(f):
     3     def inner():
     4         start_time = time.time()
     5         f()
     6         end_time = time.time()
     7         print(end_time - start_time)
     8     return inner
     9 
    10 def func():
    11     print('begin func')
    12     time.sleep(0.1)
    13     print('end func')
    14 
    15 func = timmer(func)
    16 func()   # ==> inner()
    简单的装饰器

    以上功能不简洁,不完美。引出语法糖。

     1 import time
     2 def timmer(f):
     3     def inner():
     4         start_time = time.time()
     5         f()
     6         end_time = time.time()
     7         print(end_time - start_time)
     8     return inner
     9 
    10 @timmer   # ==>  func = timmer(func)
    11 def func():
    12     print('begin func')
    13     time.sleep(0.1)
    14     print('end func')
    15 
    16 func()   # ==> inner()
    装饰器-------语法糖

    以上装饰器都是不带参数函数,现在装饰一个带参数的该怎么办?

     1 import time
     2 def timmer(f):
     3     def inner(*args,**kwargs):
     4         start_time = time.time()
     5         ret = f(*args,**kwargs)
     6         end_time = time.time()
     7         print(end_time - start_time)
     8         return ret
     9     return inner
    10 
    11 @timmer   # ==>  func = timmer(func)
    12 def func(a,b):
    13     print('begin func',a)
    14     time.sleep(0.1)
    15     print('end func',b)
    16     return True
    17 
    18 func(1,2)   # ==> inner()
    原函数带多个参数的装饰器
     1 import time
     2 
     3 def timer(func):
     4     def inner(a):
     5         start = time.time()
     6         func(a)
     7         print(time.time() - start)
     8     return inner
     9 
    10 @timer
    11 def func1(a):
    12     print(a)
    13 
    14 func1(1)
    原函数带一个参数的装饰器
     1 import time
     2 def timer(func):
     3     def inner(*args,**kwargs):
     4         start = time.time()
     5         re = func(*args,**kwargs)
     6         end=time.time()
     7         print(end- start)
     8         return re
     9     return inner
    10 
    11 @timer   #==> func1 = timer(func1)
    12 def func1(a,b):
    13     print('in func1')
    14     print(a,b)
    15 
    16 @timer   #==> func1 = timer(func1)
    17 def func2(a):
    18     print('in func2 and get a:%s'%(a))
    19     return 'fun2 over'
    20 
    21 func1(1,2)
    22 print(func2('aaaaaa'))
    原函数带多个参数的装饰器
     1 import time
     2 def timer(func):
     3     def inner(*args,**kwargs):
     4         start = time.time()
     5         re = func(*args,**kwargs)
     6         end=time.time()
     7         print(end - start)
     8         return re
     9     return inner
    10 
    11 @timer   #==> func1 = timer(func1)
    12 def jjj(a):
    13     print('in jjj and get a:%s'%(a))
    14     return 'fun2 over'
    15 
    16 jjj('aaaaaa')
    17 print(jjj('aaaaaa'))
    带返回值的装饰器

    二、开放封闭原则

    1.对扩展是开放的
    任何一个程序,不可能在设计之初就已经想好了所有的功能并且未来不做任何更新和修改。所以我们必须允许代码扩展、添加新功能。
    2.对修改是封闭的
    因为我们写的一个函数,很有可能已经交付给其他人使用了,如果这个时候我们对其进行了修改,很有可能影响其他已经在使用该函数的用户。
    装饰器完美的遵循了这个开放封闭原则。

    三、装饰器的固定结构

    1 def timmer(f):
    2     def inner(*args,**kwargs):
    3         '''执行函数之前要做的'''
    4         ret = f(*args,**kwargs)
    5         '''执行函数之后要做的'''
    6         return ret
    7     return inner
    装饰器的固定格式
    装饰器的固定格式--wraps版

    四、带参数的装饰器

    带参数的装饰器:就是给装饰器传参

    用处:就是当加了很多装饰器的时候,现在忽然又不想加装饰器了,想把装饰器给去掉,但是那么多代码,一个一个去显得麻烦,所以,可以利用带参数的装饰器去装饰它,就像一个开关,需要的时候就打开调用,不需要的时候就关闭去掉。给装饰器里面传个参数,那么这个语法糖也要带个括号。在语法糖括号内传参。可以用三层嵌套,弄一个标识

     1 # 带参数的装饰器:(相当于开关)为了给装饰器传参
     2 F=True#为True时就把装饰器给加上了
     3 # F=False#为False时就把装饰器给去掉了
     4 def outer(flag):
     5     def wrapper(func):
     6         def inner(*args,**kwargs):
     7             if flag:
     8                 print('before')
     9                 ret=func(*args,**kwargs)
    10                 print('after')
    11             else:
    12                 ret = func(*args, **kwargs)
    13             return ret
    14         return inner
    15     return wrapper
    16 
    17 @outer(F)#@wrapper
    18 def hahaha():
    19     print('hahaha')
    20 
    21 @outer(F)
    22 def shuangwaiwai():
    23     print('shuangwaiwai')
    24 
    25 hahaha()
    26 shuangwaiwai()
    给装饰器加参数

    五、多个装饰器装饰一个函数

     1 def qqqxing(fun):
     2     def inner(*args,**kwargs):
     3         print('in qqxing: before')
     4         ret = fun(*args,**kwargs)
     5         print('in qqxing: after')
     6         return ret
     7     return inner
     8 
     9 def pipixia(fun):
    10     def inner(*args,**kwargs):
    11         print('in qqxing: before')
    12         ret = fun(*args,**kwargs)
    13         print('in qqxing: after')
    14         return ret
    15     return inner
    16 @qqqxing
    17 @pipixia
    18 def dapangxie():
    19     print('饿了吗')
    20 dapangxie()
    21 
    22 '''
    23 @qqqxing和@pipixia的执行顺序:先执行qqqxing里面的 print('in qqxing: before'),然后跳到了pipixia里面的
    24         print('in qqxing: before')
    25         ret = fun(*args,**kwargs)
    26         print('in qqxing: after'),完了又回到了qqqxing里面的 print('in qqxing: after')。所以就如下面的运行结果截图一样
    27 '''
    多个装饰器装饰一个函数

     六、进阶需求

    第一种情况:

    # 500个函数

    # 设计你的装饰器 从而确认是够生效

     1 import time
     2 def outer(flag):
     3     def timmer(f):
     4         def inner(*args,**kwargs):
     5             if flag == True:
     6                 start_time = time.time()
     7                 ret = f(*args,**kwargs)
     8                 end_time = time.time()
     9                 print(end_time - start_time)
    10             else:
    11                 ret = f(*args,**kwargs)
    12             return ret
    13         return inner
    14     return timmer
    15 
    16 @outer(False)
    17 def func(a,b):
    18     print('begin func',a)
    19     time.sleep(0.1)
    20     print('end func',b)
    21     return True
    22 
    23 func(1,2)
    带参数的装饰器

     第二种情况:

    # 装饰器:登录、记录日志

     1 login_info = {'alex':False}
     2 def login(func):
     3     def inner(name):
     4         if login_info[name] != True:
     5             user = input('user:')
     6             pwd = input('pwd:')
     7             if user == 'alex' and pwd == 'alex3714':
     8                 login_info[name] = True
     9         if login_info[name] == True:
    10             ret = func(name)
    11             return ret
    12     return inner
    13 
    14 @login
    15 def index(name):
    16     print('欢迎%s来到博客园首页~' %name)
    17 
    18 @login
    19 def manager(name):
    20     print('欢迎%s来到博客园管理页~' %name)
    21 
    22 index('alex')
    23 index('alex')
    24 manager('alex')
    25 manager('alex')
    登录装饰器
     1 import time
     2 login_info = {'alex':False}
     3 def login(func):   # manager
     4     def inner(name):
     5         if login_info[name] != True:
     6             user = input('user :')
     7             pwd = input('pwd :')
     8             if user == 'alex' and pwd == 'alex3714':
     9                 login_info[name] = True
    10         if login_info[name] == True:
    11             ret = func(name)     # timmer中的inner
    12             return ret
    13     return inner
    14 
    15 def timmer(f):
    16     def inner(*args,**kwargs):
    17         start_time = time.time()
    18         ret = f(*args,**kwargs)     # 调用被装饰的方法
    19         end_time = time.time()      #
    20         print(end_time - start_time)
    21         return ret
    22     return inner
    23 
    24 @login
    25 @timmer
    26 def index(name):
    27     print('欢迎%s来到博客园首页~'%name)
    28 
    29 @login
    30 @timmer    # manager = login(manager)
    31 def manager(name):
    32     print('欢迎%s来到博客园管理页~'%name)
    33 
    34 index('alex')
    35 index('alex')
    36 manager('alex')
    37 manager('alex')
    登录、记录日志装饰器
     1 l=[]
     2 def wrapper(fun):
     3     l.append(fun)#统计当前程序中有多少个函数被装饰了
     4     def inner(*args,**kwargs):
     5         # l.append(fun)#统计本次程序执行有多少个带装饰器的函数被调用了
     6         ret = fun(*args,**kwargs)
     7         return ret
     8     return inner
     9 
    10 @wrapper
    11 def f1():
    12     print('in f1')
    13 
    14 @wrapper
    15 def f2():
    16     print('in f2')
    17 
    18 @wrapper
    19 def f3():
    20     print('in f3')
    21 print(l)
    统计多少个函数被装饰了

     

    七、总结

    # 装饰器的进阶
    # 给装饰器加上一个开关 - 从外部传了一个参数到装饰器内
    # 多个装饰器装饰同一个函数 - 套娃
    # 每个装饰器都完成一个独立的功能
    # 功能与功能之间互相分离
    # 同一个函数需要两个或以上额外的功能
     1 def wrapper1(func):
     2     def inner(*args,**kwargs):
     3         '''执行a代码'''
     4         ret = func(*args,**kwargs)
     5         '''执行b代码'''
     6         return ret
     7     return inner
     8 
     9 def wrapper2(func):
    10     def inner(*args,**kwargs):
    11         '''执行c代码'''
    12         ret = func(*args,**kwargs)
    13         '''执行d代码'''
    14         return ret
    15     return inner
    16 
    17 @wrapper1
    18 @wrapper2
    19 def func():pass
  • 相关阅读:
    django 项目需要注意的一些点
    VUE之路
    Oracle 表格碎片的查看方法
    RHEL 6.x or 7.x 使用分区绑定ASM 磁盘的方法
    RMAN 修复主库 nologging 操作导致物理备库的坏块
    Oracle 数据库19c 回退降级到 11.2.0.4 方案
    如何评估oracle 数据库rman全备和增量备份大小
    在将Oracle GI和DB升级到19c或降级到以前的版本之前需要应用的补丁 (Doc ID 2668071.1)
    Oracle 数据库坏块处理
    opatch auto 安装11.2.0.4.20190115 PSU遇到 OUI-67133: Execution of PRE script failed,with returen value 1 报错
  • 原文地址:https://www.cnblogs.com/gao-dong/p/8896586.html
Copyright © 2011-2022 走看看