View All Posts. MiCHiLU.com powered by Django ;-)

[Python]: metaclass memo

全くよく解らないので、ソースを見てみる

http://www-06.ibm.com/jp/developerworks/linux/030425/j_l-pymeta.html

Versionは2.5.1 http://svn.python.org/view/python/tags/r251/ から落としてくる

__metaclass__ でgrepすると

などが見つかる

Python/ceval.c:4060

static PyObject *
build_class(PyObject *methods, PyObject *bases, PyObject *name)
{

build_class はPythonバイトコード命令の BUILD_CLASS に対応している http://www.python.jp/doc/2.4/lib/bytecodes.html

BUILD_CLASS
新しいクラスオブジェクトを作成します。TOSはメソッド辞書、TOS1は基底クラスの名前のタプル、TOS2はクラス名です。
  PyObject *metaclass = NULL, *result, *base;

  if (PyDict_Check(methods))
    metaclass = PyDict_GetItemString(methods, "__metaclass__");
  if (metaclass != NULL)
    Py_INCREF(metaclass);
  else if (PyTuple_Check(bases) && PyTuple_GET_SIZE(bases) > 0) {
    base = PyTuple_GET_ITEM(bases, 0);
    metaclass = PyObject_GetAttrString(base, "__class__");
    if (metaclass == NULL) {
      PyErr_Clear();
      metaclass = (PyObject *)base->ob_type;
      Py_INCREF(metaclass);
    }
  }
  else {
    PyObject *g = PyEval_GetGlobals();
    if (g != NULL && PyDict_Check(g))
      metaclass = PyDict_GetItemString(g, "__metaclass__");
    if (metaclass == NULL)
      metaclass = (PyObject *) &PyClass_Type;
    Py_INCREF(metaclass);
  }
  result = PyObject_CallFunctionObjArgs(metaclass, name, bases, methods, NULL);
  Py_DECREF(metaclass);
  if (result == NULL && PyErr_ExceptionMatches(PyExc_TypeError)) {
    ...
  }
  return result;
}

metaclass

  1. クラスの __metaclass__ を代入

  2. スーパークラス( __bases__ )がある

    1つ目のスパークラスの __class__ を代入 なければ、1つ目のスパークラスの ob_type を代入

  3. Global(module)の __metaclass__ を代入

  4. PyClass_Type を代入

が入る。 __metaclass__ を記述するということは、このステップを操作すること。

Py_INCREF, Py_DECREF は参照カウンタのインクリメント/デクリメント。 http://www.python.jp/doc/2.4/ext/refcountsInPython.html

ob_type

http://www.python.jp/doc/2.4/api/type-structs.html

PyTypeObject* ob_type

型自体の型、別の言い方をするとメタタイプです。 PyObject_HEAD_INIT マクロで初期化され、通常は &PyType_Type になります。 Python 2.2.1 およびそれ以降では基底クラスの ob_type フィールドに初期化します。 ob_type が非ゼロの場合、PyType_Ready() は このフィールドを変更しません。 2.2.1 と 2.3 以降では、サブタイプはこのフィールドを継承します。

PyClass_Type

Objects/classobject.c:423

PyTypeObject PyClass_Type = {
  PyObject_HEAD_INIT(&PyType_Type)
  ...
};

PyObject_HEAD_INIT

http://www.python.jp/doc/2.4/ext/dnt-basics.html

PyObject_HEAD_INIT(&PyType_Type)
この場合、タイプオブジェクトの型は「type」という名前になります
Fri, 18 Jan 2008 01:12:35 +0900 source edit
Creative Commons License
This work is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 2.1 Japan License.

Comments


View All Posts. MiCHiLU.com powered by Django ;-)