Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/ant/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
python检查函数是否接受**kwargs_Python - Fatal编程技术网

python检查函数是否接受**kwargs

python检查函数是否接受**kwargs,python,Python,是否有方法在调用函数之前检查函数是否接受**kwargs,例如 def FuncA(**kwargs): print 'ok' def FuncB(id = None): print 'ok' def FuncC(): print 'ok' args = {'id': '1'} FuncA(**args) FuncB(**args) FuncC(**args) 当我运行这个FuncA和FuncB时,这是可以的,但是带有的FuncC错误得到了一个意外的关键字参数“

是否有方法在调用函数之前检查函数是否接受**kwargs,例如

def FuncA(**kwargs):
    print 'ok'

def FuncB(id = None):
    print 'ok'

def FuncC():
    print 'ok'

args = {'id': '1'}

FuncA(**args)
FuncB(**args)
FuncC(**args)
当我运行这个FuncA和FuncB时,这是可以的,但是带有
的FuncC错误得到了一个意外的关键字参数“id”
,因为它不接受任何参数

try:
    f(**kwargs)
except TypeError:
    #do stuff
是的


这只适用于Python函数。在C扩展(和内置)中定义的函数可能很棘手,有时会以非常有创意的方式解释它们的参数。无法可靠地检测此类函数所期望的参数。请参阅函数的docstring和其他人类可读文档。

您似乎想检查函数是否接收到“id”关键字参数。您不能通过检查来真正做到这一点,因为该函数可能不是正常函数,或者您可能遇到这样的情况:

def f(*args, **kwargs):
    return h(*args, **kwargs)

g = lambda *a, **kw: h(*a, **kw)

def h(arg1=0, arg2=2):
    pass
f(id=3)
仍然失败

按照建议捕获
TypeError
是最好的方法,但您无法真正找出导致
TypeError
的原因。例如,这仍然会引发
类型错误

def f(id=None):
     return "%d" % id

f(**{'id': '5'})
这可能是您要调试的错误。如果您正在进行检查以避免函数的某些副作用,那么如果您发现它,它们可能仍然存在。例如:

class A(object):
   def __init__(self): self._items = set([1,2,3])
   def f(self, id): return self._items.pop() + id

a = A()
a.f(**{'id': '5'})
我的建议是尝试通过另一种机制来确定这些功能。例如,使用方法而不是函数传递对象,并仅调用具有特定方法的对象。或向对象或函数本身添加标志。

根据 您应该能够使用
co_标志测试
**kwargs
的使用情况:

>>> def blah(a, b, kwargs):
...     pass

>>> def blah2(a, b, **kwargs):
...     pass

>>> (blah.func_code.co_flags & 0x08) != 0
False
>>> (blah2.func_code.co_flags & 0x08) != 0
True

不过,正如参考文献中所指出的,这可能会在将来发生变化,因此我建议您一定要格外小心。一定要添加一些单元测试来检查此功能是否仍然存在。

func
是有问题的函数

对于python2,它是:

inspect.getargspec(func).keywords is not None
python3有点诡计多端,参数的
kind
后面必须是
VAR\u关键字

def foo(a):
# 'a' can be passed via position or keyword
# this is the default and most common parameter kind
def foo(**kwargs):
Parameter.VAR_关键字-不绑定到任何其他参数的关键字参数的dict。这对应于Python函数定义中的“**kwargs”参数


对于python>3,您应该使用

导入检查
def foo(**巴):
通过
arg_spec=inspect.getfullargspec(foo)
断言arg_spec.varkw和arg_spec.varkw=='bar'

看到这个帖子中有很多不同的答案,我想我会用
inspect.signature()
给自己两分钱

假设您有以下方法:

def foo(**kwargs):
您可以测试此方法的签名中是否有
**kwargs

import inspect

sig = inspect.signature(foo)
params = sig.parameters.values()
has_kwargs = any([True for p in params if p.kind == p.VAR_KEYWORD])
更多 也可以获取方法采用的参数:

import inspect

sig = inspect.signature(foo)
params = sig.parameters.values()
for param in params:
    print(param.kind)
也可以将它们存储在变量中,如下所示:

kinds = [param.kind for param in params]

# [<_ParameterKind.VAR_KEYWORD: 4>]
可以在官方文件中找到说明

例子
POSITIONAL\u仅限

def foo(a, /): 
# the '/' enforces that all preceding parameters must be positional

foo(1) # valid
foo(a=1) #invalid
def foo(*, a):
# the '*' enforces that all following parameters must by keyworded

foo(a=1) # valid
foo(1) # invalid

POSITIONAL\u或\u关键字

def foo(a):
# 'a' can be passed via position or keyword
# this is the default and most common parameter kind
def foo(**kwargs):

VAR\u POSITIONAL

def foo(*args):

仅限关键字

def foo(a, /): 
# the '/' enforces that all preceding parameters must be positional

foo(1) # valid
foo(a=1) #invalid
def foo(*, a):
# the '*' enforces that all following parameters must by keyworded

foo(a=1) # valid
foo(1) # invalid

VAR\u关键字

def foo(a):
# 'a' can be passed via position or keyword
# this is the default and most common parameter kind
def foo(**kwargs):

“请求原谅比允许更容易”+1是的,应该是,修好了。干杯。抱歉,不行。如果您制作的是
**kwargs
正确,这将适用于任何非内置函数
def foo(x):返回x
然后
foo(**{x':1})
。这样就完成了任务,但我忍不住觉得它很危险。如果您的函数在代码中的任何位置抛出一个
TypeError
,则无法从该代码段中知道
TypeError
是传递无效的
kwargs
还是逻辑中的错误。此解决方案的问题是您无法区分“参数绑定”TypeError和f抛出的TypeError。如果您使用的是检查,那么最好使用关键字参数的名称是不相关的,并且您没有检查命名参数
varkw不是None,或者args中的“id”应该是它的样子。是的,名称不相关。存在是相关的。尝试在没有
**kwarg的情况下检查功能
VARW
将为
None
。我想您应该使用实际的解释器来检查代码示例。如果只是存在不相关,为什么要给出一个检查名称的示例?EAFP在很多方面都很好,但是如果您“盲目”运行函数,而不知道其确切签名,而不进行检查,这个答案更可靠。inspect.getargspec()在Python 3.0中被弃用,请使用inspect.signature()或inspect.getfullargspec()代替它。如果函数是否接受kwargs非常重要,为什么您还不知道呢?如果它不是特别重要,那么就按照建议尝试一下。我在参考资料中没有看到任何东西说它将来可能会改变,甚至没有说它是特定于实现的。我看到的最接近警告注释的是:“co_标志中的其他位保留供内部使用。”