带有函数参数的Python装饰器

时间:2014-10-30 04:48:50

标签: python numpy decorator argument-passing

我有一个简单的函数,定义如下:

def simple_function(x):
    """ x is an input numpy array"""
    return x + 0.1

我想通过对它应用一些边界条件来修改此函数。这些边界条件本身就是x的函数:

def upper_bound(x):
    return x**2

def lower_bound(x):
    return np.zeros(len(x))

特别是,如果simple_function(x)超过upper_bound(x)的值,或低于lower_bound(x),我希望simple_function(x)的修饰版本返回值{{1对于lower_bound,同样如此。如何在python中使用@decorator语法完成此行为?

2 个答案:

答案 0 :(得分:2)

如果您的参数,边界和结果都是numpy数组,则可以执行几个数组赋值,以便在upper_boundlower_bound函数返回的相应值之间钳制每个元素。核心部分是:

r = f(x)
l = lower_bound(x)
u = upper_bound(x)

i = r < l
j = r > u

r[i] = l
r[j] = u

ij将是布尔数组,分别说明需要将哪些索引钳位到下限和上限。要使此代码作为装饰器工作,您只需将其放在一对嵌套函数中,如下所示:

def clamp(f):
    @functools.wraps(f)
    def wrapper(x):
        r = f(x)
        l = lower_bound(x)
        u = upper_bound(x)

        i = r < l
        j = r > u

        r[i] = l
        r[j] = u

        return r

    return wrapper

functools.wraps使包装函数复制装饰函数的名称,注释和文档字符串。

上面的代码假设您始终使用相同的upper_boundlower_bound函数。如果你需要为你正在装修的不同功能定制那些,你可以添加一层额外的嵌套,并定义一个“装饰工厂”,如Ignacio Vazquez-Abrams的回答:

def clamp(lower_bound, upper_bound):   # this is the decorator factory function
    def decotator(f):                  # this is the decorator function
        @functools.wraps(f)
        def wrapper(x):                # this is the wrapper function
            ... # same code here as above
            return r

        return wrapper

    return decorator

答案 1 :(得分:0)

除了修改__doc__等之外,你在这里:

def constrain(lower, upper):
  def outer(f):
    def inner(x):
      r = f(x)
      u = upper(x)
      if r > u:
        return u
      l = lower(x)
      if r < l:
        return l
      return r
    return inner
  return outer

...

@constrain(lower_bound, upper_bound)
def simple_function(x):
   ...

不处理不同的类型和低于上限的下限。