Pythonのクラスの中身は関数である

この記事は人間でもわかるPythonバイトコードシリーズ第2回目の記事ですが、この記事から見始めても大丈夫です。
前回の記事は[こちら](https://qiita.com/MtShiba/items/6734fe97f4c4fc658936)です。

前回の記事で、次は.pycファイルのフォーマットについて説明すると書きました。が、Pythonバイトコードの仕様について調べているうちにクラスと関数の__興味深い関係__を発見しましたので、予定を変更し、タイトルも独立したものとして記事を書くこととしました。

# 環境

CPython 3.9.0

# Pythonは関数をどう定義しているか？

まずPythonインタープリタ内での関数の扱われ方について見ていきましょう。
次のスクリプトのバイトコードを逆アセンブルします。逆アセンブルとはなんぞという人は[前回の記事](https://qiita.com/MtShiba/items/6734fe97f4c4fc658936)を参照してください。

```python
def f(x, y):
    return x + y
```

2つの引数を足す関数を定義しただけのスクリプトです。結果は以下のようになります。

```console
  1           0 LOAD_CONST               0 (<code object f at 0x10ddb4190, file "test1.py", line 1>)
              2 LOAD_CONST               1 ('f')
              4 MAKE_FUNCTION            0
              6 STORE_NAME               0 (f)
              8 LOAD_CONST               2 (None)
             10 RETURN_VALUE

Disassembly of <code object f at 0x10ddb4190, file "test1.py", line 1>:
  2           0 LOAD_FAST                0 (x)
              2 LOAD_FAST                1 (y)
              4 BINARY_ADD
              6 RETURN_VALUE
```

Pythonは関数を第一級オブジェクトととして扱います。つまり、関数を宣言できるだけは足りず、オブジェクトとして動的に生成する命令が必要になります。それこそが4バイト目にある`MAKE_FUNCTION`です。

関数の生成に必要なものは、中身を表すコードオブジェクトと、関数の名前です。そのため`MAKE_FUNCTION`の前に、`LOAD_CONST`でコードオブジェクトと関数の名前fをロードしています。しかしコードオブジェクトには既にfという名前がついています。代入命令である`STORE_NAME`と合わせると、3回も関数の名前fが登場しています。くどいですね。

これはPythonバイトコードに無名関数を生成する命令がないからとも言えます。Pythonの無名関数(lambda式)は後付けの機能のため、単に`<lambda>`という名前の関数を生成することによって実現されています。

```python
lambda x: x + 1
```
↓

```console
  1           0 LOAD_CONST               0 (<code object <lambda> at 0x10c470190, file "test1.py", line 1>)
              2 LOAD_CONST               1 ('<lambda>')
              4 MAKE_FUNCTION            0
              6 POP_TOP
              8 LOAD_CONST               2 (None)
             10 RETURN_VALUE

Disassembly of <code object <lambda> at 0x10c470190, file "test1.py", line 1>:
  1           0 LOAD_FAST                0 (x)
              2 LOAD_CONST               1 (1)
              4 BINARY_ADD
              6 RETURN_VALUE
```

# コードオブジェクトとは？

気になるのはコードオブジェクトが一体何モノであるかということです。コードオブジェクトについては前回少し説明しましたが、その本質は__スコープの表現__です。コードオブジェクトはスコープを実現するために変数の名前テーブルを持っています。

よってPythonでスコープを持つものはなんでもコードオブジェクトを持っています(ex. 関数、クラス、モジュール)。逆にコードオブジェクトを使って表現されないものはスコープを持ちません。その例がifやwhile、for文などです。

```python
for i in range(1):                                                        
    j = 1
print(j)
```

このスクリプトを実行すると1が出力されますが、同じことをC言語でやろうとするとエラーになります。
このようなキモコードが動くカラクリは、まさにバイトコードを覗くことによって理解できるのです。

```console
  1           0 LOAD_NAME                0 (range)
              2 LOAD_CONST               0 (1)
              4 CALL_FUNCTION            1
              6 GET_ITER
        >>    8 FOR_ITER                 8 (to 18)
             10 STORE_NAME               1 (i)

  2          12 LOAD_CONST               0 (1)
             14 STORE_NAME               2 (j)
             16 JUMP_ABSOLUTE            8

  3     >>   18 LOAD_NAME                3 (print)
             20 LOAD_NAME                2 (j)
             22 CALL_FUNCTION            1
             24 POP_TOP
             26 LOAD_CONST               1 (None)
             28 RETURN_VALUE
```

16バイト目の`JUMP_ABSOLUTE`から分かるように、for文は原始的なジャンプ機能を使って実現されています。10~16バイト目が内側の処理に相当し、`FOR_ITER`にてイテレータが使い切られるまでループが続くというわけです。そしてjの定義が参照と同じフレーム内で行われているため、エラーにならないのです。

関数の例からすると、for文が内側の処理をコードオブジェクトを使って閉じ込めても良さそうなものです。しかし実際にはそうなっていません。これは恐らく高速化のためでしょう。ジャンプのように処理が低級であるほど実行は高速になります(それでもPythonのforは素晴らしく遅いですが)。あとループ変数の初期化をしなくて済むというメリットもありますね。

# クラスと関数

これでクラスと関数の関係性について説明できます。
先ほど言った通り、Pythonでは関数とクラスは独自のスコープを持ちます。
そのスコープはコードオブジェクトを用いて表されるので、この点で関数とクラスが共通点を持つことがわかります。
では、次のスクリプトはどのようになるでしょうか？

```python
def f():
  x = 1

class F:
  x = 1

print(f.x, F.x)
```

上のスクリプトのバイトコードは以下のように逆アセンブルされます(注:実行するとエラーになります)。

```console
  1           0 LOAD_CONST               0 (<code object f at 0x101033190, file "test1.py", line 1>)
              2 LOAD_CONST               1 ('f')
              4 MAKE_FUNCTION            0
              6 STORE_NAME               0 (f)

  4           8 LOAD_BUILD_CLASS
             10 LOAD_CONST               2 (<code object F at 0x101033240, file "test1.py", line 4>)
             12 LOAD_CONST               3 ('F')
             14 MAKE_FUNCTION            0
             16 LOAD_CONST               3 ('F')
             18 CALL_FUNCTION            2
             20 STORE_NAME               1 (F)

  7          22 LOAD_NAME                2 (print)
             24 LOAD_NAME                0 (f)
             26 LOAD_ATTR                3 (x)
             28 LOAD_NAME                1 (F)
             30 LOAD_ATTR                3 (x)
             32 CALL_FUNCTION            2
             34 POP_TOP
             36 LOAD_CONST               4 (None)
             38 RETURN_VALUE

Disassembly of <code object f at 0x101033190, file "test1.py", line 1>:
  2           0 LOAD_CONST               1 (1)
              2 STORE_FAST               0 (x)
              4 LOAD_CONST               0 (None)
              6 RETURN_VALUE

Disassembly of <code object F at 0x101033240, file "test1.py", line 4>:
  4           0 LOAD_NAME                0 (__name__)
              2 STORE_NAME               1 (__module__)
              4 LOAD_CONST               0 ('F')
              6 STORE_NAME               2 (__qualname__)

  5           8 LOAD_CONST               1 (1)
             10 STORE_NAME               3 (x)
             12 LOAD_CONST               2 (None)
             14 RETURN_VALUE
```

0~6バイト目が関数`f`の生成、8~20バイト目がクラス`F`の生成です。
なんだか似たような行程を踏んでいると分かります。特にFの生成では、クラスの生成なのになぜか`MAKE_FUNCTION`が呼ばれているではありませんか。
8バイト目の`LOAD_BUILD_CLASS`がポイントです。この命令は特殊な組み込み関数である`__build_class__`をロードします。この関数は18バイト目で<ruby>呼び出<rp>（</rp><rt>C A L L</rt><rp>）</rp></ruby>されています。

この関数はメタクラスを生成する関数です。
メタクラスはクラスのクラスです。つまり、メタクラスのインスタンスはクラスになります。関数が第一級オブジェクトなのだから当然クラスも第一級オブジェクトとして扱いたいわけで、この関数が必要になります。
`__build_class__`のCPythonでの実装を見てみましょう。

```c:cpython/Python/bltinmodule.c
static PyObject *
builtin___build_class__(PyObject *self, PyObject *const *args, Py_ssize_t nargs,
                        PyObject *kwnames)
{
    PyObject *func, *name, *bases, *mkw, *meta, *winner, *prep, *ns, *orig_bases;
    PyObject *cls = NULL, *cell = NULL;
    int isclass = 0;   /* initialize to prevent gcc warning */

    if (nargs < 2) {
        PyErr_SetString(PyExc_TypeError,
                        "__build_class__: not enough arguments");
        return NULL;
    }
    func = args[0];   /* Better be callable */
    if (!PyFunction_Check(func)) {
        PyErr_SetString(PyExc_TypeError,
                        "__build_class__: func must be a function");
        return NULL;
    }

...

    cell = PyEval_EvalCodeEx(PyFunction_GET_CODE(func), PyFunction_GET_GLOBALS(func), ns,
                             NULL, 0, NULL, 0, NULL, 0, NULL,
                             PyFunction_GET_CLOSURE(func));
...
```

これを見るに、この関数の第一引数は関数オブジェクトであることがわかります。その関数をもとにcellというオブジェクトを作ります。そしてこの後、cellからクラスが生成されます。
......これでこの記事のタイトルの真意が理解できたと思います。
なんと、__クラスのボディは関数を流用していた__のです！

# 終わりに

今回は以上です。ここまで読んでいただきありがとうございました。
次回は当初の予定通り.pycファイルのフォーマットについて解説します。

# 参考

[Python/ビルトインがビルトインされるまで - Code Reading Wiki](http://www.dzeta.jp/~junjis/code_reading/index.php?Python%2F%E3%83%93%E3%83%AB%E3%83%88%E3%82%A4%E3%83%B3%E3%81%8C%E3%83%93%E3%83%AB%E3%83%88%E3%82%A4%E3%83%B3%E3%81%95%E3%82%8C%E3%82%8B%E3%81%BE%E3%81%A7)

[メタクラス - Wikipedia](https://ja.wikipedia.org/wiki/%E3%83%A1%E3%82%BF%E3%82%AF%E3%83%A9%E3%82%B9)