__dict__
如果在 Python 中定义了一个“普通”类,它是如何创建的?- 是否有任何带有 s 的非动态类型的示例
__dict__
? - 通过 Python 定义的类型是否
PyTypeObject
通过type_new
?
有一个tp_dict
成员PyTypeObject
,但我找不到有关如何使用它的信息。typeobject.c
's中似乎也发生了一些事情,type_new
但我无法清楚地破译它。
以下是我找到的一些相关信息:
__dict__
如果在 Python 中定义了一个“普通”类,它是如何创建的?__dict__
?PyTypeObject
通过type_new
?有一个tp_dict
成员PyTypeObject
,但我找不到有关如何使用它的信息。typeobject.c
's中似乎也发生了一些事情,type_new
但我无法清楚地破译它。
以下是我找到的一些相关信息:
以下代码将生成一个__dict__
在 Python 2.x 中实现 a 的类:
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
(http://docs.python.org/c-api/typeobj.html):
如果这个类型的实例有一个包含实例变量的字典,这个字段是非零的并且包含实例变量字典的类型的实例中的偏移量;PyObject_GenericGetAttr() 使用这个偏移量。
不要将此字段与 tp_dict 混淆;那是类型对象本身属性的字典。
首先回答最后一个问题:不,type_new
仅用于在运行时动态定义的“堆类型”(例如通过类语句)。PyType_Ready()
相反,静态定义的类型被初始化。
要回答您的第一个问题:要使用描述符创建扩展类型__dict__
,您需要像解释器为类定义所做的那样动态分配类型。
获取示例的一种方法是按照 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 特定的解决方案,最简单的方法是builtins.__build_class__
通过 C API 使用适当的参数进行调用。
我还没有这样做,我在使用 C-API 时非常糟糕,但根据文档,使用andPyObject_GenericGetAttr
方法应该就足够PyObject_GenericSetAttr
了。当然,您还需要有一个 PyObject 属性。getattro
setattro
__dict__
你试过吗?
编写一些定义一个类和一个或两个方法的 Python 代码,用 Cython 编译它并检查生成的 C 代码怎么样?