简体   繁体   English

如何在python中将特定参数传递给装饰器

[英]How to pass a specific argument to a decorator in python

I want to write a python function decorator that tests that certain arguments to a function pass some criterion. 我想写一个python函数装饰器,测试函数的某些参数是否通过了一些标准。 For eg, Suppose I want to test that some arguments are always even, then I want to be able to do something like this (not valid python code) 例如,假设我想测试一些参数总是偶数,那么我希望能够做这样的事情(不是有效的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

But I cannot figure how to achieve the above. 但我无法想象如何实现上述目标。 Is there a way to pass specific arguments to the decorator? 有没有办法将特定参数传递给装饰器? (like arg2 for foo and arg3 for bar in the above) (比如arg2 for foo和arg3 for bar in)

Thanks! 谢谢!

You can do this: 你可以这样做:

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

So then: 那么:

@ensure_even(1)  #2nd argument must be even
def test(arg1, arg2):
  print(arg2)

test(1,2) #succeeds
test(1,3) #fails

My previous answer missed the point of your question. 我之前的回答错过了你的问题。

Here's a longer solution: 这是一个更长的解决方案:

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

and so this is the usage: 这是用法:

@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

although I'm not sure if it will work in all situations. 虽然我不确定它是否适用于所有情况。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM