从C创建一个实现__dict__的Python类型?

时间:2011-02-21 00:41:46

标签: python c types python-3.x python-c-api

  • 如果根据“普通”类创建的__dict__类型是如何在Python中定义的那样?
  • 是否有__dict__ s
  • 的非动态类型示例
  • 通过Python的PyTypeObject定义的类型是否通过type_new

tp_dict有一个PyTypeObject成员,但我找不到有关如何使用它的信息。 typeobject.c type_new似乎还有一些问题,但我无法清楚地解读它。

以下是我发现的一些相关信息:

4 个答案:

答案 0 :(得分:6)

以下代码将生成一个在Python 2.x中实现__dict__的类:

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);
}

重要的一位是tp_dictoffset结构PyTypeObject成员{{1}}成员:

  

如果此类型的实例具有包含实例的字典   变量,该字段非零并包含偏移量   实例变量字典类型的实例;这个偏移   由PyObject_GenericGetAttr()使用。

     

不要将此字段与tp_dict混淆;那是字典   类型对象本身的属性。

答案 1 :(得分:2)

首先回答最后一个问题:不,type_new仅用于在运行时动态定义的“堆类型”(例如,通过类语句)。静态定义的类型使用PyType_Ready()进行初始化。

回答第一个问题:要创建一个带有__dict__描述符的扩展类型,您需要以与解释器对类定义相同的方式动态分配类型。

获得示例的一种方法是按照John建议并使用Cython生成一些您自己的示例。

对于CPython 2.x,您可以查看CPython源代码(http://svn.python.org/view/python/trunk/Python/ceval.c?view=markup)中的build_class方法,以了解完全通用解决方案中涉及的步骤。

如果你正在使用Python 3,那么这个问题可能会引起关注:What does Python's builtin __build_class__ do?

也就是说,作为CPython 3.x特定的解决方案,最简单的方法是通过C API使用适当的参数调用builtins.__build_class__

答案 2 :(得分:1)

我还没有这样做,我对使用C-API感到非常尴尬,但根据文档,使用PyObject_GenericGetAttrPyObject_GenericSetAttr作为getattro就足够了}和setattro方法。您当然还需要一个名为__dict__的PyObject属性。

你试过吗?

答案 3 :(得分:0)

如何编写定义一个类和一个或两个方法的Python代码,用Cython编译它并检查生成的C代码?