18.4.7 方法和函数签名
除了函数或方法的文档,还可以得到可调用方法参数的完整规范,包括默认值。signature()函数会返回一个Signature实例,其中包含函数参数的有关信息。
import inspect
import example
sig = inspect.signature(example.module_level_function)
print('module_level_function{}'.format(sig))
print('\nParameter details:')
for name,param in sig.parameters.items():
if param.kind == inspect.Parameter.POSITIONAL_ONLY:
print(' {} (positional-only)'.format(name))
elif param.kind == inspect.Parameter.POSITIONAL_OR_KEYWORD:
if param.default != inspect.Parameter.empty:
print(' {}={!r}'.format(name,param.default))
else:
print(' {}'.format(name))
elif param.kind == inspect.Parameter.VAR_POSITIONAL:
print(' *{}'.format(name))
elif param.kind == inspect.Parameter.KEYWORD_ONLY:
if param.default != inspect.Parameter.empty:
print(' {}={!r} (keyword-only)'.format(
name,param.default))
else:
print(' {} (keyword-only)'.format(name))
elif param.kind == inspect.Parameter.VAR_KEYWORD:
print(' **{}'.format(name))
可以通过Signature的parameters属性来得到函数参数。parameters是一个有序字典,将参数名映射到描述这个参数的Parameter实例。在这个例子中,函数的第一个参数arg1没有默认值,而arg2有默认值。
修饰符或其他函数可以用一个函数的Signature来验证输入、提供不同的默认值以及完成其他任务。不过,要编写一个通用而且可重用的验证修饰符,会带来一个特殊的挑战,因为对于同时接收命名参数和位置参数的函数来说,要把收到的参数与相应的参数名对应,这可能会很复杂。bind()和bind_partial()方法提供了处理这种映射所需的逻辑。它们会返回一个BoundArguments实例,其中填充与指定函数参数名关联的实参。
import inspect
import example
sig = inspect.signature(example.module_level_function)
bound = sig.bind(
'this is arg1',
'this is arg2',
'this is an extra positional argument',
extra_named_arg='value',
)
print('Arguments:')
for name,value in bound.arguments.items():
print('{} = {!r}'.format(name,value))
print('\nCalling:')
print(example.module_level_function(*bound.args,**bound.kwargs))
BoundArguments实例包含属性args和kwargs,可以使用这种语法调用函数,以便将元组和字典扩展到参数所在的栈。
如果只能得到一些参数,则bind_partial()将人能创建一个BoundArguments实例。在增加其余参数之前,这个实例可能还无法正常使用。
import inspect
import example
sig = inspect.signature(example.module_level_function)
partial = sig.bind_partial(
'this is arg1',
)
print('Without defaults:')
for name,value in partial.arguments.items():
print('{} = {!r}'.format(name,value))
print('\nWithout defaults:')
partial.apply_defaults()
for name,value in partial.arguments.items():
print('{} = {!r}'.format(name,value))
apply_defaults()会增加参数默认值中的值。