0

私はデコレータを学んでいて、ここでは以下をデコレータパターンに変更しようとしています。

def invert(x):
    return 1/x

print invert(5)

デコレータを使用して変更できます。

def safe(fun, *args):
    if args[0]!=0:
        return fun(*args)
    else:
        "Division by 0"

def invert(x):
    return 1/x

print safe(invert, 5) 

@wapper構文を使用して、

def safe(fun, *args):
    if args[0]!=0:
        return fun(*args)
    else:
        "Division by 0"
@safe
def invert(x):
    return 1/x

print invert(5)

上記のコードはエラーになりますIndexError: tuple index out of range。私はそれが間違っている理由とそれを修正する方法を理解しようとしています。

4

2 に答える 2

4

あなたの主な問題は、デコレータが値ではなく関数を返す必要があることです。デコレーターは、定義された関数をそれに基づく新しい関数に置き換えます。

それ以上はreturn、ブロック内にステートメントはなくelse、単なる文字列リテラルです。あなたはおそらくそれを返すつもりでした。

def safe(fun):
    def f(*args):
        if not args[0] == 0:
            return fun(*args)
        else:
            return "Division by 0"
    return f

注意として、これは演習のみを目的としていると思いますが、 Python ではエラーが黙って渡されるべきではありません。例外を発行する動作は、エラー時に文字列を返すよりも一般的にはるかに便利です。実際、Python でこれをより自然に実装するには、許可のマントラではなく、許しを求める必要があります。

def safe(fun):
    def f(*args):
        try:
            return fun(*args)
        except ZeroDivisionError:
            return "Division by 0"
    return f

また、「safe」などのステートメント名を一掃することに注意してください。他の例外がスローされる可能性があります。

于 2012-06-21T10:48:43.110 に答える
3

あなたはそれを間違っています。

def safe(fun):
    def wrapper(*args)
        if args[0]!=0:
            return fun(*args)
        else:
            return "Division by 0"
    return wrapper

関数は、それで装飾する関数ごとに1 回safe呼び出されます。-- ここで呼び出される--によって返される内部関数は、装飾された関数が呼び出されるたびに呼び出されます。元の関数を呼び出すか、まったく別のことを行う責任があります。safewrapped

したがって、デコレータは 1 つの引数、つまりラップされる関数を取ります。しかし、デコレータ関数があります。これは、デコレータを返す関数です(したがって、ラップされた関数のもう1つのレイヤー):

def safe(singularities):
    def decorator(fun):
        def wrapper(*args)
            if args[0] not in singularities:
                return fun(*args)
            else:
                return "Division by 0"
        return wrapper
    return decorator

そのため、safeデコレータ関数は無限の数の異なるデコレータを返す可能性があります。次のように使用します。

@safe([0])
def invert(x):
    return 1 / x

@safe([-1, 1])
def foo(x)
    return 1 / ((x - 1) * (x + 1))

彼が投稿した後、なぜ私が Lattyware と本質的に同じ回答を投稿したのか疑問に思っている人のために: その回答は、私が私のものを書き始めるまで、すべての問題に対処していませんでした。完全な重複ではないため、削除しないでください。

于 2012-06-21T10:59:51.663 に答える