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

2024-06-26 14:54:37 发布

您现在位置:Python中文网/ 问答频道 /正文

  • 如果在Python中定义了一个“普通”类,如何创建一个具有__dict__的类型?在
  • 有没有使用__dict__s的非动态类型的例子?在
  • 通过Python的^{}定义的类型是否通过^{}?在

有一个tp_dict成员,PyTypeObject,但是我找不到关于如何使用它的信息。在typeobject.ctype_new中似乎也发生了一些事情,但我无法清楚地解读它。在

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


Tags: in信息类型new定义type动态成员
3条回答

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

要回答第一个问题:要使用__dict__描述符创建扩展类型,需要像解释器为类定义所做的那样动态分配类型。在

获取例子的一种方法是按照John的建议来做,并用Cython生成一些自己的例子。在

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

如果您使用的是python3,那么这个问题可能会引起您的兴趣:What does Python's builtin __build_class__ do?

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

我还没有这样做,我在使用C-API方面很糟糕,但是根据文档,使用PyObject_GenericGetAttr和{}来使用getattro和{}方法就足够了。当然,您还需要一个名为__dict__的PyObject属性。在

你试过了吗?在

下面的代码将生成一个在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);
}

重要的位是PyTypeObject结构(http://docs.python.org/c-api/typeobj.html)的tp_dictoffset成员:

If the instances of this type have a dictionary containing instance variables, this field is non-zero and contains the offset in the instances of the type of the instance variable dictionary; this offset is used by PyObject_GenericGetAttr().

Do not confuse this field with tp_dict; that is the dictionary for attributes of the type object itself.

相关问题 更多 >