0

予期しないパラメーターを渡して、関数を呼び出す方法を知りたいです。

私は数日前にこの問題に直面し、それを回避する方法を見つけました。でも今日、自分のやりたいことが可能かどうか見てみることにしました。残念ながら、私はそれを使用したコンテキストを覚えていません。したがって、これを行うためのより良い方法がたくさんある愚かな例を次に示しますが、それは無視してください。

def test(func, arg1, arg2):
    return func(arg1, arg2, flag1=True, flag2=False) #Only pass the flags if the function accepts them.

def func1(a, b, flag1, flag2):
    ret = a
    if flag1:
        ret *= b
    if flag2:
        ret += b
    return ret

def func2(a, b):
    return a*b

print test(func1, 5, 6) #prints 30

私が思いついた代替案は次のようになりました。

def test(func, arg1, arg2):
    numArgs = len(inspect.getargspec(func).args)
    if numArgs >= 4:
        return func(arg1, arg2, True, False)
    elif numArgs == 3:
        return func(arg1, arg2, True)
    else:
        return func(arg1, arg2)

print test(func2, 5, 6) #prints 30

または try..except.. ブロック

しかし、func1 と func2 を変更せずにこれを行うより良い方法があるはずですよね?

(編集): Max Sが提供するソリューションを利用して、これが最善のアプローチだと思います:

def callWithOptionalArgs(func, *args):
    argSpec = inspect.getargspec(func)
    lenArgSpec = len(argSpec.args or ())
    argsToPass = args[:lenArgSpec] #too many args
    defaults = argSpec.defaults or ()
    lenDefaults = len(defaults)
    argsToPass += (None, )*(lenArgSpec-len(argsToPass)-lenDefaults) #too few args
    argsToPass += defaults[len(argsToPass)+len(defaults)-lenArgSpec:] #default args

    return func(*argsToPass)
print callWithOptionalArgs(func1, 5, 6, True) #prints 30
print callWithOptionalArgs(func2, 5, 6, True) #prints 30
4

2 に答える 2

1

関数を検査することは、元の関数を変更したり装飾したりすることなく、引数の数が異なる関数を明示的に区別する唯一の方法です。ラッパーに行う唯一の変更は、任意の数の引数に対して一般化することです。

def padArgsWithTrue(func, *args):
    passed_args = list(args)
    num_args = len(inspect.getargspec(func).args)
    passed_args += [True] * (num_args - len(args))
    return func(*passed_args)

print padArgsWithTrue(lambda x,y,z,w: (x*y, z, w), 5, 6)

編集:これは、可変数の引数またはキーワード引数を持つ関数に対応していないことに注意してください。完全なソリューションを作成する前に、それらに対処するポリシーを決定する必要があります。

于 2010-02-06T05:56:56.470 に答える
0

私があなたを理解していれば、テストを使用して func1 と func2 の両方を呼び出せるようにしたいと考えています。

def test(func, arg1, arg2):
    try:
        return func(arg1, arg2, flag1=True, flag2=False)
    except TypeError:
        return func(arg1, arg2)


def func1(a, b, flag1, flag2):
    ret = a
    if flag1:
        ret *= b
    if flag2:
        ret += b
    return ret

def func2(a, b):
    return a*b

print test(func1, 5, 6) #prints 30
print test(func2, 5, 6) #prints 30
于 2010-02-06T06:19:48.413 に答える