梅村流Python探検隊　1日目

梅村流Python探検隊の詳細は <a href="http://qiita.com/Bython-Chogo/items/1af6adb309a9d0d57199">「梅村流Python探検隊　0日目」</a> をご参照！

探検初日は「ソースコードからBuiltin関数を探る」をテーマに進めていきたいと思います。

#Buitin関数とは？？
組み込み関数ともいいます。ずばり、importしなくても使える、もともと組み込まれている関数のことです。代表的なところは print とかでしょうか。チュートリアルにBuiltin関数の一覧がありますのでご参考。
http://docs.python.jp/2/library/functions.html

Builtin関数と対照的にimportして使うような関数(例：os.path)などはわかりやすいんです。PythonをInstallしたフォルダのなかのLibフォルダに（基本的には）.py 形式で保存してあるからです。一方のBuiltin関数は文字通りpythonの実行ファイルに組み込まれた形でBuildしちまっているもんなんで、ソースコードを当たらないと見つからないんですねー。

#ソースコードを見てみよう！
実際にソースコードを当たってみましょう。今回は Python-3.6.0.tgzをDownloadして中をみてみましたが、Builtin関数を確認するだけなのでどのバージョンでもよいはずです。
おいてある場所はここ：　https://www.python.org/downloads/source/

中身をみてみるとPythonをシステムにインストールするためのソースコードとかが入ったフォルダがでてきます。（そりゃそうだ。）今回目的のBuiltin関数のフォルダは以下においてあります。
/Python/bltinmodule.c

中をのぞいてみましょう。代表的な print のソースはいかに書かれているようです。(1744行目)

    static PyObject *
    builtin_print(PyObject *self, PyObject *args,  PyObject *kwds)
    {
        static char *kwlist[] = {"sep", "end", "file", "flush", 0};
        static PyObject *dummy_args;
        PyObject *sep = NULL, *end = NULL, *file =  NULL, *flush = NULL;
        int i, err;
        ....


C言語でPython実行ファイルをBuildするときにこのように print 関数も組み込んでBuildしちゃうんですね、なるほど。

#Builtin関数のリストを見てみる
builtin_methodsの配列にBuiltinする関数のリストが見られます。（2613行）

    static PyMethodDef builtin_methods[] = {
    {"__build_class__", (PyCFunction)builtin___build_class__,
     METH_VARARGS | METH_KEYWORDS, build_class_doc},
    {"__import__",      (PyCFunction)builtin___import__, METH_VARARGS | METH_KEYWORDS, import_doc},
    BUILTIN_ABS_METHODDEF
    BUILTIN_ALL_METHODDEF
    BUILTIN_ANY_METHODDEF
    BUILTIN_ASCII_METHODDEF
    BUILTIN_BIN_METHODDEF
    BUILTIN_CALLABLE_METHODDEF
    BUILTIN_CHR_METHODDEF
    BUILTIN_COMPILE_METHODDEF
    BUILTIN_DELATTR_METHODDEF
    {"dir",             builtin_dir,        METH_VARARGS, dir_doc},
    BUILTIN_DIVMOD_METHODDEF
    BUILTIN_EVAL_METHODDEF
    BUILTIN_EXEC_METHODDEF
    BUILTIN_FORMAT_METHODDEF
    {"getattr",         builtin_getattr,    METH_VARARGS, getattr_doc},
    BUILTIN_GLOBALS_METHODDEF
    BUILTIN_HASATTR_METHODDEF
    BUILTIN_HASH_METHODDEF
    BUILTIN_HEX_METHODDEF
    BUILTIN_ID_METHODDEF
    BUILTIN_INPUT_METHODDEF
    BUILTIN_ISINSTANCE_METHODDEF
    BUILTIN_ISSUBCLASS_METHODDEF
    {"iter",            builtin_iter,       METH_VARARGS, iter_doc},
    BUILTIN_LEN_METHODDEF
    BUILTIN_LOCALS_METHODDEF
    {"max",             (PyCFunction)builtin_max,        METH_VARARGS | METH_KEYWORDS, max_doc},
    {"min",             (PyCFunction)builtin_min,        METH_VARARGS | METH_KEYWORDS, min_doc},
    {"next",            (PyCFunction)builtin_next,       METH_VARARGS, next_doc},
    BUILTIN_OCT_METHODDEF
    BUILTIN_ORD_METHODDEF
    BUILTIN_POW_METHODDEF
    {"print",           (PyCFunction)builtin_print,      METH_VARARGS | METH_KEYWORDS, print_doc},
    BUILTIN_REPR_METHODDEF
    {"round",           (PyCFunction)builtin_round,      METH_VARARGS | METH_KEYWORDS, round_doc},
    BUILTIN_SETATTR_METHODDEF
    BUILTIN_SORTED_METHODDEF
    BUILTIN_SUM_METHODDEF
    {"vars",            builtin_vars,       METH_VARARGS, vars_doc},
    {NULL,              NULL},
    };

ん？2パターンみられますね。一つは printなど、構造体が記載されている関数。もう一つは変数に置き換えられているような関数。前者はこの cファイルにソースコードが記載されているようですが、後者はどこにいらっしゃるのでしょうか。

こたえは以下のヘッダファイルにありました！
/Python/clinic/bltinmodule.c.h

たとえば abs関数は・・・

    #define BUILTIN_ABS_METHODDEF    \
        {"abs", (PyCFunction)builtin_abs, METH_O, builtin_abs__doc__},


ここで定義を2つに分けている理由はわかりません。Buildがしやすかったりするのでしょうが、そこを突き止めるのは今回やめておきます。


#まとめ
Builtin関数をソースコードの探検、いかがだったでしょうか。ん？物足りないでしょうか？そうだったら申し訳けありませんが、このレベルでちょっと気になったことを軽く調べたレポートをだらだら続けていこうかと思っております。もしお付き合いいただけましたら幸いにございます。