65

Python では、assertはステートメントであり、関数ではありません。これは意図的な決定でしたか?assert関数の代わりにステートメント (および予約語) にする利点はありますか?

docsによると に展開されますassert expression1, expression2

if __debug__:
    if not expression1: raise AssertionError(expression2)

ドキュメントには、「現在のコード ジェネレーターは、コンパイル時に最適化が要求されたときに assert ステートメントのコードを発行しない」とも書かれています。詳細は不明ですが、これを可能にするために特別なケースが必要だったようです。ただし、特殊なケースを使用して、関数への呼び出しを最適化することもできassert()ます。

関数の場合assert、次のように記述できます。

assert(some_long_condition,
       "explanation")

しかし、assertはステートメントであるため、タプルは常に に評価されTrue、次の結果が得られます。

SyntaxWarning: assertion is always true, perhaps remove parentheses?

正しい書き方は、

assert some_long_condition, \
       "explanation"

これは間違いなくあまりきれいではありません。

4

4 に答える 4

39

assert を関数ではなくステートメント (および予約語) にする利点はありますか?

  1. @mgilsonが指摘したように、ユーザー関数に再割り当てすることはできません。つまり、コンパイル時に効果的に無効にすることができます。
  2. 2 番目のオプション パラメータの評価は、アサーションが失敗するまで保留されます。関数と関数の引数でそれを行うのは厄介です (ラムダを渡す必要があります)。2 番目のパラメーターの評価を延期しないと、追加のオーバーヘッドが発生します。
于 2012-11-15T02:20:53.010 に答える
20

Python やその他の言語 (特に C)の素晴らしい点の 1 つはassert、適切な(オプションで、これまでに使用したコンパイラのコマンドラインで#define) または最適化フラグ (-Oパイソン)。関数になった場合、同じ名前の組み込み関数またはユーザー定義関数があるassertかどうかは実行時までわからないため、この機能を Python に追加することは不可能です。assert


また、Python では、関数呼び出しはかなりコストがかかることに注意してください。インラインでコードに置き換えることは、パフォーマンスが重要なルーチンにステートメントif __debug__: ...を配置する場合に重要な関数呼び出しを行うよりも、おそらくはるかに効率的です。assert

于 2012-11-15T02:16:20.570 に答える
8

私は Python の専門家ではありませんが、パフォーマンスが最大の理由の 1 つだと思います。

関数として assert(式, 説明) がある場合、式の評価にコストがかかる場合、非デバッグ モードであっても、Python は両方の式を評価して assert 関数に渡す必要があります。

アサートを展開することにより、式と説明ステートメントは、実際に必要でない限り ( debugが true と評価される場合)、実際には評価されません。必要のないときにパフォーマンスに影響を与えないようにアサートしたい場合 (つまり、実稼働システムでパフォーマンス ヒットがない場合) は重要だと思います。

于 2012-11-15T03:36:18.057 に答える