1. ホーム
  2. python

関数の引数のデフォルト値を取得しますか?

2023-08-10 05:26:08

質問

この関数について

def eat_dog(name, should_digest=True):
    print "ate dog named %s. Digested, too? %" % (name, str(should_digest))

関数の外部で、その引数やデフォルト値を読み取りたいのです。つまり、この具体的な例では name にはデフォルト値がなく (つまり必須引数であること)、また True はデフォルト値として should_digest .

私が意識しているのは inspect.getargspec() は、引数やデフォルト値についての情報を与えてくれますが、この2つの間に何の関連性も見出せません。

ArgSpec(args=['name', 'should_digest'], varargs=None, keywords=None, defaults=(True,))

この出力から、どうすれば True (その中の defaults タプル) のデフォルト値は should_digest ?

さらに、私は問題にアプローチするための "ask for forgiveness" モデルについて知っていますが、残念ながらそのエラーからの出力は、不足している引数の名前を教えてはくれません。

>>> eat_dog()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: eat_dog() takes at least 1 argument (0 given)

文脈を説明すると(なぜこれをやりたいのか)、私はJSON APIを介してモジュール内の関数を公開しています。呼び出し側が特定の関数引数を省略した場合、省略された特定の関数引数を指定する特定のエラーを返したいのです。クライアントが引数を省略しても、関数の署名で提供されるデフォルトがある場合、そのデフォルトを使用したいと思います。

どのように解決するのですか?

Python3.x

Python3.xの世界では、おそらくは Signature オブジェクトを使うべきでしょう。

import inspect

def get_default_args(func):
    signature = inspect.signature(func)
    return {
        k: v.default
        for k, v in signature.parameters.items()
        if v.default is not inspect.Parameter.empty
    }

Python2.x (古い答え)

args/defaultsは、次のように組み合わせることができます。

import inspect
a = inspect.getargspec(eat_dog)
zip(a.args[-len(a.defaults):],a.defaults)

ここで a.args[-len(a.defaults):] はデフォルト値を持つ引数で、明らかに a.defaults は対応するデフォルト値である。

の出力を渡すこともできます。 zip の出力を dict のコンストラクタに追加し、キーワード展開に適したマッピングを作成します。


ドキュメントを見ると、この解決策はpython2.6またはそれ以降でしか動作しないようです。 inspect.getargspec を返すと仮定しているからです。 という名前のタプル . 以前のバージョンでは 正規のタプル を返しますが、それに応じて修正するのは非常に簡単でしょう。 以下は、古い(そして新しい)バージョンで動作するバージョンです。

import inspect
def get_default_args(func):
    """
    returns a dictionary of arg_name:default_values for the input function
    """
    args, varargs, keywords, defaults = inspect.getargspec(func)
    return dict(zip(args[-len(defaults):], defaults))

そういえば

    return dict(zip(reversed(args), reversed(defaults)))

も動作し、人によってはより直感的に理解できるかもしれません。