简体   繁体   中英

Python: Making a function signature with inspect

I'm having trouble figuring out how I should be building a signature manually. The docs say that the parameters argument of inspect.Signature should be an OrderedDict . But that fails for me.

Even the parameters in an inspect.Signature instance, returned by the inspect.signature function don't play well as an __init__ argument:

>>> from inspect import Signature, signature
>>> def f(a, b: int, c=0, d: float=0.0): ...
...
>>> Signature(signature(f).parameters)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/twhalen/.pyenv/versions/3.8.2/lib/python3.8/inspect.py", line 2775, in __init__
    kind = param.kind
AttributeError: 'str' object has no attribute 'kind'

But Signature(signature(f).parameters.values()) works fine. Yet type(signature(f).parameters.values()) tells me it's an odict_values , not an OrderedDict as the docs say.

How should one construct a parameters argument for inspect.Signature ?

Is the misalignment between inspect 's documentation and the truth of the code just that, or is there some profound reason I'm missing?

You are missing something important (but not very profound). The documentation for the class attribute parameters reads

An ordered mapping of parameters' names to the corresponding Parameter objects. Parameters appear in strict definition order, including keyword-only parameters.

However this the output of the class initializer. The documentation for the __init__ argument parameters reads:

The optional parameters argument is a sequence of Parameter objects, which is validated to check that there are no parameters with duplicate names, and that the parameters are in the right order, ie positional-only first, then positional-or-keyword, and that parameters with defaults follow parameters without defaults.

The input is expected to be a sequence, not a mapping. The output is an ordered mapping in the Signature object. The Signature class is really not meant to be initialized "by hand" unless you have a special case where you need to.

The type odict_values represents the result of a call to OrderedDict.values . It is a sequence, which is why that particular call works. You can print the ordered dictionary to get a better sense of what's happening:

>>> signature(f).parameters
mappingproxy(OrderedDict([('a', <Parameter "a">), ('b', <Parameter "b: int">), ('c', <Parameter "c=0">), ('d', <Parameter "d: float = 0.0">)]))

You can ignore the mappingproxy : it just makes the whole thing read-only. Signature 's initializer does not need the mapping because Parameter objects already contain the name of the parameter.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM