使用Python C-API定义内部类
在Python中,定义内部类非常简单:使用Python C-API定义内部类,python,python-c-api,setattribute,setattr,pyobject,Python,Python C Api,Setattribute,Setattr,Pyobject,在Python中,定义内部类非常简单: 类MyClass(对象): 类MyInnerClass(对象): 通过 …可以按预期访问内部类,例如通过执行MyClass.MyInnerClass 我正在尝试设置类似的扩展模块。通常,在modules'init()函数中将定义的扩展类型添加到扩展模块对象中,代码如下: //… if(PyType_Ready(&BufferModel_Type)
类MyClass(对象):
类MyInnerClass(对象):
通过
…可以按预期访问内部类,例如通过执行MyClass.MyInnerClass
我正在尝试设置类似的扩展模块。通常,在modules'init()
函数中将定义的扩展类型添加到扩展模块对象中,代码如下:
//…
if(PyType_Ready(&BufferModel_Type)<0){return;}
///将BufferModel类型对象添加到模块
Py_增量(&BufferModel_类型);
PyModule_AddObject(模块,
“缓冲区”,
(PyObject*)和BufferModel_类型);
/// …
为了设置内部类,我改变了这种方法,尝试添加一个PyTypeObject*
作为另一个PyTypeObject*
的属性,如下所示:
//…
if(PyType_Ready(&ImageBufferModel_Type)<0){return;}
if(PyType_Ready(&ImageModel_Type)<0){return;}
///将ImageBufferModel类型对象添加到im.Image
Py_增量(&ImageBufferModel_类型);
PyObject_SetAttrString((PyObject*)和ImageModel_类型,
“图像缓冲区”,
(PyObject*)和ImageBufferModel_类型);
PyType_-Modified((PyTypeObject*)和ImageModel_-Type);
///将ImageModel类型对象添加到模块
Py_增量(&ImageModel_类型);
PyModule_AddObject(模块,
“图像”,
(PyObject*)和ImageModel_类型);
/// …
…我想,PyObject\u SetAttrString()
将按照
类型对象可以使用PyObject_*()
或
PyType_*()
函数[…]
…我根据添加了调用PyType\u Modified()
。但是,当我编译所有内容并尝试加载扩展时,会出现以下错误:
>>> import im
Traceback (most recent call last):
File "<input>", line 1, in <module>
import im
File "im/__init__.py", line 2, in <module>
from im import (
TypeError: can't set attributes of built-in/extension type 'im.Image'
导入im
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
导入即时消息
文件“im/\uuuu init\uuuuu.py”,第2行,在
从im导入(
TypeError:无法设置内置/扩展类型“im.Image”的属性
…我想我是走错了路;我应该试试什么?为此,您需要直接使用:
在调用PyType\u Ready
之前,此字段通常应初始化为NULL;也可以将其初始化为包含该类型初始属性的字典。一旦PyType\u Ready()
已初始化该类型,只有当该类型的额外属性与重载操作(如\uuuuu add\uuu()
)不对应时,才能将其添加到此字典中
您不必使用PyObject\u SetAttrString()
只需
PyDict_SetItemString(ImageModel_Type.tp_dict, "ImageBuffer", (PyObject*) &ImageModel_Type);
但在这种情况下,文件中的警告适用:
在字典C-API上使用PyDict_SetItem()
或以其他方式修改tp_dict
是不安全的
因此,在调用ImageModel\u Type
上的PyType\u Ready
之前,可以初始化tp\u dict
:
///使用空字典初始化tp\u dict
ImageModel_Type.tp_dict=PyDict_New();
如果(!ImageModel_Type.tp_dict){return;}
///将ImageBufferModel类型对象添加到im.Image
if(PyType_Ready(&ImageBufferModel_Type)<0){return;}
Py_增量(&ImageBufferModel_类型);
PyDict_SetItemString(ImageModel_Type.tp_dict,
“图像缓冲区”,
(PyObject*)和ImageBufferModel_类型);
///将ImageModel类型对象添加到模块
if(PyType_Ready(&ImageModel_Type)<0){return;}
Py_增量(&ImageModel_类型);
PyModule_AddObject(模块,
“图像”,
(PyObject*)和ImageModel_类型);
为此,您需要直接使用:
在调用PyType\u Ready
之前,此字段通常应初始化为NULL;也可以将其初始化为包含该类型初始属性的字典。一旦PyType\u Ready()
已初始化该类型,只有当该类型的额外属性与重载操作(如\uuuuu add\uuu()
)不对应时,才能将其添加到此字典中
您不必使用PyObject\u SetAttrString()
只需
PyDict_SetItemString(ImageModel_Type.tp_dict, "ImageBuffer", (PyObject*) &ImageModel_Type);
但在这种情况下,文件中的警告适用:
在字典C-API上使用PyDict_SetItem()
或以其他方式修改tp_dict
是不安全的
因此,在调用ImageModel\u Type
上的PyType\u Ready
之前,可以初始化tp\u dict
:
///使用空字典初始化tp\u dict
ImageModel_Type.tp_dict=PyDict_New();
如果(!ImageModel_Type.tp_dict){return;}
///将ImageBufferModel类型对象添加到im.Image
if(PyType_Ready(&ImageBufferModel_Type)<0){return;}
Py_增量(&ImageBufferModel_类型);
PyDict_SetItemString(ImageModel_Type.tp_dict,
“图像缓冲区”,
(PyObject*)和ImageBufferModel_类型);
///将ImageModel类型对象添加到模块
if(PyType_Ready(&ImageModel_Type)<0){return;}
Py_增量(&ImageModel_类型);
PyModule_AddObject(模块,
“图像”,
(PyObject*)和ImageModel_类型);
Wow,谢谢!类型对象文档有时会让人困惑,我很欣赏这个直接的答案,这完全有效。我还应该补充一点,在Python方面,对PyTypeObject的tp_dict
数据成员进行更改可以实现许多通常使用元类实现的相同目的(例如,合成基于类的描述符ála Django的ORM等).Wow,谢谢!类型对象文档有时会让人困惑,我很欣赏这个直接的答案,这完全有效。我还应该补充一点,在Python方面,对PyTypeObject的tp_dict
数据成员进行更改可以实现许多通常使用元类实现的相同目的(例如,合成基于类的描述符ála Django的ORM等)。