给定函数的位置参数的名称,可以确定参数的位置吗?

jcs*_*nt0 2 python python-3.x

我正在研究玩具Python类型检查器,使用Python 3中的函数注释功能来定义函数参数和返回值的类型,我似乎在检查一个函数类型是否是另一个函数类型的子类型时遇到了问题.采取这两个功能:

def f(x: int, y: int) -> type(None):
    pass

def g(a: object, b: int) -> type(None):
    pass
Run Code Online (Sandbox Code Playgroud)

我想让我的代码确定类型g是一个类型的子类型f(因为每个f参数的类型是g参数列表中相同索引处参数类型的子类型,并且返回type g是返回类型的子类型f).但是,该__annotations__字段是字典:

f.__annotations__ == { 'x': int, 'y': int, 'return': type(None) }
Run Code Online (Sandbox Code Playgroud)

这意味着它没有向我提供我认为需要的参数排序信息.是否有一种可靠的方法来确定这x是第一个参数f,只是检查运行时属性f

Mar*_*ers 5

是的,Python函数确实携带了这些信息.

最简单的方法是使用该inspect.getfullargspec()函数提取此信息,或使用Signature对象从Python 3.3开始.

inspect.getfullargspec()返回值具有.args列出的参数,以便属性:

>>> import inspect
>>> def f(x: int, y: int) -> type(None):
...     pass
... 
>>> def g(a: object, b: int) -> type(None):
...     pass
... 
>>> inspect.getfullargspec(f)
FullArgSpec(args=['x', 'y'], varargs=None, varkw=None, defaults=None, kwonlyargs=[], kwonlydefaults=None, annotations={'x': <class 'int'>, 'y': <class 'int'>, 'return': <class 'NoneType'>})
>>> inspect.getfullargspec(f).args
['x', 'y']
>>> inspect.getfullargspec(g).args
['a', 'b']
Run Code Online (Sandbox Code Playgroud)

注释也包括在内:

>>> inspect.getfullargspec(f).annotations
{'x': <class 'int'>, 'y': <class 'int'>, 'return': <class 'NoneType'>}
>>> inspect.getfullargspec(g).annotations
{'return': <class 'NoneType'>, 'a': <class 'object'>, 'b': <class 'int'>}
Run Code Online (Sandbox Code Playgroud)

签名对象仍然更丰富:

>>> sig_f = inspect.signature(f)
>>> sig_g = inspect.signature(g)
>>> sig_f.parameters
mappingproxy(OrderedDict([('x', <Parameter at 0x1031f1ea8 'x'>), ('y', <Parameter at 0x102e00228 'y'>)]))
>>> sig_f.parameters['x'].annotation
<class 'int'>
>>> sig_g.parameters['b'].annotation
<class 'int'>
>>> sig_f.return_annotation == sig_g.return_annotation
True
Run Code Online (Sandbox Code Playgroud)

在哪里Signature.parameters使用有序字典,让您以正确的顺序比较参数.