33

次のようなpython関数がある場合:

def some_func(arg1, arg2, arg3=1, arg4=2):

関数内からキーワードで渡された引数を特定する方法はありますか?

編集

なぜこれが必要なのかと尋ねる人には、本当の理由はありません。会話の中で話題になり、好奇心が勝りました.

4

7 に答える 7

22

いいえ、この署名を使用して Python コードでそれを行う方法はありません。この情報が必要な場合は、関数の署名を変更する必要があります。

Python C API を見ると、引数が通常の Python 関数に渡される実際の方法は、常にタプルと dict であることがわかります。つまり、*args, **kwargs. そのタプルと dict は、名前で渡されたとしても、特定の位置引数と署名で指定されたものに解析されます。 and が*a存在**kwする場合は、その解析からの「オーバーフロー」があれば、その解析からのみ取得されます。この時点で、Python コードは制御を取得し、それまでに、要求している情報 (さまざまな引数がどのように渡されたか) はもう存在しません。

したがって、要求した情報を取得するには、署名をに変更*a, **kwし、独自の解析/検証を行います。これは「卵からオムレツまで」、つまり、ある程度の作業ですが、確かに実行可能です。 「オムレツから卵に戻る」というのは...単に実現不可能です;-)。

于 2010-01-18T18:00:04.273 に答える
12

デコレータを介した私の解決策は次のとおりです。

def showargs(function):
    def inner(*args, **kwargs):
        return function((args, kwargs), *args, **kwargs)
    return inner

@showargs
def some_func(info, arg1, arg2, arg3=1, arg4=2):
    print arg1,arg2,arg3,arg4
    return info

In [226]: some_func(1,2,3, arg4=4)
1 2 3 4
Out[226]: ((1, 2, 3), {'arg4': 4})

これをさらにクリーンアップする方法があるかもしれませんが、これは私には最小限の邪魔に思え、呼び出し元のコードを変更する必要はありません。

編集:特定の引数がキーワードによって渡されたかどうかを実際にテストするには、some_func内で次のようなことを行います。

args, kwargs = info
if 'arg4' in kwargs:
    print "arg4 passed as keyword argument"

免責事項:引数がどのように渡されたかを本当に気にするかどうかを検討する必要があります。このアプローチ全体は不要かもしれません。

于 2010-01-18T18:05:59.300 に答える
3

関数を再定義する必要があります。

def some_func(*args, **kwargs):

自分でマーシャリングを行います。位置渡し、キーワード渡し、デフォルトの違いを見分ける方法はありません。

于 2010-01-18T18:01:37.060 に答える
1

外部から渡されたからなのか、デフォルト値だからなのarg3か知りたいですか?1いいえ、私が知る限り、これを行う方法はありません。主な理由は、そのような知識が必要ないことだと思います。通常行われることは次のとおりです。

>>> def func(a, b=None):
    if b is None:
# here we know that function was called as:
# func('spam') or func('spam', None) or func('spam', b=None) or func(a='spam', b=None)

        b = 42
于 2010-01-18T17:55:56.957 に答える
1

次のようにしてください:

def some_func ( arg1, arg2, arg3=None, arg4=None ):
    if arg3 is None:
        arg3 = 1 # default value
    if arg4 is None:
        arg4 = 2 # default value

    # do something

そうすれば、何かがいつ設定されたかを確認でき、次のような問題に遭遇することなく、より複雑なデフォルト構造 (リストなど) を操作することもできます。

>>> def test( arg=[] ):
        arg.append( 1 )
        print( arg )
>>> test()
[1]
>>> test()
[1, 1]
于 2010-01-18T18:01:07.797 に答える