我有一个dict,我需要将键/值作为关键字参数传递。例如..
d_args = {'kw1': 'value1', 'kw2': 'value2'}
example(**d_args)
这很好,但如果d_args dict中的值不被example
函数接受,它显然会死掉。比如说,如果示例函数定义为def example(kw2):
这是一个问题,因为我无法控制d_args
或example
函数的生成..它们都来自外部模块,example
只接受一些来自dict的关键字参数..
理想情况下我会做
parsed_kwargs = feedparser.parse(the_url)
valid_kwargs = get_valid_kwargs(parsed_kwargs, valid_for = PyRSS2Gen.RSS2)
PyRSS2Gen.RSS2(**valid_kwargs)
我可能只是从有效的关键字参数列表中过滤dict,但我想知道:有没有办法以编程方式列出特定函数所需的关键字参数?
答案 0 :(得分:137)
比直接检查代码对象并计算变量要好一点就是使用inspect模块。
>>> import inspect
>>> def func(a,b,c=42, *args, **kwargs): pass
>>> inspect.getargspec(func)
(['a', 'b', 'c'], 'args', 'kwargs', (42,))
如果你想知道它是否可以用一组特定的args调用,你需要没有指定默认值的args。这些可以通过以下方式获得:
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.
然后,一个函数告诉你特定字典中缺少的是:
def missingArgs(func, argdict):
return set(getRequiredArgs(func)).difference(argdict)
同样,要检查无效的args,请使用:
def invalidArgs(func, argdict):
args, varargs, varkw, defaults = inspect.getargspec(func)
if varkw: return set() # All accepted
return set(argdict) - set(args)
如果它是可调用的,那么完整的测试是:
def isCallableWithArgs(func, argdict):
return not missingArgs(func, argdict) and not invalidArgs(func, argdict)
(仅在python的arg解析时这是好的。显然无法检测到kwargs中无效值的任何运行时检查。)
答案 1 :(得分:30)
这将打印所有可通过参数的名称,关键字和非关键字参数:
def func(one, two="value"):
y = one, two
return y
print func.func_code.co_varnames[:func.func_code.co_argcount]
这是因为第一个co_varnames
始终是参数(接下来是局部变量,如上例中的y
)。
所以现在你可以有一个功能:
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)
然后你可以这样使用:
>>> func(**getValidArgs(func, args))
编辑:一个小小的补充:如果你确实只需要一个函数的关键字参数,你可以使用func_defaults
属性来提取它们:
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,例如:
func(param1, param2, **getValidKwargs(func, kwargsDict))
这假定func
在其签名中不使用*args
或**kwargs
魔法。
答案 2 :(得分:6)
在Python 3.0中:
>>> 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={})
答案 3 :(得分:4)
对于Python 3解决方案,您可以使用inspect.signature
并根据您想了解的the kind of parameters进行过滤。
采用位置或关键字,仅关键字,var位置和var关键字参数的示例函数:
def spam(a, b=1, *args, c=2, **kwargs):
print(a, b, args, c, kwargs)
您可以为它创建签名对象:
from inspect import signature
sig = signature(spam)
然后使用列表推导过滤以找出所需的详细信息:
>>> # 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']
,类似地,对于使用p.VAR_POSITIONAL
的var位置和使用VAR_KEYWORD
的var关键字。
此外,您可以通过检查p.default
是否等于p.empty
来为if添加一个子句以检查是否存在默认值。
答案 4 :(得分:3)
扩展DzinX的答案:
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)
答案 5 :(得分:0)
只需将其用于函数名称“myfun”:
myfun.__code__.co_varnames