Can you list the keyword arguments a function receives?
我有一个字典,我需要传递键/值作为关键字参数..例如..
1 2 | d_args = {'kw1': 'value1', 'kw2': 'value2'} example(**d_args) |
这样可以正常工作,但是如果d_args dict中的值不被
这是一个问题,因为我不控制
理想情况下我会这样做
1 2 3 | parsed_kwargs = feedparser.parse(the_url) valid_kwargs = get_valid_kwargs(parsed_kwargs, valid_for = PyRSS2Gen.RSS2) PyRSS2Gen.RSS2(**valid_kwargs) |
我可能只是从有效的关键字参数列表中过滤掉dict,但我想知道:有没有办法以编程方式列出特定函数所需的关键字参数?
比直接检查代码对象和计算变量要好一点就是使用inspect模块。
1 2 3 4 | >>> import inspect >>> def func(a,b,c=42, *args, **kwargs): pass >>> inspect.getargspec(func) (['a', 'b', 'c'], 'args', 'kwargs', (42,)) |
如果你想知道它是否可以用一组特定的args调用,你需要没有指定默认值的args。这些可以通过:
1 2 3 4 5 | def getRequiredArgs(func): args, varargs, varkw, defaults = inspect.getargspec(func) if defaults: args = args[:-len(defaults)] return args # *args and **kwargs are not required, so ignore them. |
然后,一个函数告诉你特定字典中缺少的是:
1 2 | def missingArgs(func, argdict): return set(getRequiredArgs(func)).difference(argdict) |
同样,要检查无效的args,请使用:
1 2 3 4 | def invalidArgs(func, argdict): args, varargs, varkw, defaults = inspect.getargspec(func) if varkw: return set() # All accepted return set(argdict) - set(args) |
因此,如果它是可调用的完整测试是:
1 2 | def isCallableWithArgs(func, argdict): return not missingArgs(func, argdict) and not invalidArgs(func, argdict) |
(只有python的arg解析才有用。显然无法检测到kwargs中无效值的任何运行时检查。)
这将打印所有可通过参数的名称,关键字和非关键字参数:
1 2 3 4 | def func(one, two="value"): y = one, two return y print func.func_code.co_varnames[:func.func_code.co_argcount] |
这是因为第一个
所以现在你可以有一个功能:
1 2 3 4 5 | def getValidArgs(func, argsDict): '''Return dictionary without invalid function arguments.''' validArgs = func.func_code.co_varnames[:func.func_code.co_argcount] return dict((key, value) for key, value in argsDict.iteritems() if key in validArgs) |
你可以这样使用:
1 | >>> func(**getValidArgs(func, args)) |
编辑:一个小小的补充:如果你真的只需要一个函数的关键字参数,你可以使用
1 2 3 4 5 6 | def getValidKwargs(func, argsDict): validArgs = func.func_code.co_varnames[:func.func_code.co_argcount] kwargsLen = len(func.func_defaults) # number of keyword arguments validKwargs = validArgs[-kwargsLen:] # because kwargs are last return dict((key, value) for key, value in argsDict.iteritems() if key in validKwargs) |
你现在可以用已知的args调用你的函数,但是提取的kwargs,例如:
1 | func(param1, param2, **getValidKwargs(func, kwargsDict)) |
这假设
在Python 3.0中:
1 2 3 4 5 6 | >>> import inspect >>> import fileinput >>> print(inspect.getfullargspec(fileinput.input)) FullArgSpec(args=['files', 'inplace', 'backup', 'bufsize', 'mode', 'openhook'], varargs=None, varkw=None, defaults=(None, 0, '', 0, 'r', None), kwonlyargs=[], kwdefaults=None, annotations={}) |
对于Python 3解决方案,您可以使用
使用位置或关键字,仅关键字,var位置和var关键字参数采样示例函数:
1 2 | def spam(a, b=1, *args, c=2, **kwargs): print(a, b, args, c, kwargs) |
您可以为它创建签名对象:
1 2 | from inspect import signature sig = signature(spam) |
然后使用列表推导过滤以找出所需的详细信息:
1 2 3 4 5 6 | >>> # positional or keyword >>> [p.name for p in sig.parameters.values() if p.kind == p.POSITIONAL_OR_KEYWORD] ['a', 'b'] >>> # keyword only >>> [p.name for p in sig.parameters.values() if p.kind == p.KEYWORD_ONLY] ['c'] |
类似地,对于使用
此外,您可以通过检查
扩展DzinX的答案:
1 2 3 | argnames = example.func_code.co_varnames[:func.func_code.co_argcount] args = dict((key, val) for key,val in d_args.iteritems() if key in argnames) example(**args) |