如何检查函数的参数?

时间:2010-07-14 15:37:00

标签: python

我有这样定义的功能:

def f1 (a, b, c = None, d = None):
    .....

如何检查ab是否与某个值不相等。例如。我想检查它们不是空字符串,例如""" "

思考像。

arguments = locals()
for item in arguments:
    check_attribute(item, arguments[item])

然后检查参数是否不是""" "。但在这种情况下,它还会尝试检查None值(我不想做的)。

3 个答案:

答案 0 :(得分:8)

一种典型的方法是:

import sys

...

def check_attribute(name, value):
    """Gives warnings on stderr if the value is an empty or whitespace string.

       All other values, including None, are OK and give no warning.
    """
    if isinstance(value, basestring) and (not value or value.isspace()):
        print>>sys.stderr, "Invalid value %r for argument %r" % (value, name)

或者,当然,如果根据应用程序的语义问题非常严重,您可以发出警告或引发异常。

应该将所有检查委托给单个函数,而不是在你正在检查它的args的函数中循环(后者会在应用程序逻辑中间坚持“检查代码” - 更好地保留它出路或路......):

def check_arguments(d):
    for name, value in d.iteritems():
        check_attribute(name, value)

,功能就是:

def f1 (a, b, c=None, d=None):
    check_arguments(locals())
    ...

您也可以编写装饰器以便能够编码

@checked_arguments
def f1 (a, b, c=None, d=None):
   ...

(为了检查代码甚至更多“”),但这可能被视为过度杀伤,除非你真的有一个很多的功能需要这种检查!

参数名称内省(虽然可行,但由于模块inspect)在装饰器中远不如函数本身那么简单,这就是为什么我最喜欢的设计方法是在这种情况下避开装饰器方法(简单非常好; - )。

编辑 - 显示如何实现装饰器,因为OP明确要求一个(虽然没有说明原因)。

主要问题(在Python 2.6和更早版本中)是包装器构造一个等效于Python为您提供的locals()的映射,但需要在通用包装器中显式完成。

但是 - 如果你使用新的2.7,inspect.getcallargs为你做了!因此,问题变得更加简单,并且装饰器可能在更多情况下值得做(如果你在2.6或更早版本中,我仍然建议避免使用装饰器方法,这对于这种专门用途来说会更复杂)。 / p>

所以,这就是你需要的,在Python 2.7中(重用我上面定义的check_arguments函数):

import functools
import inspect

def checked_arguments(f):
  @functools.wraps(f)
  def wrapper(*a, **k):
    d = inspect.getcallargs(f, *a, **k)
    check_arguments(d)
    return f(*a, **k)
  return wrapper

2.7之前版本的难度完全来自于实现等效inspect.getcallargs的难度 - 所以,我希望,如果你真的需要这种类型的装饰器,你可以简单地从{{ {1}}并将其安装在您的盒子上! - ) (如果你这样做,除了以前任何Python版本之外,你还会得到更多好东西,以及更长的支持周期,因为2.7将被定为Python www.python.org行中的最后一个版本)。

答案 1 :(得分:5)

为什么不能通过名字来引用这些值?

def f1 (a, b, c=None, d=None):
    if not a.strip():
        print('a is not empty')

如果您有许多参数,则值得将函数签名更改为:

def f2 (*args, c=None, d=None):
    for var in args:
        if not var.strip():
            raise ValueError('all elements should be non-empty')

答案 2 :(得分:0)

for key, value in locals().items():
    if value is not None:
        check_attribute(key, value)

虽然正如其他人已经说过的那样,你可以直接按名称查看参数。