🐈

pythonの bin()関数の中身を見る

2024/08/18に公開

二進数文字列に変換してくれる関数 bin()

0bがつくことに注意

a = 5
b = bin(a)
print(b)
#--- output ---
# 0b101

今週プログラミングで使う機会があったので、こういう組み込み関数のソースでも見てみる。
結論としては思っていた何倍も長く、なるほどね、とはならなかった。


エントリーポイントがあっているのか怪しいですが、おそらくこちら

cpython/Python/bltinmodule.c
static PyObject *
builtin_bin(PyObject *module, PyObject *number)
/*[clinic end generated code: output=b6fc4ad5e649f4f7 input=53f8a0264bacaf90]*/
{
    return PyNumber_ToBase(number, 2);
}

PyNumber_ToBase が下に続く。2しか使っていませんでしたが、2 or 8 or 10 or 16のassertがあるんですね。

cpython/Objects/abstract.c
PyNumber_ToBase(PyObject *n, int base)
{
    if (!(base == 2 || base == 8 || base == 10 || base == 16)) {
        PyErr_SetString(PyExc_SystemError,
                        "PyNumber_ToBase: base must be 2, 8, 10 or 16");
        return NULL;
    }
    PyObject *index = _PyNumber_Index(n);
    if (!index)
        return NULL;
    PyObject *res = _PyLong_Format(index, base);
    Py_DECREF(index);
    return res;
}

一応_PyLong_Formatも見てみます

cpython/Objects/longobject.c
PyObject *
_PyLong_Format(PyObject *obj, int base)
{
    PyObject *str;
    int err;
    if (base == 10)
        err = long_to_decimal_string_internal(obj, &str, NULL, NULL, NULL);
    else
        err = long_format_binary(obj, base, 1, &str, NULL, NULL, NULL);
    if (err == -1)
        return NULL;
    return str;
}

同一ファイルのlong_format_binaryがある。長いので転記はやめておきます。
writerがNULLなのでv = PyUnicode_New(sz, 'x')が仕事をしているように読めました。
出力の先頭の0bもここで見て取れました。(0x[16進数], 0o[8進数])もあるみたいですね。

今後の課題として読めるよう頑張ります。

Discussion