2017-07-16 55 views
2

这是简单的装饰带参数:如何当一个参数传递装饰与装饰的功能或者说条件匹配

app.py

from __future__ import print_function 
import time 

def newdecorator(arg1): 
    def benchmarking(funct): 
     #The argument is accessible here 
     print("this is the value of argument",arg1) 
     def timercheck(*args, **kwarg): 
      starttime=time.time() 
      print("starting time",time.time()) 
      funct(*args, **kwarg) 
      print("TOTAL TIME TAKEN ::",time.time()-starttime) 
     return timercheck 
    return benchmarking 

#passing value to the decorators with arguments 
@newdecorator('arg value') 
def tara(): 
    print("hellow testing") 

if __name__=="__main__": 
    tara() 

的装饰工作正常。它用一种功能来装饰功能,以显示其开始时间。

我想达到的目标: 我希望修饰者能有条件地实现我的意思。

  • 当用户运行app.py让装修不执行

  • 用户运行app.py -t比想要的装饰中实现

我将使用参数解析argparse模块,这不是一个大的p我想知道的是如何使装饰条件有条件地工作。

回答

1

您还可以将模块或一些其他命名空间中使用全局变量,但可能只有当你想把这个状态用于别的东西时才有用。拥有配置装饰器行为的应用程序设置并不罕见。

import time 

TIMING_ENABLED = True 


def newdecorator(): 
    def benchmarking(funct): 
     def timercheck(*args, **kwarg): 
      if TIMING_ENABLED: 
       starttime = time.time() 
       print("starting time", time.time()) 
      funct(*args, **kwarg) 
      if TIMING_ENABLED: 
       print("TOTAL TIME TAKEN ::", time.time() - starttime) 
     return timercheck 
    return benchmarking 

# passing value to the decorators with arguments 


@newdecorator() 
def tara(): 
    print("hellow testing") 


if __name__ == "__main__": 
    TIMING_ENABLED = False 
    tara() 

把条件检查的timercheck函数内部,因为较低的范围在模块初始化期间执行(执行main()之前),我们不会得到设置TIMING_ENABLED变量的机会是很重要的。

如果您只希望这是一个开/关的事情,那么@拉文的答案是要走的路。

既然你不需要任何参数到这个特定的装饰器,你也可以简化它。我们在没有()的情况下应用装饰器,并且可以删除一层嵌套。另外,我们将functools.wraps装饰器添加到timecheck,所以这个函数看起来像python的tara函数。 (请参阅main中的其他打印件),因为装饰器的功能实际上是用timecheck代替tara功能。

from __future__ import print_function 
import time 
from functools import wraps 

TIMING_ENABLED = True 

def newdecorator(funct): 
    @wraps(funct) 
    def timercheck(*args, **kwarg): 
     if TIMING_ENABLED: 
      starttime=time.time() 
      print("starting time",time.time()) 
     funct(*args, **kwarg) 
     if TIMING_ENABLED: 
      print("TOTAL TIME TAKEN ::",time.time()-starttime) 
    return timercheck 

@newdecorator 
def tara(): 
    """Docs for tara function""" 
    print("hellow testing") 

if __name__=="__main__": 
    TIMING_ENABLED = True 
    print(tara.__name__, tara.__doc__) 
    tara() 

您可以随时删除@wraps(funct)线,看看main将以不同的方式打印出有关tara功能。要做到这一点

1

@decorator语法只是语法糖。在引擎盖下,所发生的一切就是装饰器是用装饰函数作为参数来调用的。

所以,你可以定义你的函数没有装饰,然后如果条件满足应用装饰:

def tara(): 
    print("hellow testing") 

if script_called_with_t_flag: 
    tara = newdecorator('arg value')(tara) 
0

一种方法是有条件地适用于装饰只有在脚本调用-t否则什么都不做:

import time 

script_called_with_t = True 

def newdecorator(arg1): 
    if script_called_with_t: 
     def benchmarking(funct): 
      #The argument is accessible here 
      print("this is the value of argument",arg1) 
      def timercheck(*args, **kwarg): 
       starttime=time.time() 
       print("starting time",time.time()) 
       funct(*args, **kwarg) 
       print("TOTAL TIME TAKEN ::",time.time()-starttime) 
      return timercheck 
     return benchmarking 
    else: 
     return lambda funct: funct 

#passing value to the decorators with arguments 
@newdecorator('arg value') 
def tara(): 
    print("hellow testing") 

if __name__ == "__main__": 
    TIMING_ENABLED = False 
    tara() 
1

您可以使用sys模块在Windows命令使用参数来运行Python脚本线

运行该代码在终端与蟒app.py真使装饰和用于禁用装饰蟒app.py蟒app.py假

import time 
import sys 

TIMING_ENABLED = True 


def newdecorator(): 
    def benchmarking(funct): 
     def timercheck(*args, **kwarg): 
      if TIMING_ENABLED: 
       starttime = time.time() 
       print("starting time", time.time()) 
      funct(*args, **kwarg) 
      if TIMING_ENABLED: 
       print("TOTAL TIME TAKEN ::", time.time()-starttime) 
     return timercheck 
    return benchmarking 

# passing value to the decorators with arguments 


@newdecorator() 
def tara(): 
    print("hellow testing") 


if __name__ == "__main__": 
    TIMING_ENABLED = sys.argv[1] 
    tara()