添加新的python类型:TypeError:can';t设置内置/扩展类型的属性

添加新的python类型:TypeError:can';t设置内置/扩展类型的属性,python,python-c-api,python-c-extension,Python,Python C Api,Python C Extension,下面是正确编译的python-c代码 #include <Python.h> #include <structmember.h> struct rangerr { long min; long max; }; //Python type to represent rangerr struct py_rangerr { PyObject_HEAD struct rangerr range; }; // * ge

下面是正确编译的python-c代码

#include <Python.h>
#include <structmember.h>

struct rangerr {
        long    min;
        long    max;
};

//Python type to represent rangerr
struct py_rangerr {
    PyObject_HEAD
    struct rangerr range;
};
// * get & set methods for py_rangerr

static PyObject * py_rangerr_min_get(struct py_rangerr *self) {
    self->range.min  = 1;
        return PyLong_FromLong(self->range.min);
}
static PyObject * py_rangerr_min_set(struct py_rangerr *self) {
printf("Setter called");
self->range.min  = 1;
}


static PyObject * py_rangerr_max_get(struct py_rangerr *self) {
    self->range.max  = 10;
        return PyLong_FromLong(self->range.max);
}


//* GetSet method definition for py_rangerr
static PyGetSetDef py_rangerr_getset[] = {
    {"min",(getter)py_rangerr_min_get, (setter)py_rangerr_min_set, "min",NULL},
    {"max",(getter)py_rangerr_max_get, NULL, "max",NULL},

    /* Sentinel */
    {NULL},
};

/******************************************************************************
 */
static void py_rangerr_dealloc(struct py_rangerr *self) { 
        self->ob_type->tp_free((PyObject *)self);               
}

static PyTypeObject py_rangerr_type = {  
    PyObject_HEAD_INIT(NULL)    
     .tp_name       = "rangerr",        
    .tp_basicsize = sizeof(struct py_rangerr),
    .tp_dealloc   = (destructor) py_rangerr_dealloc,  
    .tp_flags     = Py_TPFLAGS_DEFAULT,                        
    .tp_alloc     = PyType_GenericAlloc,                       
    .tp_doc       = "rangerr",                                 
    .tp_getset    = py_rangerr_getset,                
};

void
initrangerr(void)
{
   PyObject* mod;

 mod = Py_InitModule3("rangerr", NULL, "An extension with a type.");
   if (mod == NULL) {
      return;
   }
  py_rangerr_type.tp_new = PyType_GenericNew;
  if (PyType_Ready(&py_rangerr_type) < 0){
      return;
   }


 Py_INCREF(&py_rangerr_type);
   PyModule_AddObject(mod, "rangerr", (PyObject*)&py_rangerr_type);

}
#包括
#包括
结构范围{
龙敏;
长最大值;
};
//表示rangerr的Python类型
结构py_rangerr{
皮尤头
结构范围;
};
//*获取和设置py_rangerr的方法
静态PyObject*py\u rangerr\u min\u get(struct py\u rangerr*self){
self->range.min=1;
从远程返回PyLong_(自->范围.min);
}
静态PyObject*py\u rangerr\u min\u集(结构py\u rangerr*self){
printf(“称为Setter”);
self->range.min=1;
}
静态PyObject*py\u rangerr\u max\u get(struct py\u rangerr*self){
self->range.max=10;
从long(self->range.max)返回PyLong_;
}
//*py_rangerr的GetSet方法定义
静态PyGetSetDef py_rangerr_getset[]={
{“min”,(getter)py_rangerr_min_get,(setter)py_rangerr_min_set,“min”,NULL},
{“max”,(getter)py_rangerr_max_get,NULL,“max”,NULL},
/*哨兵*/
{NULL},
};
/******************************************************************************
*/
静态void py_rangerr_dealloc(结构py_rangerr*self){
self->ob\u type->tp\u free((PyObject*)self);
}
静态PyTypeObject py_rangerr_type={
PyObject\u HEAD\u INIT(空)
.tp_name=“rangerr”,
.tp_basicsize=sizeof(struct py_rangerr),
.tp_dealloc=(析构函数)py_rangerr_dealloc,
.tp_flags=Py_TPFLAGS_默认值,
.tp_alloc=PyType_generalicalloc,
.tp_doc=“rangerr”,
.tp_getset=py_rangerr_getset,
};
无效的
initrangerr(无效)
{
PyObject*mod;
mod=Py_InitModule3(“rangerr”,NULL,“带有类型的扩展”);
如果(mod==NULL){
返回;
}
py_rangerr_type.tp_new=PyType_GenericNew;
if(PyType\u Ready(&py\u rangerr\u type)<0){
返回;
}
Py_增量(&Py_rangerr_类型);
PyModule_AddObject(mod,“rangerr”、(PyObject*)和py_rangerr_类型);
}
但当我尝试调用set/get方法时,它会抛出以下错误:

>>> import rangerr as r
>>> r.rangerr.min
<attribute 'min' of 'rangerr' objects>
>>> r.rangerr.min=2
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can't set attributes of built-in/extension type 'rangerr'
>>> type(r.rangerr.min)
<type 'getset_descriptor'>
>>将rangerr导入为
>>>r.rangerr.min
>>>r.rangerr.min=2
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
TypeError:无法设置内置/扩展类型“rangerr”的属性
>>>类型(r.rangerr.min)

我需要添加类似“PyMemberDef”的内容吗?谢谢你的指点和帮助

参数不能直接使用默认值。您可以向模块中添加一个函数,将全局默认值设置为静态变量

如果你只想初始化你的实例,你应该定义
PyTypeObject.tp\u init
like

static int py_rangerr_init(struct py_rangerr *self, PyObject *args, PyObject *kwds) {
    static char *kwlist[] = {"min", "max",  NULL};
    int min = 0, max = 1;

    if (!PyArg_ParseTupleAndKeywords(args, kwds, "|ii", kwlist, &min, &max))
        return -1;

    self->range.min = min;
    self->range.max = max;

    return 0;
}

static PyTypeObject py_rangerr_type = {  
    PyObject_HEAD_INIT(NULL)
    [...]
    .tp_init      = (initproc) py_rangerr_init,
};
如果您没有为
min
max
提供值,则行
int min=0,max=1中的默认值将被使用

关于
PyMemberDef
的用法,您的问题是,对于
int
这样的类型,使用
PyTypeObject.tp\u members
而不是
PyTypeObject.tp\u getset
可能会更简单、更不容易出错

此外,setter的typedef是:

typedef int (*setter)(PyObject *, PyObject *, void *);

您似乎试图更改类定义中的值,而不是实例中的值。我只是想看看(a)在定义中设置默认值并获取它,或者(b)通过实例1设置它是否有效。到目前为止,我无法让它们都工作。感谢您的回复,tynn:)今天晚些时候将尝试一下。OT:顺便问一下,你对C-Python文档/链接/书籍有什么建议吗?除了nedbatchelder.com和docs.python.org docs.Nope。只有docs.python.org。但是python源代码帮助很大。