我有这样定义的函数:
def f1 (a, b, c = None, d = None):
.....
Run Code Online (Sandbox Code Playgroud)
我如何检查a,b不等于某个值.我想检查它们不是空字符串,""或者" "
思考像.
arguments = locals()
for item in arguments:
check_attribute(item, arguments[item])
Run Code Online (Sandbox Code Playgroud)
然后检查参数是否不是""," ".但在这种情况下,它也会尝试检查None值(我不想做的事情).
一种典型的方法是:
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)
Run Code Online (Sandbox Code Playgroud)
或者,当然,根据应用程序的语义,如果问题非常严重,您可以发出警告或引发异常.
应该将所有检查委托给单个函数,而不是在你正在检查它的args的函数中循环(后者将在应用程序逻辑的中间坚持"检查代码" - 更好地保持它或者办法...):
def check_arguments(d):
for name, value in d.iteritems():
check_attribute(name, value)
Run Code Online (Sandbox Code Playgroud)
而功能只是:
def f1 (a, b, c=None, d=None):
check_arguments(locals())
...
Run Code Online (Sandbox Code Playgroud)
或者,您可以编写装饰器以便能够编码
@checked_arguments
def f1 (a, b, c=None, d=None):
...
Run Code Online (Sandbox Code Playgroud)
(以便更加 " 检查" 检查代码),但这可能被视为过度杀伤,除非你真的有很多功能需要这种检查!
参数名称内省(虽然可行,但由于模块inspect)在装饰器中远不如函数本身那么简单,这就是为什么我最喜欢的设计方法是在这种情况下避开装饰器方法(简单性非常好;-) .
编辑 - 显示如何实现装饰器,因为OP明确要求一个(虽然没有说明原因).
主要问题(在Python 2.6及更早版本中)是包装器构造一个等效于locals()Python为您提供的映射,但需要在通用包装器中显式完成.
但是 - 如果你使用新的2.7,inspect.getcallargs会为你做到这一点!因此,问题变得更加简单,并且装饰器可能在更多情况下值得做(如果你在2.6或更早的时候,我仍然建议避开装饰器方法,这对于这种专门用途来说会更复杂).
所以,这就是你需要的,在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
Run Code Online (Sandbox Code Playgroud)
2.7之前版本的难度完全来自于实现等效的难度inspect.getcallargs- 所以,我希望,如果你真的需要这种类型的装饰器,你可以简单地下载Python 2.7 www.python.org并将其安装在你的盒子上! - ) (如果你这样做,除了以前任何Python版本之外,你还会获得更多好东西,以及更长的支持周期,因为2.7将被定为Python 2.*系列中的最后一个版本).
为什么你不能用他们的名字来引用价值观?
def f1 (a, b, c=None, d=None):
if not a.strip():
print('a is not empty')
Run Code Online (Sandbox Code Playgroud)
如果您有许多参数,则值得将函数签名更改为:
def f2 (*args, c=None, d=None):
for var in args:
if not var.strip():
raise ValueError('all elements should be non-empty')
Run Code Online (Sandbox Code Playgroud)