2

元の呼び出しがオプションの引数を提供した、または提供しなかったという事実を隠すことなく、関数の引数を転送する方法はありますか?

def func1(a=x):
    # do stuff

def func2(b=y):
    # pass args to func1 without masking func1 defaults
    return func1(?)

func2() を呼び出すと、 func1() が引数なしで呼び出されるか、少なくともデフォルトの引数が何であれ、呼び出されます。

以下はほとんど機能しますが、基本的に、 func2 がそのデフォルトが呼び出されたかどうかを判断する方法があるかどうかはわかりません。

def func2(b=y):
    # this comes close but what if func2(y) is called?
    if b == y:
        return func1()
    else:
        return func1(b)
4

5 に答える 5

1

これを行う正しい方法は、func2関数にセンチネル値をデフォルト引数として使用させることだと思います。これにより、簡単に認識できます。そのセンチネルを取得した場合は、渡す引数を必要に応じて設定できますfunc1(たとえば、引数を渡さないなど)。引数のアンパックを使用して、可変数の引数 (0 ~ 1 など) の受け渡しを処理できます。

一般的なセンチネルは ですがNone、それが呼び出し元が渡す意味のある値である可能性がある場合は、別のものを使用することをお勧めします ( のインスタンスがobject一般的な選択肢です)。次に例を示します。

def func1(a="default value"): # lets assume we don't know what this default is
    # do stuff with a

# later, perhaps in a different module

_sentinel = object()    # our sentinel object

def func2(b=_sentinel):
    if b is _sentinel:  # test for the sentinel
        b = "some useful value"
        a_args = ()     # arguments to func1 is an empty tuple
    else:
        a_args = (b,)   # pack b into a 1-tuple

    # do stuff with b perhaps

    func1(*a_args)      # call func1 with appropriate arguments (either b or nothing)

この設計は比較的ばかげていることに注意してください。ほとんどのfunc1場合、すべての場合に引数を指定して呼び出すか、すべての場合に引数なしで呼び出します。このような引数を条件付きで渡す必要はほとんどありません。

于 2014-09-09T16:23:57.680 に答える
1

パラメータがオフのままかどうかを判断する通常の方法はNone、デフォルトとして使用することです。で関数を呼び出すことはほとんどないNoneため、便利なマーカーです。

def func2(b=None):
    if b is None:
        return func1()
    else:
        return func1(b)
于 2014-09-09T15:59:41.870 に答える
0

あなたの正確なユースケースは何ですか? func2適切なパラメーターのみを に渡すだけの十分にスマートである必要がfunc1あり、パラメーターのデフォルト値に依存する必要があります。

func2呼び出しの方法を変更する必要があることがわかったのは、厄介なシグネチャを持つ関数のfunc1場合だけです。func1c

def func2(this, that, those=None):
    if those is None:
        return func1(this, that)
    else:
        return func1(this, that, those)
于 2014-09-09T16:49:42.187 に答える
0

引数の転送は、可変引数で行う必要があります。

def func2(*args, **kwargs):
    func1(*args, **kwargs)

内省は少し苦しむ可能性がありますが、すべてがうまくいきます。


引数を渡す必要がない場合は、いつでも引数を削除できます。

del kwargs["name"]

例:

def print_wrapper(*args, extrabig=False, **kwargs):
    if extrabig:
        args = [arg*2 for arg in args]
        kwargs["sep"] = kwargs.get("sep", " ") * 2

    print(*args, **kwargs)

print_wrapper(2, 4, 8, end="!!!\n")
#>>> 2 4 8!!!

print_wrapper(2, 4, 8, sep=", ", end="!!!\n")
#>>> 2, 4, 8!!!

print_wrapper(2, 4, 8, extrabig=True, end="!!!\n")
#>>> 4  8  16!!!

本当にこれをしたくない場合は (間違っているかもしれませんが)、 を使用objectして一意のセンチネルを生成できます。

# Bad! Won't let you print None
def optionally_print_one_thing(thing=None):
    if thing is not None:
        print(thing)

# Better
_no_argument = object()
def optionally_print_one_thing(thing=_no_argument):
    if thing is not _no_argument:
        print(thing)
于 2014-09-09T16:05:15.347 に答える