4

Lisp の arg-supplied-p 変数のように機能するものを探しています。これは、デフォルト値をユーザーが指定した同じ値と区別するのに役立ちます。

例:

def foo(a=10):
    pass

次のように呼び出された場合、fooで知りたい:

foo()

またはこのように:

foo(10)

またはこのように:

foo(a=10)

最後の 2 つは、私にとって同義語です。私はその詳細を知る必要はありません。inspect モジュールを少し調べましたが、getargspec は 3 つの呼び出しすべてに対してまったく同じ結果を返します。

4

4 に答える 4

11

ソース コードを調べる以外に、3 つの関数呼び出しを区別する方法はありません。これらはまったく同じ意味を持つように意図されています。それらを区別する必要がある場合は、別のデフォルト値を使用してくださいNone

def foo(a=None):
    if a is None:
        a = 10
        # no value for a provided
于 2012-06-28T18:57:32.207 に答える
6

Svenが指摘しているように、デフォルトの引数にはNoneを使用するのが一般的です。引数なしと明示的なNoneが提供されていることの違いを区別する必要がある場合でも、センチネルオブジェクトを使用できます。

sentinel = object()

def foo(a=sentinel):
    if a is sentinel:
        # No argument was provided
        ...
于 2012-06-28T19:02:51.550 に答える
2

あまり。を使用foo.func_defaultsして関数のデフォルト引数のリストを取得できるため、それを使用して、渡された引数でオブジェクトの同一性を確認できます。ただし、これは変更可能なオブジェクトに対してのみ確実に機能します。あなたの例のように、誰かが 10 を渡したのか、デフォルトの 10 を使用したのかを知る方法はありません。両方の 10 が同じオブジェクトである可能性が高いためです。

とにかく、これは関数がどのように呼び出されたかがわからないため、大まかな概算にすぎません。デフォルトの引数が何であるかがわかるので、実際の引数を見て、それらが同じかどうかを推測してみてください。関数の呼び出しに使用される構文形式にアクセスする方法はありません。

これがどのように機能するか、または機能しないかを示す例を次に示します。

>>> def f(x="this is crazy"):
...     print x is f.func_defaults[0]
>>> f()
True
>>> f("this is crazy")
False
>>> def f(x=10):
...     print x is f.func_defaults[0]
>>> f()
True
>>> f(10)
True
于 2012-06-28T19:05:32.337 に答える
0

呼び出された関数は、デフォルト値であるか渡されたものであるかにかかわらず、最後の引数値のみを取得します。したがって、呼び出し元が何かを渡したかどうかを判断できるようにするために必要なことは、デフォルト値を渡せないものにすることです。の。

彼らは渡すNoneことができるので、あなたはそれを使うことができません。何が使えますか?

最も簡単な解決策は、ある種のPythonオブジェクトを作成し、それを関数のデフォルト値として使用することですdel。そうすると、ユーザーはそれを参照できなくなります。技術的には、ユーザーはこれを関数オブジェクトから掘り下げることができますが、そのような長さになることはめったにありません。そうする場合は、取得する価値があると主張できます。

default = []

def foo(a=default):
    if a is default:
        a = 10
    print a

del default

ここで使用している「デフォルト値」は空のリストです。リストは変更可能であるため、再利用されることはありません。つまり、空のリストはそれぞれ一意のオブジェクトです。(Pythonは、実際にはすべての空のタプルに同じ空のタプルオブジェクトを使用するため、空のタプルを使用しないでください。文字列リテラルと小さい整数も同様に再利用されるため、これらも使用しないでください。)objectインスタンスは問題ありません。変更可能であり、したがって共有されない限り、何でも。

問題は、上記のコードが実行されてから実際に実行されないことですdel default。実行時に関数でこのオブジェクトへの参照を取得して、それに対してテストできるようにするにはどうすればよいですか?これを行う1つの方法は、実際の引数には使用されないデフォルトの引数値を使用することです。

default = []

def foo(a=default, default=default):
    if a is default:
          a = 10
     print a

del default

これにより、関数の定義時にオブジェクトが引数のデフォルト値にバインドされるため、グローバル名が1秒後に削除されても問題ありません。しかし、誰かがhelp()あなたの関数を実行したり、それを内省したりすると、彼らが渡すことができる追加の引数があるように見えるという問題があります。より良い解決策はクロージャです。

default = []

def foo(default=default):   # binds default to outer func's local var default
    def foo(a=default):     # refers to outer func's local var default
        if a is default:
            a = 10
        print a
    return foo
foo = foo()

del default

これはすべてかなり多くの作業を行う必要があるため、実際には気にしないでください。

于 2012-06-28T19:17:31.790 に答える