你能列出函数接收的关键字参数吗?

发布于 2024-07-06 10:01:44 字数 649 浏览 5 评论 0原文

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

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

这工作正常,但是如果 d_args 字典中存在 example 函数,它显然死了.. 比如说,如果示例函数被定义为 def example(kw2):

这是一个问题,因为我不控制d_argsexample 函数。它们都来自外部模块,并且 example 只接受字典中的一些关键字参数。理想

情况下,

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

我可能只是从有效关键字参数列表中过滤字典,但我想知道:是否有一种方法可以以编程方式列出特定函数所采用的关键字参数? >

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

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

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

数理化全能战士 2024-07-13 10:01:44

比直接检查代码对象并计算变量更好一点的是使用检查模块。

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

如果您想知道它是否可以使用一组特定的参数进行调用,则需要未指定默认值的参数。 这些可以通过以下方式获得:

def get_required_args(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 missing_args(func, argdict):
    return set(get_required_args(func)).difference(argdict)

类似地,要检查无效参数,请使用:

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

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

def is_callable_with_args(func, argdict):
    return not missing_args(func, argdict) and not invalid_args(func, argdict)

这仅在以下情况下才有效python 的 arg 解析。显然无法检测到 kwargs 中的任何运行时检查。)

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:

def get_required_args(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 missing_args(func, argdict):
    return set(get_required_args(func)).difference(argdict)

Similarly, to check for invalid args, use:

def invalid_args(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 is_callable_with_args(func, argdict):
    return not missing_args(func, argdict) and not invalid_args(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.)

情魔剑神 2024-07-13 10:01:44

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

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 get_valid_args(func, args_dict):
    '''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 args_dict.iteritems() 
                if key in validArgs)

然后你可以像这样使用它:

>>> func(**get_valid_args(func, args))

如果你真的只需要函数的关键字参数,你可以使用func_defaults属性来提取它们:

def get_valid_kwargs(func, args_dict):
    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 args_dict.iteritems() 
                if key in validKwargs)

您现在可以使用已知的参数调用函数,但提取了 kwargs,例如:

func(param1, param2, **get_valid_kwargs(func, kwargs_dict))

这假设 func 不使用 *args**kwargs它的签名充满魔力。

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).

So now you could have a function:

def get_valid_args(func, args_dict):
    '''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 args_dict.iteritems() 
                if key in validArgs)

Which you then could use like this:

>>> func(**get_valid_args(func, args))

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

def get_valid_kwargs(func, args_dict):
    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 args_dict.iteritems() 
                if key in validKwargs)

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

func(param1, param2, **get_valid_kwargs(func, kwargs_dict))

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

夜空下最亮的亮点 2024-07-13 10:01:44

对于 Python 3 解决方案,您可以使用 inspect.signature并根据 参数类型进行过滤< /a> 你想知道的。

获取带有位置或关键字、仅关键字、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']

同样,对于 var使用 p.VAR_POSITIONAL 的位置和使用 VAR_KEYWORD 的 var 关键字。

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

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

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

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.

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.

£烟消云散 2024-07-13 10:01:44

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

In 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={})
日裸衫吸 2024-07-13 10:01:44

只需将其用作函数名称“myfun”:

myfun.__code__.co_varnames

Just use this for a function name 'myfun':

myfun.__code__.co_varnames
↙温凉少女 2024-07-13 10:01:44

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

Extending DzinX's answer:

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)
黯然 2024-07-13 10:01:44

没有经过太多测试,但这适用于我的情况:

import inspect


def example(arg_1: int, arg_2: list, arg_optional="Hello", *, kwarg, kwarg_optional="Hi"):
    pass


spec = inspect.getfullargspec(example)

args_required = spec.args
args_optional = args_required[-len(spec.defaults or []):]
args_required = args_required[:-len(args_optional)]

kwargs_required, kwargs_optional = spec.kwonlyargs, (spec.kwonlydefaults or {})
kwargs_required = [key for key in kwargs_required if key not in kwargs_optional]

unlimited_args, unlimited_kwargs = bool(spec.varargs), bool(spec.varkw)
annotations = spec.annotations

print(args_required, args_optional, kwargs_required, kwargs_optional, unlimited_args, unlimited_kwargs, annotations)

Not tested a lot but this will work for my case:

import inspect


def example(arg_1: int, arg_2: list, arg_optional="Hello", *, kwarg, kwarg_optional="Hi"):
    pass


spec = inspect.getfullargspec(example)

args_required = spec.args
args_optional = args_required[-len(spec.defaults or []):]
args_required = args_required[:-len(args_optional)]

kwargs_required, kwargs_optional = spec.kwonlyargs, (spec.kwonlydefaults or {})
kwargs_required = [key for key in kwargs_required if key not in kwargs_optional]

unlimited_args, unlimited_kwargs = bool(spec.varargs), bool(spec.varkw)
annotations = spec.annotations

print(args_required, args_optional, kwargs_required, kwargs_optional, unlimited_args, unlimited_kwargs, annotations)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文