您能列出Python函数接收到的关键字参数吗?

时间:2022-04-01 05:21:29

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

我有一个命令,我需要传递key/values作为关键字参数。例如. .

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命令中有不被示例函数所接受的值,它显然会死。例如,如果将示例函数定义为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的生成,也不控制示例函数。它们都来自外部模块,示例只接受来自命令的一些关键字参数。

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?

我可能会从一个有效的关键字参数列表中过滤这个命令,但是我想知道:是否有一种方法可以编程列出一个特定函数所需要的关键字参数?

5 个解决方案

#1


116  

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

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

>>> 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:

如果您想知道它的callable是否具有特定的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魔法。

#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


0  

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解决方案,您可以使用检查。根据您想了解的参数,签名和筛选。

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位置。var_position和var关键字与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.

此外,您可以在if中添加一个子句,以检查是否存在默认值。

#1


116  

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

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

>>> 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:

如果您想知道它的callable是否具有特定的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魔法。

#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


0  

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解决方案,您可以使用检查。根据您想了解的参数,签名和筛选。

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位置。var_position和var关键字与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.

此外,您可以在if中添加一个子句,以检查是否存在默认值。