确定函数的参数和关键字参数

Ana*_*bus 4 python parameters functional-programming function signature

如何确定函数调用的有效形式?

例如,假设我们有一个函数info可以完成此任务;info 可能会像这样工作(我愿意接受有关任何可能更完整且更一致的方式来表示返回信息的建议):

def foo():
    pass

info(foo)
# { 'args': (), 'kwargs': {} }

def bar(a):
    pass

info(bar)
# { 'args': ('a',), 'kwargs': {} }

def baz(a, b=42):
    pass

info(baz)
# { 'args': ('a',), 'kwargs': { 'b': 42 } }

def qux(a, *args, b=42, **kwargs):
    pass

info(qux)
# { 'args': ('a',), 'kwargs': { 'b': 42 }, 'optional': {'*args', '**kwargs'} }
Run Code Online (Sandbox Code Playgroud)

info函数应该适用于任何函数。我不确定如何为每个模式编写示例返回:例如,help(range.__init__)显示

# __init__(self, /, *args`, **kwargs)
Run Code Online (Sandbox Code Playgroud)

我不确定这/意味着什么。

的返回info需要是经过计算(以合理的努力)以产生对 的参数的任意、正确调用的东西info,例如,用于随机测试。

Cyt*_*rak 8

已经有一个用于此目的的函数,inspect.getfullargspec它返回namedtuples

>>> import inspect
>>> inspect.getfullargspec(foo)
FullArgSpec(args=[], varargs=None, varkw=None, defaults=None, kwonlyargs=[], kwonlydefaults=None, annotations={})
>>> inspect.getfullargspec(qux)
FullArgSpec(args=['a'], varargs='args', varkw='kwargs', defaults=None, kwonlyargs=['b'], kwonlydefaults={'b': 42}, annotations={})
>>> inspect.getfullargspec(bar)
FullArgSpec(args=['a'], varargs=None, varkw=None, defaults=None, kwonlyargs=[], kwonlydefaults=None, annotations={})
>>> inspect.getfullargspec(baz)
FullArgSpec(args=['a', 'b'], varargs=None, varkw=None, defaults=(42,), kwonlyargs=[], kwonlydefaults=None, annotations={})
Run Code Online (Sandbox Code Playgroud)

但是,如果您愿意,您可以从此构建一个函数:

def info(func):
    """returns function argument info"""
    specs = inspect.getfullargspec(func)
    dict_ = {}
    dict_['args'] = tuple(specs.args)
    dict_['kwargs'] = {} if specs.kwonlydefaults is None else specs.kwonlydefaults
    dict_['optional'] = set()
    dict_['defaults'] = {} if specs.defaults is None else specs.defaults
    if specs.varargs is not None:
        dict_['optional'].add(f"*{specs.varargs}")
    if specs.varkw is not None:
        dict_['optional'].add(f"*{specs.varkw}")
    if not dict_['optional']:
        dict_['optional'] = {}
    return dict_

>>> info(foo)
{'args': (), 'kwargs': {}, 'optional': {}, 'defaults': {}}

>>> info(qux)
{'args': ('a',), 'kwargs': {'b': 42}, 'optional': {'*args', '*kwargs'}, 'defaults': {}}

>>> info(bar)
{'args': ('a',), 'kwargs': {}, 'optional': {}, 'defaults': {}}

>> info(baz)
{'args': ('a', 'b'), 'kwargs': {}, 'optional': {}, 'defaults': (42,)}
Run Code Online (Sandbox Code Playgroud)

in不是关键字参数,它是默认参数42baz因为调用时不需要提供关键字b

*的 tohelp(__init__)关键字仅指后面的参数,即它告诉后面的参数必须是keyword-only参数,类似地,前面的任何参数都/必须是positional argument,更多信息请参见PEP457, PEP570, PEP3102

其中许多信息可以从code函数的固有对象中获得,该对象具有以下属性:

for attr in dir(qux.__code__):
    if not attr.startswith('_'):
        print(attr,':',getattr(qux.__code__, attr))

co_argcount : 1
co_cellvars : ()
co_code : b'd\x00S\x00'
co_consts : (None,)
co_filename : <ipython-input-43-6608913c4d65>
co_firstlineno : 1
co_flags : 79
co_freevars : ()
co_kwonlyargcount : 1
co_lnotab : b'\x00\x01'
co_name : qux
co_names : ()
co_nlocals : 4
co_stacksize : 1
co_varnames : ('a', 'b', 'args', 'kwargs')
Run Code Online (Sandbox Code Playgroud)

然而,这些描述性不够,也不易于访问,也不适合 python 内部使用。因此,除非您绝对需要自定义函数,否则inspect.getfullargspec这可能是最好的选择。

fullargspec作为 a的输出,namedtuple您可以轻松访问不同的字段:

>>> argspecs = inspect.getfullargspec(qux)
>>> argspecs.args
['a']
>>> argspecs.kwonlydefaults
{'b': 42}
Run Code Online (Sandbox Code Playgroud)

如果你想要一个字典,你可以调用_asdict结果的方法namedtuple

>>> inspect.getfullargspec(qux)._asdict()  #gives OrderedDict
OrderedDict([('args', ['a']),
             ('varargs', 'args'),
             ('varkw', 'kwargs'),
             ('defaults', None),
             ('kwonlyargs', ['b']),
             ('kwonlydefaults', {'b': 42}),
             ('annotations', {})])
>>> dict(inspect.getfullargspec(qux)._asdict()) #call dict to get regular dict
{'args': ['a'],
 'varargs': 'args',
 'varkw': 'kwargs',
 'defaults': None,
 'kwonlyargs': ['b'],
 'kwonlydefaults': {'b': 42},
 'annotations': {}}
Run Code Online (Sandbox Code Playgroud)

  • 谢谢。对于任何其他提问者:当搜索 [inspect.getfullargspec with the python tag](https://stackoverflow.com/search?q=%5Bpython%5D+inspect.getfullargspec) 时,可以在 StackOverflow 上找到更多内容, _现在我知道要搜索什么了_。谢谢。 (2认同)