简体   繁体   English

如何检查函数的参数?

[英]How to check arguments of the function?

I have function defined this way: 我以这种方式定义了函数:

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

How do I check that a , b are not equal to some value. 如何检查ab不等于某个值。 Eg I want to check they are not empty strings like, "" or " " 例如,我要检查它们是否不是空字符串,例如""" "

Thinking about something like. 考虑类似的东西。

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

And then check if arguments are not "" , " " . 然后检查参数是否不是""" " But in this case it will also try to check None values (what I don't want to do). 但是在这种情况下,它还将尝试检查None值(我不想做什么)。

A typical approach would be: 一种典型的方法是:

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)

or, of course, you could issue warnings, or raise exceptions if the problem is very serious according to your application's semantics. 当然,根据应用程序的语义,如果问题非常严重,也可以发出警告或引发异常。

One should probably delegate all of the checking to a single function, instead of looping in the function whose args you're checking (the latter would be sticking "checking code" smack in the middle of application logic -- better keep it out or the way...): 一个人可能应该将所有检查委托给一个函数,而不是循环执行要检查其args的函数(后者将在应用程序逻辑中间粘贴“检查代码”的痕迹-最好将其保留或方式...):

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

and the function would be just: 函数将是:

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

You could, alternatively, write a decorator in order to be able to code 您也可以编写一个装饰器以便能够编码

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

(to get checking code even more "out of the way"), but this might be considered overkill unless you really have a lot of functions requiring exactly this kind of checks! (使检查代码 “杂乱无章”),但是除非您确实有很多功能需要这种检查,否则这可能被认为是过大的!

Argument-name introspection (while feasible, thanks to module inspect ) is far less simple in a decorator than within the function itself, which is why my favorite design approach would be to eschew the decorator approach in this case (simplicity is seriously good;-). 在装饰器中,参数名自省(虽然可行,这要归功于模块inspect )比在函数本身内部要简单得多,这就是为什么我最喜欢的设计方法是在这种情况下避免使用装饰器方法(简单性非常好;- )。

Edit -- showing how to implement a decorator, since the OP explicitly asked for one (though without clarifying why). 编辑 -由于OP明确要求装饰器,因此显示了如何实现装饰器(尽管未阐明原因)。

The main problem (in Python 2.6 and earlier) is for the wrapper to construct a mapping equivalent to the locals() which Python makes for you, but needs to be done explicitly in a generic wrapper. 主要问题(在python 2.6和更早版本中)是包装器构造的映射等效于Python为您创建的locals() ,但需要在通用包装器中显式完成。

But -- if you use the new 2.7, inspect.getcallargs does it for you! 但是 -如果您使用新的2.7, 那么inspect.getcallargs您做到! So, the problem becomes much simpler, and the decorator perhaps worth doing in many more cases (if you're in 2.6 or earlier, I still recommend eschewing the decorator approach, which would be substantially more complicated, for such specialized uses). 因此,问题变得更加简单,装饰器可能在更多情况下也值得做(如果您使用的是2.6或更早的版本,我仍然建议避免使用装饰器方法,对于这种专门用途,这种方法会更加复杂)。

So, here is all you need, in Python 2.7 (reusing the check_arguments function I defined above): 因此,这是您在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

The difficulty in pre-2.7 versions comes entirely from the difficulty of implementing the equivalent of inspect.getcallargs -- so, I hope that, if you really need decorators of this kind, you can simply download Python 2.7 from www.python.org and install it on your box!-) (If you do, you'll also get many more goodies besides, as well as a longer support cycle than just about any previous Python version, since 2.7 is slated to be the last release in the Python 2.* line). 2.7之前版本中的困难完全来自于实现相当于inspect.getcallargs的困难-因此,我希望,如果您确实需要这种装饰器,则可以直接从www.python.org下载Python 2.7和将其安装在您的盒子上!-)(如果这样做,您还会得到更多的好东西,并且比任何以前的Python版本都可获得更多的支持周期,因为2.7被定为Python的最新版本。 2.*行)。

Why can't you refer to the values by their names? 为什么不能通过名称来引用值?

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

If you have many arguments it is worth changing function signature to: 如果您有很多参数,则值得将函数签名更改为:

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

Though as others have said already, you can just check the arguments directly by name. 尽管正如其他人已经说过的那样,您可以直接按名称检查参数。

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

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