2017-04-05 4 views
1

If/ElseブロックとTry/Exceptブロックのどちらを使用するかについて既に議論が行われています。 Better to 'try' something and catch the exception or test if its possible first to avoid an exception?ネストされたTry/ExceptまたはIf/Else - 使用する方法を指定する方法?

しかし、私はネストされたtry/exceptネストされたif/elif/else論理ブロックに少しさらなる議論を拡張したいと思います。このような質問はここに位置しています。ここにはセットアップがあります...ユーザーが文字列リテラル、整数、または反復可能なものを提供できるようにする関数を記述したいと思います。これは、私が書いた他の関数にあるレベルの抽象化を提供する高水準関数です。私のコードはそうのようなものです:

def high_level_func(parameter = None): 
    """ 
    :param parameter: Can accept the string 'All', a single integer, or an iterable such 
     as a range or a list or tuple of ints. 
    """ 
    try: 
     if parameter.lower() == 'all' 
     # .lower because str input should be case-insensitive 
      return str_all_function(parameter) # Only accepts the 
        # string 'all' - case insensitive 
    except AttributeError: 
     # if parameter is an int or iter end up here because those types 
     # don't have .lower() methods 
     try: 
      for para in parameter: 
       try: 
        print(int_input_function(parameter)) 
       except MyException: 
        raise MyException('An iter of something other than ints was ' 
             'provided and cause this error.') 
     except TypeError: 
      # parameter must be an int because ints aren't iterable and end up here 
      return int_input_function(parameter) 

この場合のは、私はほとんどのユーザーは、任意のユーザーは、どちらかiterintに合格することも同様に可能性がある、すなわち(好むでしょう入力の種類見当がつかないと仮定しましょう文字列のリストを渡すことはほとんどないでしょう - iter

これは大丈夫ですか?入力のタイプとif/elif/else(IEE)コードブロックを実行していますか?あなたの意見では、IEEコードブロックを読みやすくすることはできますか?

代わりの提案:try/exceptとIEEの組み合わせはどうですか?たとえば、文字列リテラル 'all'の場合はtry/exceptが入力を下げようとしますが、IEEはexceptブロックにネストされ、代替のケース(整数またはiterまたは不正なタイプ)を確認します。

さらに一般的には、どのような方法が最も速いのかを3つの異なる時間関数を記述し、それぞれをテストすることなくどのように調べることができますか?

さらに、Try/ExceptがIf/Elif/Elseテストよりも速い場合でも、If/Elif/Elseの方が読みやすさが優れていると考えられます。ウィンドウの読みやすさを投げ捨てることを正当化するか、またはスピードの面で可読性が常に勝つのだろうか?それとも、コーダーの/チームの裁量にかかっていますか?

+0

Pythonは(簡単許可よりも許しを求めるために)EAFPモデルを推奨していますので、この場合、 try-exceptを使用することは、Pythonの方法です。個人的には、非パイソンルートに行き、isinstance(parameter、collections.Iterable)を使用してバリデーションを分割し、try-exceptsのカスケードを回避します。パフォーマンスに関しては、testitモジュールを使用して簡単なバージョンとテストを作成することをお勧めします。 –

+0

追加情報については、この比較の簡略化されたバージョンを100,000回繰り返し実行し、if/Elif/ElseがisInstanceで、実際にtry/exceptメソッドよりも高速であることがわかりました。 (私はtestitモジュールを使用していませんでした。)この場合、If/Elseアプローチを使用することは読みやすさと効率性を両立させるようです。理由はわかりません。 試行/例外の方法:1.34000015258789秒100,000回のループ /Elif/Elseの場合:1.18899989128112秒100,000回以上のループ – boymeetscode

答えて

1

あなたの入力関数は、それらを呼び出す関数ではなく、入力の検証に責任があると思います。その後、あなたは、高レベルの機能をさせることができ、高いレベルを維持し、それが成功するまで、それらのいずれかを使用するtry INGを保つ:

def high_level_function(parameter=None): 
    try: 
    return str_input_function(parameter) 
    except ValueError: # Raised by str_input_function on bad input. 
    pass 

    try: 
    return iter_input_function(parameter) # MyException now propagates itself. 
    except ValueError: # Raised by iter_input_function on bad input. 
    pass 

    try: 
    return int_input_function(parameter) 
    except ValueError: # Raised by int_input_function on bad input. 
    pass 

    # This should never be hit: 
    raise ValueError("parameter has unsupported type: " + type(parameter).__name__) 
+0

この洞察に感謝します。シンプルでクリーンで読みやすく、それでもPythonのEAFPの方法論に従っています。この問題を熟考して自分自身を怒らせるようなもの。私はPythonでそれをする傾向があります。 Grrrr。 – boymeetscode

+0

問題ありません! FWIW、あなたは正しい道にいると思う。 –

+0

'return'ステートメントに到達すると、私はhigh_level_functionを残すべきですか?私は自分のコードをテストしていますが、それぞれのブロックがreturnステートメントを持っているにもかかわらず、すべてのtryブロックを通過しているようで、成功すると思っていますが、そうではありません。私が期待していることと、Pythonがしていることを確実にすることは同じことです。 – boymeetscode

関連する問題