CPython を実例に取り, 型がどのようなもので, どう機能するのかについて解説
型とは何か?CPython の実装by @cocoatomo, written in HuiFontP
View Slide
ご結婚おめでとうございます!!• 型い愛で結ばれたお二人に• CPython の型のお話をプレゼント
そもそも型とは?• 例を出すと
例えば血液型• A型• B型• AB型• O型
例えば軍艦• 金剛型• 陽炎型• 天城型• 利根型• etc…
「型とは値の集合である」• Types and Programming Languages• ↑型についての入門書• 「名古屋入国のためのパスポート」• 安全性 = 推進性 + 保全性
何の役に立つの?• 推進性 ⇒ 式の評価 (=計算) が値になるまで実行できることが分かる• 保全性 ⇒ 式の評価によって型が変わらない• ⇒ 「ある程度」ちゃんと動くことが保証され, 結果の予想できるプログラムが書ける
理論は分かったでは実際の実装は?• CPythonを見てみよう
え? Python に型あるの??• 「動的言語だから型は弱いんじゃないの?」• → その発言は危険が危ない!
Pythonにだって型はある!!!• TypeError: 型のエラー
混ぜるな危険• 「型付けルールがある」=型付き言語• 「値の型」と「変数の型」• ⇒ Python に無いのは変数の型• 「型チェックが『実行する』前に or 後で行われる」=(いわゆる) 静的とか動的とか• [余談] ところで「実行」の定義, 考えたことありますか? (読者の宿題)
Pythonとは• クラスベースオブジェクト指向プログラミング言語 (全てのものはobject)• 実行時の型チェック• 参照カウントGC• 思想: Zen of Python• Explicit is better than implicit.etc…
CPythonとは• C で実装された Python• ⇒ C とは異なる型システムをどう実装しているのか?
ソースコード• https://www.python.org/ftp/python/3.4.0/Python-3.4.0.tar.xz にソースコードがある.• ↑のリンクがあるページは https://www.python.org/downloads/release/python-340/
PyObject• Pythonの型階層の基底クラス object のC 実装• 「全てのものはPyObject!」• Include/object.h で宣言されている型• ⇒ 実装を見てみよう
PyObjectの実装• 実体はCの「構造体」
PyObject の型は?⇒ ob_type が PyObject の型
struct _typeobject とは?⇒ CPythonの型は「構造体」で表現!
その中身は?ずらっと関数ポインタが並ぶ
PyTypeObject最後に PyTypeObject に typedef
CPythonの型• 結局, CPythonにとっての型は関数の集まり (構造体)• (→他の言語での型の表現方法については詳しい人教えて)
型の判定• メソッドの引数チェックとかどうしてるの?• → さっきの「3 +’a’」の C での動きを見てみよう
メソッド呼び出しとは?• Python では以下の3つは同じ意味• 「3 + ’a’」• =「3.__add__(‘a’)」• =「int.__add__(3, ‘a’)」
C では?• 「int.__add__」の実装は• Object/abstract.c• にある• PyNumber_Add 関数
CPython の読み方• CPython の命名規則ではメソッドの実装は• Object/object.c• にある• Py_• という名前の関数となっている
Number 型って?• int, float, bool, complex の上位の抽象型• Python の protocol と呼ばれるもの
protocol• Java の interface のようなもの• 実装すべきメソッドの集合を定めてある• Long は Number protocol を提供している• もちろんコンパイラのチェックは無い• ↑そもそも Python にコンパイラが無い
結局, 呼び出されるのは• PyNumber_Add から,• PyLong_Type->tp_as_number ->nb_add• と型構造体のメンバを辿って• Object/longobject.c• にある long_add 関数が呼ばれる
long_add 関数⇒ CHECK_BINOP に注目!
CHECK_BINOP macro⇒ ここで引数チェックをしていた!
なんで型チェックするの?• long_add の引数は PyLongObject なのに、なんで CHECK_BINOP で型チェックするの!?
long_add の型への登録• PyLong_Type->tp_as_number のメンバnb_add に long_add が代入される箇所を見ると……
キャストされとる!(※この long_as_number がPyLong_Type->tp_as_number に代入される)
PyObject だらけ• 実行時に PyObject から PyTypeObject(=関数の集まり) を取得し, 最初に型チェック• よく見ると, せっかくの C の型情報がキャストで消えてる (引数も返り値もPyObject)• ⇒ これが「動的」と言われる所以
Python/C API• ここらへんの内容は, Python 公式ドキュメントの C API の項に載ってる• http://docs.python.jp/3.3/c-api/index.html
公式ドキュメント• 言語仕様, チュートリアル, 標準ライブラリの解説……が載っている文書• 日本語訳もあるよ• 私を含めチームで3.3を翻訳中• ⇒ I needs you• https://code.google.com/p/python-doc-ja/
まとめ• CPython の型オブジェクトは構造体• CPython の実行時の型チェックは、型オブジェクトを毎回調べる• Python 3.3 ドキュメント翻訳中!