__dict__
类型是如何在Python中定义的那样?__dict__
s PyTypeObject
定义的类型是否通过type_new
? tp_dict
有一个PyTypeObject
成员,但我找不到有关如何使用它的信息。 typeobject.c
type_new
似乎还有一些问题,但我无法清楚地解读它。
以下是我发现的一些相关信息:
答案 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_GenericGetAttr
和PyObject_GenericSetAttr
作为getattro
就足够了}和setattro
方法。您当然还需要一个名为__dict__
的PyObject属性。
你试过吗?
答案 3 :(得分:0)
如何编写定义一个类和一个或两个方法的Python代码,用Cython编译它并检查生成的C代码?