你能列出一个函数收到的关键字参数吗?

时间:2021-08-05 23:21:33

I have a dict, which I need to pass key/values as keyword arguments.. For example..

我有一个字典,我需要传递键/值作为关键字参数..例如..

d_args = {'kw1': 'value1', 'kw2': 'value2'}
example(**d_args)

This works fine, but if there are values in the d_args dict that are not accepted by the example function, it obviously dies.. Say, if the example function is defined as def example(kw2):

这样可以正常工作,但是如果d_args dict中的值没有被示例函数接受,那么它显然会死掉。比如,如果示例函数被定义为def示例(kw2):

This is a problem since I don't control either the generation of the d_args, or the example function.. They both come from external modules, and example only accepts some of the keyword-arguments from the dict..

这是一个问题,因为我不控制d_args的生成或示例函数..它们都来自外部模块,示例只接受来自dict的一些关键字参数。

Ideally I would just do

理想情况下我会这样做

parsed_kwargs = feedparser.parse(the_url)
valid_kwargs = get_valid_kwargs(parsed_kwargs, valid_for = PyRSS2Gen.RSS2)
PyRSS2Gen.RSS2(**valid_kwargs)

I will probably just filter the dict, from a list of valid keyword-arguments, but I was wondering: Is there a way to programatically list the keyword arguments the a specific function takes?

我可能只是从有效的关键字参数列表中过滤dict,但我想知道:有没有办法以编程方式列出特定函数所需的关键字参数?

5 个解决方案

#1


118  

A little nicer than inspecting the code object directly and working out the variables is to use the inspect module.

比直接检查代码对象和计算变量要好一点就是使用inspect模块。

>>> import inspect
>>> def func(a,b,c=42, *args, **kwargs): pass
>>> inspect.getargspec(func)
(['a', 'b', 'c'], 'args', 'kwargs', (42,))

If you want to know if its callable with a particular set of args, you need the args without a default already specified. These can be got by:

如果你想知道它是否可以用一组特定的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.

Then a function to tell what you are missing from your particular dict is:

然后,一个函数告诉你特定字典中缺少的是:

def missingArgs(func, argdict):
    return set(getRequiredArgs(func)).difference(argdict)

Similarly, to check for invalid args, use:

同样,要检查无效的args,请使用:

def invalidArgs(func, argdict):
    args, varargs, varkw, defaults = inspect.getargspec(func)
    if varkw: return set()  # All accepted
    return set(argdict) - set(args)

And so a full test if it is callable is :

因此,如果它是可调用的完整测试是:

def isCallableWithArgs(func, argdict):
    return not missingArgs(func, argdict) and not invalidArgs(func, argdict)

(This is good only as far as python's arg parsing. Any runtime checks for invalid values in kwargs obviously can't be detected.)

(只有python的arg解析才有用。显然无法检测到kwargs中无效值的任何运行时检查。)

#2


28  

This will print names of all passable arguments, keyword and non-keyword ones:

这将打印所有可通过参数,关键字和非关键字参数的名称:

def func(one, two="value"):
    y = one, two
    return y
print func.func_code.co_varnames[:func.func_code.co_argcount]

This is because first co_varnames are always parameters (next are local variables, like y in the example above).

这是因为第一个co_varnames总是参数(接下来是局部变量,如上例中的y)。

So now you could have a function:

所以现在你可以有一个功能:

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)

Which you then could use like this:

你可以这样使用:

>>> func(**getValidArgs(func, args))

EDIT: A small addition: if you really need only keyword arguments of a function, you can use the func_defaults attribute to extract them:

编辑:一个小小的补充:如果你真的只需要一个函数的关键字参数,你可以使用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)

You could now call your function with known args, but extracted kwargs, e.g.:

你现在可以使用已知的args调用你的函数,但是提取的kwargs,例如:

func(param1, param2, **getValidKwargs(func, kwargsDict))

This assumes that func uses no *args or **kwargs magic in its signature.

这假设func在其签名中不使用* args或** kwargs magic。

#3


6  

In Python 3.0:

在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={})

#4


3  

Extending DzinX's answer:

扩展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


1  

For a Python 3 solution, you can use inspect.signature and filter according to the kind of parameters you'd like to know about.

对于Python 3解决方案,您可以根据您想要了解的参数类型使用inspect.signature和filter。

Taking a sample function with positional or keyword, keyword-only, var positional and var keyword parameters:

使用位置或关键字,仅关键字,var位置和var关键字参数采样示例函数:

def spam(a, b=1, *args, c=2, **kwargs):
    print(a, b, args, c, kwargs)

You can create a signature object for it:

您可以为它创建签名对象:

from inspect import signature
sig =  signature(spam)

and then filter with a list comprehension to find out the details you need:

然后使用列表推导过滤以找出所需的详细信息:

>>> # 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']

and, similarly, for var positionals using p.VAR_POSITIONAL and var keyword with VAR_KEYWORD.

类似地,对于使用p.VAR_POSITIONAL的var位置和使用VAR_KEYWORD的var关键字。

In addition, you can add a clause to the if to check if a default value exists by checking if p.default equals p.empty.

此外,您可以通过检查p.default是否等于p.empty来向if添加子句以检查是否存在默认值。

#1


118  

A little nicer than inspecting the code object directly and working out the variables is to use the inspect module.

比直接检查代码对象和计算变量要好一点就是使用inspect模块。

>>> import inspect
>>> def func(a,b,c=42, *args, **kwargs): pass
>>> inspect.getargspec(func)
(['a', 'b', 'c'], 'args', 'kwargs', (42,))

If you want to know if its callable with a particular set of args, you need the args without a default already specified. These can be got by:

如果你想知道它是否可以用一组特定的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.

Then a function to tell what you are missing from your particular dict is:

然后,一个函数告诉你特定字典中缺少的是:

def missingArgs(func, argdict):
    return set(getRequiredArgs(func)).difference(argdict)

Similarly, to check for invalid args, use:

同样,要检查无效的args,请使用:

def invalidArgs(func, argdict):
    args, varargs, varkw, defaults = inspect.getargspec(func)
    if varkw: return set()  # All accepted
    return set(argdict) - set(args)

And so a full test if it is callable is :

因此,如果它是可调用的完整测试是:

def isCallableWithArgs(func, argdict):
    return not missingArgs(func, argdict) and not invalidArgs(func, argdict)

(This is good only as far as python's arg parsing. Any runtime checks for invalid values in kwargs obviously can't be detected.)

(只有python的arg解析才有用。显然无法检测到kwargs中无效值的任何运行时检查。)

#2


28  

This will print names of all passable arguments, keyword and non-keyword ones:

这将打印所有可通过参数,关键字和非关键字参数的名称:

def func(one, two="value"):
    y = one, two
    return y
print func.func_code.co_varnames[:func.func_code.co_argcount]

This is because first co_varnames are always parameters (next are local variables, like y in the example above).

这是因为第一个co_varnames总是参数(接下来是局部变量,如上例中的y)。

So now you could have a function:

所以现在你可以有一个功能:

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)

Which you then could use like this:

你可以这样使用:

>>> func(**getValidArgs(func, args))

EDIT: A small addition: if you really need only keyword arguments of a function, you can use the func_defaults attribute to extract them:

编辑:一个小小的补充:如果你真的只需要一个函数的关键字参数,你可以使用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)

You could now call your function with known args, but extracted kwargs, e.g.:

你现在可以使用已知的args调用你的函数,但是提取的kwargs,例如:

func(param1, param2, **getValidKwargs(func, kwargsDict))

This assumes that func uses no *args or **kwargs magic in its signature.

这假设func在其签名中不使用* args或** kwargs magic。

#3


6  

In Python 3.0:

在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={})

#4


3  

Extending DzinX's answer:

扩展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


1  

For a Python 3 solution, you can use inspect.signature and filter according to the kind of parameters you'd like to know about.

对于Python 3解决方案,您可以根据您想要了解的参数类型使用inspect.signature和filter。

Taking a sample function with positional or keyword, keyword-only, var positional and var keyword parameters:

使用位置或关键字,仅关键字,var位置和var关键字参数采样示例函数:

def spam(a, b=1, *args, c=2, **kwargs):
    print(a, b, args, c, kwargs)

You can create a signature object for it:

您可以为它创建签名对象:

from inspect import signature
sig =  signature(spam)

and then filter with a list comprehension to find out the details you need:

然后使用列表推导过滤以找出所需的详细信息:

>>> # 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']

and, similarly, for var positionals using p.VAR_POSITIONAL and var keyword with VAR_KEYWORD.

类似地,对于使用p.VAR_POSITIONAL的var位置和使用VAR_KEYWORD的var关键字。

In addition, you can add a clause to the if to check if a default value exists by checking if p.default equals p.empty.

此外,您可以通过检查p.default是否等于p.empty来向if添加子句以检查是否存在默认值。