# Signature、Parameter

# 概述

Python的signature​模块是在Python 3.3中引入的,它提供了一个Signature​类,用于表示Python函数的参数签名(参数名、默认值、注解等信息)。同时,该模块还提供了一些函数和装饰器,用于解析和生成参数签名,从而使得Python函数更加灵活和易于使用。

Python中的函数签名是由参数列表、返回值和抛出的异常组成的,这些信息对于Python函数的调用和文档生成等方面都非常重要。在Python 2.x版本中,获取函数签名信息通常需要手动解析函数定义代码,而在Python 3.x版本中,signature​模块可以帮助我们自动解析函数签名,从而简化代码。

以下展示了如何使用signature​​模块来解析函数签名:

from inspect import signature

def foo(a: int, b: str = 'hello', *args: float, **kwargs: bool) -> dict:
    return {'a': a, 'b': b, 'args': args, 'kwargs': kwargs}

sig = signature(foo)
print(sig)

输出结果如下:

(a:int, b:str='hello', *args:float, **kwargs:bool) -> dict

可以看到,通过调用signature​函数,我们成功解析了函数foo​的参数签名,并将其表示为一个字符串。在这个字符串中,参数名和默认值使用等号(=)连接,位置参数和可变参数使用星号(*)表示,关键字参数和可变关键字参数使用双星号(**)表示,注解使用冒号(:)表示。

除了解析函数签名,signature​模块还提供了一些其他函数和装饰器,例如Parameter​、bind​和partial​等,这些工具可以帮助我们更加灵活地处理函数参数。需要注意的是,signature​模块在Python 3.3及以上版本中才可用,如果需要在旧版本中使用类似的功能,可以使用inspect​模块中的一些函数和类来实现。

# bind​ & bind_partial

在 Python 中,Signature​ 对象有两个方法 bind()​ 和 bind_partial()​,用于绑定参数并返回一个 BoundArguments​ 对象,表示参数和对应值的绑定关系。

bind()​ 方法的功能是将参数绑定到对应的值,它需要接收一系列参数,这些参数与 Signature​ 中定义的参数一一对应。如果所有的参数都绑定了值,则返回一个 BoundArguments​ 对象,如果参数数量不匹配,则抛出 TypeError​ 异常。

bind_partial()​ 方法与 bind()​ 类似,但是它可以只绑定部分参数。例如,如果有一个方法需要三个参数,但是只想绑定前两个参数,则可以使用 bind_partial()​ 方法来进行绑定。

下面是一个使用 Signature​ 对象的例子:

import inspect

def my_function(a: int, b: str, *, c: float = 3.14) -> bool:
    pass

sig = inspect.signature(my_function)

bound_args = sig.bind(1, "hello", c=2.0)
print(bound_args)
# 输出: <BoundArguments (a=1, b='hello', c=2.0)>

bound_args_partial = sig.bind_partial(1, "hello")
print(bound_args_partial)
# 输出: <BoundArguments (a=1, b='hello')>

在上面的例子中,我们使用 inspect​ 模块的 signature()​ 方法来获取 my_function()​ 方法的参数签名 sig​。然后我们分别使用 sig.bind()​ 和 sig.bind_partial()​ 来对方法参数进行绑定,得到对应的 BoundArguments​ 对象。

注意:如果在调用 bind()​ 或 bind_partial()​ 方法时传入了未定义的参数,将会抛出 TypeError​ 异常。

# Signature & Parameter

在Python中,函数的签名由参数和返回值组成。Signature类表示函数的签名,而Parameter类则表示一个函数参数的定义。在函数定义中,可以通过Signature类和Parameter类来声明函数的参数和返回值的类型、名称、默认值等。

在函数定义中,可以通过inspect模块中的signature()函数来获取函数的签名,该函数返回一个Signature对象。Signature对象包含一个parameters属性,该属性是一个有序字典,表示函数的所有参数。每个参数都是一个Parameter对象,它包含了参数的名称、默认值、注释等信息。可以通过Parameter类中的属性和方法来访问这些信息。

>>> from inspect import Signature, Parameter
>>> # Make a signature for a func(x, y=42, *, z=None)
>>> parms = [ Parameter('x', Parameter.POSITIONAL_OR_KEYWORD),
...         Parameter('y', Parameter.POSITIONAL_OR_KEYWORD, default=42),
...         Parameter('z', Parameter.KEYWORD_ONLY, default=None) ]
>>> sig = Signature(parms)
>>> print(sig)
(x, y=42, *, z=None)
>>>
>>> def func(*args, **kwargs):
...     bound_values = sig.bind(*args, **kwargs)
...     for name, value in bound_values.arguments.items():
...         print(name,value)
...
>>> # Try various examples
>>> func(1, 2, z=3)
x 1
y 2
z 3
>>> func(1)
x 1
>>> func(1, z=3)
x 1
z 3