3

数を計算するために、いつも同じ引数チェック コードを書いていることに気が付きました。

def myfun(a, b):
    if a < 0:
        raise ValueError('a cannot be < 0 (was a=%s)' % a)
    # more if.. raise exception stuff here ...
    return a + b

より良い方法はありますか?これらのことには「アサート」を使用しないように言われました (ただし、エラーの原因となった変数の値がわからないことを除けば、問題はわかりません)。

編集:明確にするために、引数は通常単なる数値であり、エラーチェック条件は複雑で自明ではない可能性があり、後で例外につながるとは限りませんが、単に間違った結果になります。(不安定なアルゴリズム、無意味なソリューションなど)

4

3 に答える 3

4

assertで実行すると、最適化されなくなりますpython -O(適度な最適化ですが、あると便利な場合もあります)。頻繁に繰り返されるパターンがある場合の好ましい代替手段の 1 つは、デコレータを使用することです。これは、繰り返しを除外する優れた方法です。たとえば、(キーワードではなく) 位置ごとに引数を指定して呼び出す必要があり、最初の引数を正にする必要がある無数の関数があるとします。それから...:

def firstargpos(f):
  def wrapper(first, *args):
    if first < 0:
      raise ValueError(whateveryouwish)
    return f(first, *args)
  return wrapper

次に、次のように言います。

@firstargpos def myfun(a, b): ...

チェックは、デコレーター (または、それが返すラッパー クロージャー) で一度だけ実行されます。したがって、唯一のトリッキーな部分は、関数が必要とするチェックと、それらを表現するためにデコレータを呼び出す最善の方法を正確に把握することです (定義している関数のセットとそれぞれが必要とするチェックのセットを見ずに言うのは難しいです) !-)。DRY (「Don't Repeat Yourself」) は、ソフトウェア開発の指針となる原則の中で最上位に近いことを忘れないでください。Python には、DRY を実装してボイラープレートや反復的なコードを回避できる合理的なサポートがあります!-)

于 2009-10-29T04:24:58.580 に答える
0

-Oassert 行がチェックされず、エラー (コマンド ライン フラグ)が発生しないような方法でコードを実行できる (一部のシステムではデフォルトである) ため、assert を使用したくありません。

同じプロパティを持つはずの多くの変数を使用している場合、使用している型をサブクラス化し、そのチェックをクラス自体に追加してみませんか? 次に、新しいクラスを使用すると、無効な値がまったくないことがわかり、あちこちチェックする必要がなくなります。

于 2009-10-29T04:21:10.257 に答える
-1

これがあなたの質問に答えるかどうかはわかりませんが、関数の開始時に多くの引数をチェックすることはあまりPythonicではないことに気づきました。

これが言いたいのは、ほとんどのpythonistasは、私たちは皆同意した大人であり、愚かなことをしないようにお互いを信頼しているという仮定です. あなたの例を書く方法は次のとおりです。

def myfun(a, b):
    '''a cannot be < 0'''
    return a + b

これには 3 つの明確な利点があります。まず、簡潔です。実際にやろうとしていることと関係のないことをする余分なコードはありません。help(myfun)次に、 pythonistas が使用上の注意を探すと予想される場所に、情報を正確に配置します。最後に、正でない値はa本当にエラーなのでしょうか? あなたはそう思うかもしれませんが、a が 0 の場合に何かが確実に壊れない限り (ここではおそらく壊れません)、それをすり抜けて呼び出しストリームでエラーを発生させる方が賢明です。結局のところ、a + bエラーが発生した場合、コール スタックに渡される例外が発生し、動作はほとんど同じです。

于 2009-10-29T04:44:48.330 に答える