用参数装饰发电机

时间:2019-03-18 15:22:00

标签: python decorator

这是我的生成器,它接受数组输入并以特定方式对其进行迭代:

def array_gen(answer):
    n = len(answer)
    m = len(answer[0])
    elem=0
    i = n
    j = 0
    curr = 0
    steps = [(-1,0), (0,1), (1,0), (0,1)]
    while not (elem == n*m):
        if (((i == n - 1) and (j != 0)) or i == 0):
            curr += 1
        i += steps[curr % 4][0]
        j += steps[curr % 4][1]
        elem+=1
        yield answer[i][j]

现在,我想编写一个装饰器,该装饰器在遍历数组时返回数组的元素对(当前和下一个)。有人可以给我一些实现此功能的想法吗?

1 个答案:

答案 0 :(得分:1)

使用itertools recipes中的pairwise食谱并将其用作装饰器:

from itertools import tee

def pairwise(iterable):
    "s -> (s0,s1), (s1,s2), (s2, s3), ..."
    a, b = tee(iterable)
    next(b, None)
    return zip(a, b)
from functools import wraps

def pairwise_decorator(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        return pairwise(func(*args, **kwargs))
    return wrapper

这很适合使用生成器(itertools模块中的所有函数),并在Python 3中返回zip对象(一种特殊的生成器)。

用法示例:

@pairwise_decorator
def f(n):
    return range(n)

list(f(5))
# [(0, 1), (1, 2), (2, 3), (3, 4)]

要使其更通用(在装饰函数的输出上调用任何函数),请使其成为接受参数的装饰器:

def call_after(outer_func):
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            return outer_func(func(*args, **kwargs))
        return wrapper
    return decorator

@call_after(pairwise)
def f(n):
    return range(n)

@call_after(lambda x: grouper(x, 3))
def g(n):
    return range(n)

list(f(5))
# [(0, 1), (1, 2), (2, 3), (3, 4)]
list(g(5))
# [(0, 1, 2), (3, 4, None)]