对于功能和发电机实时装饰(real-time decorator for functions and

2019-10-30 12:29发布

我有我需要挂钩的某些功能,这样我可以检查返回值和追踪他们的情况。 这是例如通过运行方法/函数返回值的平均值追踪有用的。 然而,这些方法/功能也可以是发电机。

但是,如果我没有错,在解析时蟒蛇检测发电机和当函数被调用运行时,它总是返回一个发电机。 因此,我不能简单地做一些事情,如:

import types
def decorator(func):
    average = None # assume average can be accessed by other means
    def wrap(*args, **kwargs):
        nonlocal average
        ret_value = func(*args, **kwargs)
        #if False wrap is still a generator 
        if isinstance(ret_value, types.GeneratorType): 
           for value in ret_value:
              # update average
              yield value
        else:
            # update average
            return ret_value # ret_value can't ever be fetched
    return wrap

yield在这个装饰ING是必要的,因为我需要跟踪的值作为主叫迭代这个装饰发生器(即“实时”)。 意思是,我不能简单地取代for ,并yieldvalues = list(ret_value)并返回values 。 (IE)如果func是它需要保持装饰一旦发电机发电机。 但是,如果func是一个纯函数/方法,即使else执行, wrap仍然是一个发电机。 这意味着,该ret_value永远不能被取出。

使用这样的发电机将是一种玩具例如:

@decorated
def some_gen(some_list):
    for _ in range(10):
       if some_list[0] % 2 == 0:
           yield 1
       else:
           yield 0
def caller():
   some_list = [0]
   for i in some_gen(some_list):
      print(i)
      some_list[0] += 1 # changes what some_gen yields

对于玩具的例子,有可能是简单的解决方案,但它只是为了证明这一点。

也许我失去了一些东西很明显,但我做了一些研究,并没有发现任何东西。 我发现的最接近的事情是这个 。 但是,这仍然没有让装饰检查由包发生器(只是第一)返回的每一个值。 这是否有一个解决方案,或两种类型的装饰(一个功能,一个用于装饰)必要的?

Answer 1:

一旦解决,我意识到是:

def as_generator(gen, avg_update):
     for i in gen:
         avg_update(i)
         yield i

import types
def decorator(func):
    average = None # assume average can be accessed by other means
    def wrap(*args, **kwargs):
        def avg_update(ret_value):
            nonlocal average
            #update average
            pass

        ret_value = func(*args, **kwargs)
        #if False wrap is still a generator 
        if isinstance(ret_value, types.GeneratorType): 
           return as_generator(ret_value, avg_update)
        else:
            avg_update(ret_value)
            return ret_value # ret_value can't ever be fetched
    return wrap

我不知道这是不是唯一的一个,或者如果存在一个不进行单独的函数发生器的情况下。



文章来源: real-time decorator for functions and generators