zoukankan      html  css  js  c++  java
  • python装饰器系列(三)

    装饰器的应用实例

    1 import time
    2 def timeit(fn):
    3     start = time.time()
    4     fn()
    5     print(time.time() - start)
    6     
    7 def sleep():
    8     time.sleep(3)

    上边代码定义了两个函数,timeit函数能够模拟计算出在执行fn函数所花费的时间

    1 timeit(sleep)
    2 3.003638505935669

    这样来计算一个函数的执行时间是有缺陷的,sleep函数必须是一个接收参数的函数,那怎样才能让sleep能接收参数呢?做如下改进:

     1 def timeit_1(fn):
     2     def wrap(x):
     3         start = time.time()
     4         fn(x)
     5         print(time.time() - start)
     6     return wrap
     7   
     8 
     9 def sleep_1(x):
    10     time.sleep(x)
    1 timeit_1(sleep_1)(3)
    2 3.0035746097564697

    这样timeit_1函数通过wrap函数进行一次包装后就可以让sleep函数接收一个参数,但如果sleep函数所接收的参数个数是不确定的呢?

    这个可以采用python中的可变参数来解决,如下:

    1 def timeit_2(fn):
    2     def wrap(*args,**kwargs):
    3         start = time.time()
    4         fn(*args,**kwargs)
    5         print(time.time() - start)
    6     return wrap

    这样对于sleep这个函数所需要接收的参数个数就没有限制了,调用方法与上边的不变

    1 timeit_2(sleep_1)(3)
    2 3.003852605819702

    其实这里的timeit_2就是一个装饰器,在python中有一个语法糖来表示,如果在执行一个函数时,比如上边的sleep_1函数想在其执行前后增加一些语句操作,比如上边的start = time.time()print(time.time() - start),那在定义sleep_1函数时就可以加上一个装饰器来装饰此函数,这样定义的函数有其独特的语法,在定义函数时在其上边用一个@符号加上装饰器函数的名称即可

    1 @timeit_2
    2 def sleep_2(x):
    3     time.sleep(x)

    如上定义后的sleep_2的函数,我们在调用时就不需要再去调用timeit_2这个函数了,直接调用sleep_2函数即可,如下:

    1 sleep_2(3)
    2 3.0038673877716064

    调用sleep_2(3)时,函数的执行流程:

    首先把sleep_2函数作为参数传递到timeit_2这个装饰器函数中执行,返回一个wrap函数对象

    再把调用sleep_2(3)函数时的参数3传递到wrap函数参数中进行函数调用,实质就是解释器会转换成timeit_2(sleep_2)(3)的方式来调用,

    但是在已经使用@timeit_2语法来装饰函数sleep_2的场景下不能再使用timeit_2(sleep_2)(3)来调用函数,因为这样wrap函数会被执行两次。

    总结一下:

    装饰器的本质就是一个函数,此函数接收一个函数作为参数,返回一个函数,通常,返回的这个函数,是对传入的函数执行进行前后增加了一些语句,所以叫做装饰器。

  • 相关阅读:
    BZOJ1217: [HNOI2003]消防局的设立
    BZOJ3925: [Zjoi2015]地震后的幻想乡
    BZOJ2328: [HNOI2011]赛车游戏
    BZOJ1011: [HNOI2008]遥远的行星
    BZOJ2007: [Noi2010]海拔
    BZOJ1833: [ZJOI2010]count 数字计数
    BZOJ1026: [SCOI2009]windy数
    BZOJ1196: [HNOI2006]公路修建问题
    BZOJ1076: [SCOI2008]奖励关
    BZOJ2752: [HAOI2012]高速公路(road)
  • 原文地址:https://www.cnblogs.com/tianshug/p/10921830.html
Copyright © 2011-2022 走看看