11

私はたくさんの関数を作成しましたが、それらすべてに非常によく似たexcept節が必要ですが、try節とexcept節の行が非常に多く、各関数内に同じコードがあるのは嫌いです。例えば:

import sys
import random

def foo():
    num=random.random()
    try:
        if num>0.5: print 'OK'
        elif num>0.25: raise NameError('Too Small')
        else: raise KeyboardInterrupt
    except NameError:
        print "%s had a NameError" % sys._getframe().f_code.co_name
    except:
        print "%s had a different Error" % sys._getframe().f_code.co_name

def bar():
    num=random.random()
    try:
        if num>0.8: print 'OK'
        elif num>0.6: raise NameError('Too Small')
        else: raise KeyboardInterrupt
    except NameError:
        print "%s had a NameError" % sys._getframe().f_code.co_name
    except:
        print "%s had a different Error" % sys._getframe().f_code.co_name

"try" の後のコードは関数によって異なりますが、"except" の後のコードは同じです。コードが窮屈にならないように、except ステートメントを統合したいと考えています。これを行う良い方法はありますか?

4

5 に答える 5

24

Python デコレータはあなたが望むものです。

例外ブロックは常に同じだと言いました。必要なことを行うカスタム デコレータを作成します。これを各関数/メソッドに適用する必要がありますが、重複を確実に節約できます。

def handleError(function):
    def handleProblems():
        try:
            function()
        except Exception:
            print "Oh noes"
    return handleProblems


@handleError
def example():
   raise Exception("Boom!")

デコレータを適用してメソッドを呼び出す場合:

>>>
>>> 例()
おやおや
>>>

例外の種類と何をするかを変更する必要がありますが、これで私がどこに行くのかの要点がわかります。

于 2012-02-21T22:53:27.460 に答える
7

上記の答えは、引数を取る関数には当てはまりません。後者の場合、次のようなものが必要になると思います。

def handleError(f):
    def handleProblems(*args, **kwargs):
        try:
            return f(*args, **kwargs)
        except Exception:
            print "Oh noes"
    return handleProblems

次のようにテストできます。

@handleError
def addTwo(x, y): 
    print(x + y) 

>>> addTwo(5,5)
10
>>> addTwo(5, 's')
Oh noes 
于 2014-07-12T10:08:06.323 に答える
6

ブロック内のコンテンツtryは興味深いものなので、関数に含める必要があります。次に、必要な関数を選択して呼び出し、例外でラップします。例外コードを関数として記述し、選択した関数をこれに引数として渡すこともできます。例えば

def foo():
    num=random.random()
    if num>0.5: print 'OK'
    elif num>0.25: raise NameError('Too Small')
    else: raise KeyboardInterrupt

def bar():
    num=random.random()
    if num>0.8: print 'OK'
    elif num>0.6: raise NameError('Too Small')
    else: raise KeyboardInterrupt

def try_numerics(f):
    try:
        f()
    except NameError:
        print "%s had a NameError" % sys._getframe().f_code.co_name
    except:
        print "%s had a different Error" % sys._getframe().f_code.co_name

# In your main code...
if (need_to_run_foo):
    try_numerics(foo)
elif (need_to_run_bar):
    try_numerics(bar)
于 2012-02-21T22:58:56.403 に答える
2

それらが実際の関数である場合、それらを一般化するのは簡単です。

1 つの一般的な関数を作成できます

def general(bottom_num, top_num):
  num=random.random()
  try:
    if num>top_num: print 'OK'
    elif num>bottom_num: raise NameError('Too Small')
    else: raise KeyboardInterrupt
  except NameError:
    print "%s had a NameError" % sys._getframe().f_code.co_name
  except:
    print "%s had a different Error" % sys._getframe().f_code.co_name

これにより、コードが繰り返されるのを防ぎ、try: except: の問題に対処できます。

于 2012-02-21T23:11:27.200 に答える