見出し画像

Pythonのinspectモジュール Signatureオブジェクトについて

inspectはオブジェクト (モジュール、クラス、メソッド、関数etc)から情報を取得する関数をもつPython言語のbuilt-inのモジュールです。このinspectモジュールのSignatureオブジェクトを使って関数の情報を取得することがあったので、復習として本記事にまとめていきます。

Signatureオブジェクト

■概要

Signatureオブジェクトは、関数などの呼び出し可能なオブジェクトのシグネチャとその戻り値のアノテーションを表します。具体的には、任意の関数がどのような引数を持ち、返り値を持つのかなどの情報を持ちます。

使い方

以下の some_function関数を使って、使い方を見てみます。

def some_function(a, b: int, c: str = "default", d = 1.5) -> bool:
    return True

こちらをinspectモジュールのsignatureオブジェクトに渡して中身を見てみましょう。

import inspect
sig = inspect.signature(some_function)

■parameters

関数の引数の情報をもつParameterオブジェクトが返却されます。引数が定義されている順番に並んでおり、引数の名前・型・デフォルト値・引数の種類を見ることができます。

for name, param in sig.parameters.items():
  print(f"Name: {name}, Type: {param.annotation}, Default: {param.default}, Kind: {param.kind}")

Name: a, Type: <class 'inspect._empty'>, Default: <class 'inspect._empty'>, Kind: POSITIONAL_OR_KEYWORD
Name: b, Type: <class 'int'>, Default: <class 'inspect._empty'>, Kind: POSITIONAL_OR_KEYWORD
Name: c, Type: <class 'str'>, Default: default, Kind: POSITIONAL_OR_KEYWORD
Name: d, Type: <class 'inspect._empty'>, Default: 1.5, Kind: POSITIONAL_OR_KEYWORD

■return_annotation

関数のreturnアノテーションを返却します

sig.return_annotation

<class 'bool'>

注意ですが、こちらは明示的に返り値の型が関数に明記されていない場合はParamter.empty が返却されます。

import inspect
def some_function(a, b: int, c: str = "default", d = 1.5):
    return True
sig = inspect.signature(some_function)
print(sig.return_annotation)

<class 'inspect._empty'>

■bind

指定された引数を関数のシグネチャにバインドし、BoundArgumentsオブジェクトを返却します

bound_args = sig.bind(10, 30, "sample string", 1.1)
for name, value in bound_args.arguments.items():
    print(f"{name} = {value}")

a = 10
b = 30
c = sample string
d = 1.1

■bind_partial

部分的に引数をバインドし、BoundArgumentsオブジェクトを返却します

partial_bound_args = sig.bind_partial(10, b=30)
for name, value in partial_bound_args.arguments.items():
    print(f"{name} = {value}")

a = 10
b = 30

■replace

既存のシグネチャを基に新しいシグネチャを作成します(以下の例では既存の関数にreturnアノテーションを追加しています)

def some_function(a, b: int, c: str = "default", d = 1.5):
    return 0
sig = inspect.signature(some_function)
new_sig = sig.replace(return_annotation=int)
print(str(new_sig))

(a, b: int, c: str = 'default', d=1.5) -> int

出典