listにjoinを追加してみた
もちろん、ご期待どおりあらびきな方法です。
src
高度に訓練されたpythonistaは継承で拡張なんてしません。
setup.py
from distutils.core import setup, Extension module1 = Extension('listjoin', sources = ['listjoin.c']) setup( name='PackageName', version='1.0', description='This is a demo package', ext_modules = [module1])
listjoin.c
#include <Python.h> static PyMethodDef ListMethods[] = { {NULL, NULL, 0, NULL} /* Sentinel */ }; static PyObject * string_join(PyStringObject *self, PyObject *orig) { char *sep = PyString_AS_STRING(self); const Py_ssize_t seplen = PyString_GET_SIZE(self); PyObject *res = NULL; char *p; Py_ssize_t seqlen = 0; size_t sz = 0; Py_ssize_t i; PyObject *seq, *item; seq = PySequence_Fast(orig, ""); if (seq == NULL) { return NULL; } seqlen = PySequence_Size(seq); if (seqlen == 0) { Py_DECREF(seq); return PyString_FromString(""); } if (seqlen == 1) { item = PySequence_Fast_GET_ITEM(seq, 0); if (PyString_CheckExact(item) || PyUnicode_CheckExact(item)) { Py_INCREF(item); Py_DECREF(seq); return item; } } for (i = 0; i < seqlen; i++) { const size_t old_sz = sz; item = PySequence_Fast_GET_ITEM(seq, i); if (!PyString_Check(item)){ if (PyUnicode_Check(item)) { /* Defer to Unicode join. * CAUTION: There's no gurantee that the * original sequence can be iterated over * again, so we must pass seq here. */ PyObject *result; result = PyUnicode_Join((PyObject *)self, seq); Py_DECREF(seq); return result; } item = Py_TYPE(item)->tp_str(item); } sz += PyString_GET_SIZE(item); if (i != 0) sz += seplen; if (sz < old_sz || sz > PY_SSIZE_T_MAX) { PyErr_SetString(PyExc_OverflowError, "join() result is too long for a Python string"); Py_DECREF(seq); return NULL; } } /* Allocate result space. */ res = PyString_FromStringAndSize((char*)NULL, sz); if (res == NULL) { Py_DECREF(seq); return NULL; } /* Catenate everything. */ p = PyString_AS_STRING(res); for (i = 0; i < seqlen; ++i) { size_t n; item = PySequence_Fast_GET_ITEM(seq, i); if (!PyString_Check(item)){ item = Py_TYPE(item)->tp_str(item); } n = PyString_GET_SIZE(item); Py_MEMCPY(p, PyString_AS_STRING(item), n); p += n; if (i < seqlen - 1) { Py_MEMCPY(p, sep, seplen); p += seplen; } } Py_DECREF(seq); return res; } static PyObject * listjoin(PyListObject *self, PyObject *sep) { assert(sep != NULL && PyString_Check(sep)); assert(x != NULL); return string_join((PyStringObject *)sep, self); } static PyMethodDef method = {"join", (PyCFunction)listjoin, METH_O, NULL}; PyMODINIT_FUNC initlistjoin(void) { PyObject *m; PyTypeObject *listobj; PyObject *dict; PyMethodDescrObject *descr; m = Py_InitModule("listjoin", ListMethods); listobj = &PyList_Type; dict = listobj->tp_dict; descr = PyDescr_NewMethod(listobj, &method); PyDict_SetItemString(dict, "join", (PyObject *)descr); }
実行
モジュールなのでimportします。
>>> import listjoin
>>> [1].join('')
'1'
>>> [1].join(',')
'1'
>>> [1, 2].join(',')
'1,2'
>>> [1, 2].join('-')
'1-2'
>>> ["1", "2"].join(',')
'1,2'
>>> ["1", "2"].join('-')
'1-2'
>>> ["1", "2", 3].join('-')
'1-2-3'
>>>
文字列への変換も自動(__str__表現)
とりあえず、かたつむりの林はおもしろいって話ですよねー。