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

Joh*_*ohn 10 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)
Run Code Online (Sandbox Code Playgroud)

当我运行这个FuncA和FuncB会没问题,但FuncC错误,got an unexpected keyword argument 'id'因为它不接受任何参数

Kat*_*iel 16

try:
    f(**kwargs)
except TypeError:
    #do stuff
Run Code Online (Sandbox Code Playgroud)

这是更容易请求原谅比许可.

  • 此解决方案的问题是您无法区分"Argument Binding"TypeError与f抛出的TypeError.最好使用[`inspect.Signature.bind`](https://docs.python.org/3/library/inspect.html#inspect.Signature.bind) (8认同)
  • 这样就完成了工作,但是我不禁觉得它很危险。如果您的函数在代码中的任何地方抛出“ TypeError”,则无法从该代码段中得知“ TypeError”是传递无效的“ kwargs”还是逻辑错误。 (4认同)
  • 该解决方案不应该是公认的答案。仅需要检查函数时运行函数并不是用户问题的意图。运行该函数可能很危险,而且肯定是无意的。 (4认同)
  • 抱歉,没有。如果您正确设置** kwargs,它将与_any_非内置函数一起使用。`def foo(x):返回x`,然后返回`foo(** {'x':1})`。 (2认同)

900*_*000 11

def foo(a, b, **kwargs):
  pass

import inspect
args, varargs, varkw, defaults = inspect.getargspec(foo)
assert(varkw=='kwargs')
Run Code Online (Sandbox Code Playgroud)

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

  • 自Python 3.0起,inspect.getargspec()已被弃用,请使用inspect.signature()或inspect.getfullargspec()代替 (2认同)

gmd*_*dev 7

看到这个线程中有很多不同的答案,我想我会给出我的两分钱,使用inspect.signature().

假设你有这个方法:

def foo(**kwargs):
Run Code Online (Sandbox Code Playgroud)

您可以测试是否**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])
Run Code Online (Sandbox Code Playgroud)

更多的

获取方法所采用的参数也是可能的:

import inspect

sig = inspect.signature(foo)
params = sig.parameters.values()
for param in params:
    print(param.kind)
Run Code Online (Sandbox Code Playgroud)

您还可以将它们存储在变量中,如下所示:

kinds = [param.kind for param in params]

# [<_ParameterKind.VAR_KEYWORD: 4>]
Run Code Online (Sandbox Code Playgroud)

除了关键字参数之外,总共有 5 种参数类型,如下所示:

def foo(**kwargs):
Run Code Online (Sandbox Code Playgroud)

官方文档中的描述可以在这里找到。

例子

POSITIONAL_ONLY

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

foo(1) # valid
foo(a=1) #invalid
Run Code Online (Sandbox Code Playgroud)

POSITIONAL_OR_KEYWORD

def foo(a):
# 'a' can be passed via position or keyword
# this is the default and most common parameter kind
Run Code Online (Sandbox Code Playgroud)

VAR_POSITIONAL

def foo(*args):
Run Code Online (Sandbox Code Playgroud)

KEYWORD_ONLY

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

foo(a=1) # valid
foo(1) # invalid
Run Code Online (Sandbox Code Playgroud)

VAR_KEYWORD

def foo(**kwargs):
Run Code Online (Sandbox Code Playgroud)


rus*_*nov 6

对于 python > 3,您应该使用spect.getfullargspec

import inspect

def foo(**bar):
    pass

arg_spec = inspect.getfullargspec(foo)
assert arg_spec.varkw and arg_spec.varkw == 'bar'
Run Code Online (Sandbox Code Playgroud)


spe*_*hil 5

func 是有问题的功能。

使用python2,它是:

inspect.getargspec(func).keywords is not None
Run Code Online (Sandbox Code Playgroud)

python3有一些技巧,以下https://www.python.org/dev/peps/pep-0362/kind参数必须是VAR_KEYWORD

Parameter.VAR_KEYWORD-未绑定到任何其他参数的关键字参数的字典。这对应于Python函数定义中的“ ** kwargs”参数。

any(param for param in inspect.signature(func).parameters.values() if param.kind == param.VAR_KEYWORD)
Run Code Online (Sandbox Code Playgroud)