代码之家  ›  专栏  ›  技术社区  ›  MK.

如何在python中将特定参数传递给decorator

  •  3
  • MK.  · 技术社区  · 14 年前

    我想编写一个python函数修饰符来测试函数的某些参数是否通过某种标准。例如,假设我想测试一些参数是否总是偶数,那么我想做一些类似的事情(不是有效的python代码)

    def ensure_even( n )  :
      def decorator( function ) :
        @functools.wraps( function )
        def wrapper(*args, **kwargs):
          assert(n % 2 == 0)
          return function(*args, **kwargs)
        return wrapper
       return decorator
    
    
    @ensure_even(arg2)
    def foo(arg1, arg2, arg3) : pass
    
    @ensure_even(arg3)
    def bar(arg1, arg2, arg3) : pass
    

    但我不知道如何实现上述目标。有没有一种方法可以将特定的参数传递给decorator(如上图中arg2表示foo,arg3表示bar)

    2 回复  |  直到 14 年前
        1
  •  11
  •   jcao219    14 年前

    您可以这样做:

    def ensure_even(argnum):
      def fdec(func):
        def f(*args, **kwargs):
          assert(args[argnum] % 2 == 0)  #or assert(not args[argnum] % 2)
          return func(*args, **kwargs)
        return f
      return fdec
    

    那么:

    @ensure_even(1)  #2nd argument must be even
    def test(arg1, arg2):
      print(arg2)
    
    test(1,2) #succeeds
    test(1,3) #fails
    
        2
  •  4
  •   jcao219    14 年前

    我先前的回答没有抓住你问题的重点。

    def ensure_even(*argvars):
      def fdec(func):
        def f(*args,**kwargs):
          for argvar in argvars:
            try:
              assert(not args[func.func_code.co_varnames.index(argvar)] % 2)
            except IndexError:
              assert(not kwargs[argvar] % 2)
          return func(*args,**kwargs)
        return f
      return fdec
    

    这就是用法:

    @ensure_even('a','b')
    def both_even(a,b):
        print a,b
    
    @ensure_even('even')
    def first_even(even, arg2):
        print even, arg2
    
    both_even(2,2)
    first_even(2,3)
    both_even(2,1) #fails
    

    尽管我不确定它是否能在所有情况下都起作用。