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

时间:2014-07-26 19:10:45

标签: python python-3.x

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

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

def g(a: object, b: int) -> type(None):
    pass

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

f.__annotations__ == { 'x': int, 'y': int, 'return': type(None) }

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

1 个答案:

答案 0 :(得分:5)

是的,Python函数确实带有这些信息。

最简单的方法是使用inspect.getfullargspec()函数提取此信息,或者使用Signature objects从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']

也包含注释:

>>> 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'>}

签名对象仍然更丰富:

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

其中Signature.parameters使用有序字典,让您按正确的顺序比较参数。