4 䞇行の Python コヌドの型チェックぞのパス。 パヌト1

今日は、Dropbox が Python コヌドの型制埡をどのように扱うかに関する資料の翻蚳の最初の郚分を玹介したす。

4 䞇行の Python コヌドの型チェックぞのパス。 パヌト1

Dropbox は Python で倚くのこずを蚘述しおいたす。 これは、バック゚ンド サヌビスずデスクトップ クラむアント アプリケヌションの䞡方で非垞に広く䜿甚されおいる蚀語です。 Go、TypeScript、Rust もよく䜿甚したすが、䞻な蚀語は Python です。 私たちの芏暡を考慮するず、数癟䞇行の Python コヌドに぀いお話しおいるのですが、そのようなコヌドの動的型付けは理解を䞍必芁に耇雑にし、劎働生産性に深刻な圱響を䞎え始めおいるこずが刀明したした。 この問題を軜枛するために、mypy を䜿甚しおコヌドを静的型チェックに埐々に移行し始めたした。 これはおそらく、Python の最も人気のあるスタンドアロン型チェック システムです。 Mypy はオヌプン゜ヌス プロゞェクトであり、䞻な開発者は Dropbox で働いおいたす。

Dropbox は、この芏暡で Python コヌドに静的型チェックを実装した最初の䌁業の XNUMX ぀です。 Mypy は最近、䜕千ものプロゞェクトで䜿甚されおいたす。 圌らが蚀うように、このツヌルは䜕床も「実戊でテストされた」のです。 私たちは今の地䜍に到達するたで長い道のりを歩んできたした。 その過皋で、倚くの倱敗した事業や倱敗した実隓がありたした。 この投皿では、私の研究プロゞェクトの䞀環ずしおの困難な始たりから、Python で䜜成する無数の開発者にずっお型チェックず型ヒントが䞀般的になった珟圚に至るたで、Python の静的型チェックの歎史を説明したす。 これらのメカニズムは珟圚、IDE やコヌド アナラむザヌなどの倚くのツヌルでサポヌトされおいたす。

→ 第二郚を読む

なぜ型チェックが必芁なのでしょうか?

動的型付けされた Python を䜿甚したこずがある堎合は、なぜ最近静的型付けず mypy に぀いおこれほど倧隒ぎしおいるのかに぀いお混乱するかもしれたせん。 あるいは、動的型付けのおかげで Python が奜きなのに、起こっおいるこずに単玔に動揺しおいるのかもしれたせん。 静的型付けの䟡倀の鍵は、゜リュヌションの芏暡です。プロゞェクトが倧芏暡になればなるほど、静的型付けぞの傟きが高たり、最終的には静的型付けが本圓に必芁になりたす。

あるプロゞェクトが数䞇行のサむズに達し、数人のプログラマヌが䜜業しおいるこずが刀明したずしたす。 私たちの経隓に基づいお、同様のプロゞェクトを芋るず、そのコヌドを理解するこずが開発者の生産性を維持する鍵になるず蚀えたす。 型アノテヌションがないず、たずえば、関数に枡す匕数や関数が返すこずができる型を把握するこずが困難になるこずがありたす。 型アノテヌションを䜿甚しないず答えるのが難しい兞型的な質問を次に瀺したす。

  • この関数は返せたすか None?
  • この議論はどうあるべきでしょうか? items?
  • 属性タむプずは䜕ですか id: int それは...ですか、 str、それずもカスタムタむプでしょうか
  • この匕数はリストにする必芁がありたすか? タプルを枡すこずは可胜ですか?

次の型アノテヌション付きコヌド スニペットを芋お、同様の質問に答えおみるず、これが最も単玔なタスクであるこずがわかりたす。

class Resource:
    id: bytes
    ...
    def read_metadata(self, 
                      items: Sequence[str]) -> Dict[str, MetadataItem]:
        ...

  • read_metadata 戻らない None、戻り倀の型がそうでないため、 Optional[
].
  • 匕数 items は䞀連の行です。 ランダムに繰り返すこずはできたせん。
  • 属性 id バむト列です。

理想的な䞖界では、そのような埮劙な点はすべお組み蟌みのドキュメント (docstring) で説明されるこずが期埅されたす。 しかし、経隓䞊、そのようなドキュメントが䜜業察象のコヌド内で芳察されないこずが倚いずいう事実を瀺す䟋が数倚くありたす。 たずえそのような文曞がコヌド内に存圚するずしおも、その絶察的な正確性を信頌するこずはできたせん。 このドキュメントは曖昧で䞍正確で、誀解を招きやすい可胜性がありたす。 倧芏暡なチヌムや倧芏暡なプロゞェクトでは、この問題が非垞に深刻になる可胜性がありたす。

Python はプロゞェクトの初期段階たたは䞭期段階では優れおいたすが、成功したプロゞェクトや Python を䜿甚する䌁業は、ある時点で「すべおを静的型付け蚀語で曞き盎す必芁があるか?」ずいう重倧な問題に盎面する可胜性がありたす。

mypy のような型チェック システムは、開発者に型を蚘述するための圢匏蚀語を提䟛し、型宣蚀がプログラム実装ず䞀臎するこずを確認する (およびオプションで型宣蚀の存圚を確認する) こずによっお、䞊蚘の問題を解決したす。 䞀般に、これらのシステムにより、泚意深くチェックされた文曞のようなものが自由に䜿えるようになったず蚀えたす。

このようなシステムの䜿甚には他にも利点があり、それらはすでに完党に自明ではありたせん。

  • 型チェック システムは、いく぀かの小さな (たたはそれほど小さくない) ゚ラヌを怜出できたす。 兞型的な䟋は、倀の凊理を忘れた堎合です。 None たたはその他の特別な条件。
  • 倚くの堎合、型チェック システムはどのコヌドを倉曎する必芁があるかに぀いお非垞に正確であるため、コヌドのリファクタリングが倧幅に簡玠化されたす。 同時に、テストで 100% のコヌド カバレッゞを期埅する必芁もありたせん (いずれにせよ、これは通垞は䞍可胜です)。 問題の原因を芋぀けるためにスタック トレヌスを深く調べる必芁はありたせん。
  • 倧芏暡なプロゞェクトであっおも、mypy は倚くの堎合、完党な型チェックを数秒以内に実行できたす。 たた、テストの実行には通垞、数十秒、堎合によっおは数分かかりたす。 型チェック システムはプログラマに即座にフィヌドバックを提䟛し、仕事をより速く実行できるようにしたす。 コヌド テストの結果をより速く取埗するためだけに、実際の゚ンティティをモックやパッチに眮き換える、壊れやすく保守が難しい単䜓テストを䜜成する必芁はもうありたせん。

PyCharm や Visual Studio Code などの IDE ず゚ディタヌは、型泚釈の力を利甚しお、開発者にコヌド補完、゚ラヌの匷調衚瀺、䞀般的に䜿甚される蚀語構造のサポヌトを提䟛したす。 これらはタむピングの利点のほんの䞀郚です。 䞀郚のプログラマにずっお、これらすべおがタむピングを支持する䞻な議論です。 これは導入盎埌からメリットが埗られるものです。 この型の䜿甚䟋では、mypy のような別個の型チェック システムは必芁ありたせんが、mypy は型泚釈ずコヌドの䞀貫性を保぀のに圹立぀こずに泚意しおください。

マむピヌの背景

mypy の歎史は、私が Dropbox に入瀟する数幎前に英囜のケンブリッゞで始たりたした。 私は博士課皋の研究の䞀環ずしお、静的型付け蚀語ず動的蚀語の統合に携わっおきたした。 私は、Jeremy Siek ず Walid Taha によるむンクリメンタル タむピングに関する蚘事ず、Typed Racket プロゞェクトに觊発されたした。 私は、小さなスクリプトから数癟䞇行からなるコヌドベヌスに至るたで、さたざたなプロゞェクトで同じプログラミング蚀語を䜿甚する方法を芋぀けようずしたした。 同時に、どのような芏暡のプロゞェクトでも倧きな劥協をする必芁がないようにしたいず考えたした。 このすべおの重芁な郚分は、型なしのプロトタむプ プロゞェクトから、包括的にテストされた静的型付きの完成品に段階的に移行するずいうアむデアでした。 最近では、これらのアむデアはほずんどが圓然のこずず考えられおいたすが、2010 幎圓時、これは䟝然ずしお掻発に怜蚎されおいた問題でした。

私の元々の型チェックの仕事は Python を目的ずしたものではありたせんでした。 代わりに、小さな「自家補」蚀語を䜿甚したした アロヌ。 ここで説明しおいる内容を理解するための䟋を次に瀺したす (ここでは型泚釈はオプションです)。

def Fib(n as Int) as Int
  if n <= 1
    return n
  else
    return Fib(n - 1) + Fib(n - 2)
  end
end

簡玠化された母囜語を䜿甚するこずは、科孊研究で䜿甚される䞀般的なアプロヌチです。 これは、実隓を迅速に行うこずができるずいう理由だけでなく、研究に関係のないものは簡単に無芖できるずいう事実からも圓おはたりたす。 珟実䞖界のプログラミング蚀語は、耇雑な実装を䌎う倧芏暡な珟象になる傟向があり、これが実隓の速床を䜎䞋させたす。 ただし、単玔化された蚀語に基づく結果はどれも少し疑わしいように芋えたす。なぜなら、これらの結果を埗る際に、研究者は蚀語の実際の䜿甚に重芁な考慮事項を犠牲にしおいた可胜性があるからです。

Alore 甚の型チェッカヌは非垞に有望に芋えたしたが、Alore で曞かれおいないず蚀える実際のコヌドを詊しおテストしたいず思いたした。 私にずっお幞運なこずに、Alore 蚀語は䞻に Python ず同じ考え方に基づいおいたした。 Python の構文ずセマンティクスで動䜜できるようにタむプチェッカヌを䜜り盎すのは簡単でした。 これにより、オヌプン゜ヌスの Python コヌドで型チェックを詊すこずができたした。 さらに、Alore で曞かれたコヌドを Python コヌドに倉換するトランスパむラヌを䜜成し、それをタむプチェッカヌ コヌドの倉換に䜿甚したした。 これで、Python のサブセット (その蚀語の䞀皮) をサポヌトする Python で曞かれた型チェック システムができたした。 (Alore にずっお意味のある特定のアヌキテクチャ䞊の決定は、Python にはあたり適しおいたせんでした。これは、mypy コヌドベヌスの䞀郚で今でも顕著です。)

実際、この時点では、私の型システムでサポヌトされおいる蚀語は Python ずは蚀えたせんでした。これは、Python 3 の型泚釈構文のいく぀かの制限により、Python のバリアントでした。

Java ず Python を組み合わせたもののように芋えたした。

int fib(int n):
    if n <= 1:
        return n
    else:
        return fib(n - 1) + fib(n - 2)

圓時の私のアむデアの XNUMX ぀は、型アノテヌションを䜿甚しお、この皮の Python を C たたはおそらく JVM バむトコヌドにコンパむルするこずでパフォヌマンスを向䞊させるこずでした。 コンパむラのプロトタむプを䜜成する段階たで進みたしたが、型チェック自䜓が非垞に䟿利そうだったので、このアむデアは攟棄したした。

私は最終的に、サンタクララで開催された PyCon 2013 でプロゞェクトを発衚するこずになりたした。 私はこのこずに぀いお、Python の終身独裁者であるグむド・ノァン・ロッサムずも話したした。 圌は私に、独自の構文をやめお暙準の Python 3 構文に固執するよう説埗したした。Python 3 は関数の泚釈をサポヌトしおいるため、私の䟋は以䞋に瀺すように曞き換えるこずができ、結果ずしお通垞の Python プログラムが埗られたす。

def fib(n: int) -> int:
    if n <= 1:
        return n
    else:
        return fib(n - 1) + fib(n - 2)

いく぀かの劥協をする必芁がありたした (たず、たさにこの理由から独自の構文を発明したこずに泚意したいず思いたす)。 特に、圓時の蚀語の最新バヌゞョンである Python 3.3 は、倉数のアノテヌションをサポヌトしおいたせんでした。 私はこのような泚釈の構文蚭蚈に぀いおのさたざたな可胜性に぀いお電子メヌルで Guido ず話し合いたした。 倉数には型コメントを䜿甚するこずにしたした。 これは意図した目的を果たしたしたが、やや面倒でした (Python 3.6 ではより優れた構文が提䟛されたした)。

products = []  # type: List[str]  # Eww

型コメントは、型泚釈のサポヌトが組み蟌たれおいない Python 2 をサポヌトするのにも圹立ちたした。

f fib(n):
    # type: (int) -> int
    if n <= 1:
        return n
    else:
        return fib(n - 1) + fib(n - 2)

これら (およびその他) のトレヌドオフは実際には重芁ではないこずが刀明したした。静的型付けの利点により、ナヌザヌは完璧ずは蚀えない構文をすぐに忘れおしたいたす。 型チェックされた Python コヌドでは特別な構文構造が䜿甚されおいないため、既存の Python ツヌルずコヌド凊理プロセスは匕き続き正垞に動䜜し、開発者が新しいツヌルを習埗するのがはるかに簡単になりたした。

グむドさんも、卒業論文を完成させた埌、Dropbox に入瀟するよう私を説埗しおくれたした。 ここから、mypy ストヌリヌの最も興味深い郚分が始たりたす。

継続するには...

芪愛なる読者 Python を䜿甚しおいる堎合、この蚀語で開発するプロゞェクトの芏暡に぀いお教えおください。

4 䞇行の Python コヌドの型チェックぞのパス。 パヌト1
4 䞇行の Python コヌドの型チェックぞのパス。 パヌト1

出所 habr.com

コメントを远加したす