1

因此,用于编写扩展的 python 文档是这样说的:

“我们希望将我们的实例变量作为属性公开。有很多方法可以做到这一点。最简单的方法是定义成员定义:

static PyMemberDef Noddy_members[] = {
    {"first", T_OBJECT_EX, offsetof(Noddy, first), 0,
     "first name"},
    {"last", T_OBJECT_EX, offsetof(Noddy, last), 0,
     "last name"},
    {"number", T_INT, offsetof(Noddy, number), 0,
     "noddy number"},
    {NULL}  /* Sentinel */
};

并将定义放在 tp_members 槽中:

Noddy_members,             /* tp_members */"

但是,我们已经将实例变量放入了 Noddy 结构体中:

 typedef struct {
    PyObject_HEAD
    PyObject *first;
    PyObject *last;
    int number;
} Noddy;

所以我的问题是为什么我们把它们放在这两个地方。我的印象是,这是因为我们希望类型和实例都拥有它们,以便在实例更新后保留类型值。但是如果是这样的话,如果我们改变类属性,实例值是如何更新的呢?像这样:

>>> class foo(object): x = 4
...
>>> f = foo()
>>> f.x
4
>>> foo.x = 5
>>> f.x
5
4

2 回答 2

3

编写 C 扩展是一个复杂的过程,因为您必须编写 C 代码,并且您必须向 Python 提供足够的信息,以便它可以像处理 Python 数据一样操作您的 C 数据。您必须两次提及结构的成员:一次让 C 编译器知道如何制作结构,然后再次让 Python 知道数据在哪里,以及它被称为什么。

C 没有自省能力,因此您不能(例如)在运行时获取结构的成员列表。PyMemberDef 的数组提供了该信息。

于 2011-06-30T19:43:03.313 回答
1

好的,所以我做了我的研究,是的,实例变量和属性是不同的,那是因为类实例和类有单独的字典。如文档中所述::

类实例是通过调用类对象创建的(见上文)。类实例具有作为字典实现的命名空间,这是搜索属性引用的第一个位置。如果在那里找不到属性,并且实例的类具有该名称的属性,则使用类属性继续搜索。

所以基本上 Noddy 结构包含实例变量。Noddy_members 持有属性。此外:

属性分配和删除会更新实例的字典,而不是类的字典。如果类有setattr () 或 delattr () 方法,则调用此方法而不是直接更新实例字典。

还:

如果发现类属性是用户定义的函数对象或未绑定的用户定义的方法对象,其关联类是为其启动属性引用的实例的类(称为 C)或其基之一,它转化为im_class属性为C,im_self属性为实例的绑定用户自定义方法对象。静态方法和类方法对象也被转换,就好像它们是从类 C 中检索的一样;见上文“类”。有关通过其实例检索的类的属性可能与实际存储在类的dict中的对象不同的另一种方式,请参见实现描述符一节。如果没有找到类属性,并且对象的类有getattr() 方法,即调用以满足查找。

于 2011-07-06T21:21:33.620 回答