在d中声明的函数访问变量

2024-05-01 21:59:00 发布

您现在位置:Python中文网/ 问答频道 /正文

我想记录很多指标,比如函数执行所需的时间。我希望解决方案是轻量级的。添加一个装饰和完成。也许90%的时间是这样的:

@LogMetrics
def my_business_logic(var1):
  print 'done'

但是,我也希望能够访问metrics对象,并在10%的时间内执行以下操作:

@LogMetrics
def my_business_logic(var1):
  metrics.inc_counter('counter_a')
  print 'done'

到目前为止,我有一个处理第一个场景的装饰器:

class LogMetrics(object):

  def __init__(self, module=None):
    self.module = module


  def __call__(self, target):

    def wrapped(*args, **kwargs):
      # set up metrics
      metrics = Metrics(module=module)

      metrics.start_timer()
      try:
        result = target(*args, **kwargs)
      except Exception as e:
        metrics.set_fault()
        raise e
      finally:
        metrics.stop_timer()
        metrics.push()

      return result

    return wrapped

如何支持场景2?我想做这样的事情answer,但共识似乎是不这样做。请帮忙。。。你知道吗


Tags: selfmydefcounter时间场景装饰business
2条回答

唯一不涉及全局对象或禁止魔法的解决方案是将metrics对象作为可选参数传递给函数(我假设如果可以编辑它,那么可以更改它的签名):

class LogMetrics(object):

  ...

  def __call__(self, target):

    def wrapped(*args, **kwargs):
      # set up metrics
      metrics = Metrics(module=module)
      kwargs['metrics'] = metrics  # add metrics object to kwargs
      metrics.start_timer()
      try:
        result = target(*args, **kwargs)
      except Exception as e:
        metrics.set_fault()
        raise e
      finally:
        metrics.stop_timer()
        metrics.push()
      return result
    return wrapped


@LogMetrics
def my_business_logic(var1, metrics=None):
  if metrics is not None:
      metrics.inc_counter('counter_a')
  print 'done'

顺便问一下,您确定要在Metrics内而不是在__call__内初始化Metrics吗?你知道吗

可以向函数添加属性。我做了一个非常简单的例子(在Python3中)。add_counter修饰符向原始函数添加一个_counter属性(您将改为添加一个metrics对象)。本例中的计数器在每次调用后递增。最后,一个_orig_func属性被添加到修饰函数中,以允许访问计数器。你知道吗

def add_counter(func):
    func._counter = 0 
    def decorated(*args, **kwargs):
        result = func(*args, **kwargs)
        func._counter += 1
        return result
    decorated._orig_func = func
    return decorated

@add_counter
def func1():
    print("FUNC1")
    print(func1._orig_func._counter)

@add_counter
def func2():
    print("FUNC2")
    print(func2._orig_func._counter)

func1()
func1()
func1()
func2()
func2()
func1()

相关问题 更多 >