3

私は長い間 Python 開発者であり、言語の動的な性質が大好きですが、Python がオプションの静的型付けの恩恵を受けるかどうか疑問に思っています。 ライブラリの API に静的型付けを適用できると便利でしょうか? また、これにはどのような欠点がありますか?

Pastebin で実行時静的型チェック実装するデコレータを簡単にスケッチしたところ、次のように動作します。

# A TypeError will be thrown if the argument "string" is not a "str" and if 
# the returned value is not an "int"
@typed(int, string = str)
def getStringLength(string):
    return len(string)

ライブラリの API 関数でこのようなデコレータを使用することは実用的でしょうか? 私の観点では、ライブラリのドメイン固有モジュールの内部動作では型チェックは必要ありませんが、ライブラリとそのクライアントの間の接続ポイントでは、型チェックを適用することによる契約による単純なバージョンの設計が役立つ可能性があります。特に、ライブラリのクライアントに対して何を期待し、何を返すかを明確に示す強制ドキュメントの一種として。

この例のように、addObjectToQueue()isObjectProcessed()はクライアントが使用するために公開されておりprocessTheQueueAndDoAdvancedStuff()、内部ライブラリ関数です。型チェックは外向きの関数では役立つと思いますが、内部関数で使用すると、python の動的性と有用性が肥大化して制限されるだけです。

# some_library_module.py

@typed(int, name = string)
def addObjectToQueue(name):
    return random.randint() # Some object id

def processTheQueueAndDoAdvancedStuff(arg_of_library_specific_type)
    # Function body here

@typed(bool, object_id = int)
def isObjectProcessed(object_id):
    return True

この手法を使用することの欠点は何ですか? ペーストビンでの私の素朴な実装の欠点は何ですか?

Python を静的に型付けされた言語に変換することについて議論する回答ではなく、API 設計固有の長所と短所についての考えです。(質問ではないと考える場合は、これをprogrammers.stackexchange.comに移動してください)

4

1 に答える 1

8

個人的には、このアイデアは Python にとって魅力的ではありません。もちろん、これはすべて私の意見にすぎませんが、文脈上、おそらく Python と Haskell が私のお気に入りの 2 つのプログラミング言語であることをお伝えします。私は、静的型付けと動的型付けの範囲の両端にある言語が好きです。

静的型付けの主な利点は次のとおりです。

  1. コンパイラがコードを受け入れると、コードが正しい可能性が高くなります。1 つの結果の型が別の入力の型と常に一致し、最終的な結果の型が必要な型になるように、呼び出したすべての操作に値をスレッド化したことがわかっている場合、正しい操作を選択しました。この点は非常に議論の余地のある価値があります。なぜなら、あまりテストを行っていない場合にのみ問題になるからです。しかし、Haskell でプログラミングしているとき、私が座って「やった!」と言うのは事実です。私は実際に多くの時間を終えていますが、私の Python コードにはほとんど当てはまりません。
  2. コンパイラーは、データ構造またはインターフェースに互換性のない変更を加えると (ほとんどの場合)、変更が必要な場所のほとんどを自動的に指摘します。繰り返しになりますが、すべての影響を実際に把握したことを実際に確認するにはテストが必要ですが、私の経験では、ほとんどの場合、コンパイラのしつこい動作で十分です。これにより、そのようなリファクタリングが大幅に簡素化されます。リファクタリングのコアを実装してから、プログラムがまだ正常に動作するかどうかをテストするまで、すぐに進むことができます。これは、流れに沿ったすべての変更を行う実際の作業がほとんど機械的であるためです。
  3. 効率的な実装。コンパイラは、型に関するすべての知識を使用して最適化を行います。

あなたが提案したシステムは、実際にはこれらの利点を提供しません。

  1. あなたのライブラリを利用するプログラムを書いたとしても、実行パスに不正な呼び出しが含まれていないかどうかを確認するために完全なコード カバレッジで広範なテストを行うまで、関数の型が正しくない使用が含まれているかどうかはまだわかりません。
  2. 何かをリファクタリングするとき、「完全なテストスイートを実行し、例外を探し、それがどこから来たのかを見つけ、コードを修正する」という何回ものラウンドを経て、静的型付けコンパイラの問題検出のようなものを得る必要があります。
  3. Python は、これらの変数がいつでも何でもあるかのように動作します。

そして、それを実現するために、Python のダックタイピングの柔軟性を犠牲にしてきました。十分に「リストのような」オブジェクトを提供するだけでは十分ではなく、実際にリストを提供する必要があります。

私にとって、この種の静的型付けは両方の世界で最悪です。主な動的型付けの引数は、「とにかくコードをテストする必要があるため、それらのテストを使用して型エラーをキャッチし、型システムが役に立たないときに型システムを回避する必要から解放することもできます」. それは本当に優れた静的型システムに関しては良い議論かもしれませんし、そうでないかもしれませんが、実行時に型エラーを検出するだけの弱い部分静的型システムに関しては絶対に説得力のある議論です. より良いエラー メッセージ (ほとんどの場合、これだけで十分です。インターフェイスでキャッチされない型エラーは、コール スタックの奥深くで例外をスローすることはほぼ確実です) は、柔軟性を失う価値があるとは思いません。

于 2012-01-28T23:42:38.450 に答える