8
  • __dict__「通常の」クラスのように作成された型は、Pythonで定義された場合どのように作成されますか?
  • sを使用した非動的タイプの例はあります__dict__か?
  • PythonのPyTypeObjectパススルーを介して定義された型はありtype_newますか?

tp_dictメンバーがPyTypeObjectいますが、使い方がわかりません。でも何かが起こっているようですがtypeobject.ctype_newはっきりと解読できません。

これが私が見つけたいくつかの関連情報です:

4

4 に答える 4

6

__dict__次のコードは、 Python2.xでを実装するクラスを生成します。

typedef struct {
  PyObject_HEAD
  PyObject* dict;
} BarObject;

static PyTypeObject BarObject_Type = {
  PyObject_HEAD_INIT(NULL)
};

PyMODINIT_FUNC
initFoo(void)
{
  PyObject *m;

  m = Py_InitModule("Foo", NULL);
  if (m == NULL)
    return;

  BarObject_Type.tp_new = PyType_GenericNew;
  BarObject_Type.tp_name = "Foo.Bar";
  BarObject_Type.tp_basicsize = sizeof(BarObject);
  BarObject_Type.tp_getattro = PyObject_GenericGetAttr;
  BarObject_Type.tp_setattro = PyObject_GenericSetAttr;
  BarObject_Type.tp_flags = Py_TPFLAGS_DEFAULT;
  BarObject_Type.tp_dictoffset = offsetof(BarObject,dict);
  BarObject_Type.tp_doc = "Doc string for class Bar in module Foo.";
  if (PyType_Ready(&BarObject_Type) < 0)
    return;

  Py_INCREF(&BarObject_Type);
  PyModule_AddObject(m, "Bar", (PyObject*)&BarObject_Type);
}

重要なビットは、構造体(http://docs.python.org/c-api/typeobj.html)のtp_dictoffsetメンバーです。PyTypeObject

このタイプのインスタンスにインスタンス変数を含むディクショナリがある場合、このフィールドはゼロ以外であり、インスタンス変数ディクショナリのタイプのインスタンスのオフセットが含まれます。このオフセットは、PyObject_GenericGetAttr()によって使用されます。

このフィールドをtp_dictと混同しないでください。これは、タイプオブジェクト自体の属性の辞書です。

于 2012-09-20T02:31:45.917 に答える
2

最後の質問に最初に答えるには:いいえ、type_new実行時に動的に定義される「ヒープタイプ」にのみ使用されます(たとえば、クラスステートメントを介して)。静的に定義されたタイプは、PyType_Ready()代わりにを使用して初期化されます。

最初の質問に答えるには、__dict__記述子を使用して拡張型を作成するには、インタープリターがクラス定義に対して行うのと同じ方法で型を動的に割り当てる必要があります。

そのための例を取得する1つの方法は、Johnが提案するように実行し、Cythonを使用して独自の例をいくつか生成することです。

CPython 2.xの場合build_class、CPythonソースコード(http://svn.python.org/view/python/trunk/Python/ceval.c?view=markup)のメソッドを調べて、手順を理解することができます。完全に一般的なソリューションに関与します。

ただし、Python 3を使用している場合は、この質問が興味深いかもしれません。Pythonの組み込みの__build_class__は何をしますか?

つまり、CPython 3.x固有のソリューションとして、最も簡単な方法は、CAPIbuiltins.__build_class__を介して適切な引数を使用して呼び出すことです。

于 2011-02-21T01:58:06.650 に答える
1

私はこれを行っていません。C-APIを使用するのは恥ずかしいほど悪いですが、ドキュメントによると、andメソッドを使用するだけで十分PyObject_GenericGetAttrPyObject_GenericSetAttrはずgetattroですsetattro。もちろん、PyObject属性も必要です__dict__

あなたはそれを試しましたか?

于 2011-02-21T09:47:12.593 に答える
0

クラスとメソッドを1つか2つ定義するPythonコードを記述し、それをCythonでコンパイルして、生成されたCコードを検査するのはどうですか?

于 2011-02-21T00:53:45.920 に答える