因此,writing extension的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
答案 0 :(得分:2)
编写C扩展是一个复杂的过程,因为您必须编写C代码,并且必须向Python提供足够的信息,以便它可以像处理Python数据那样操作C数据。你必须两次提到结构的成员:一次是让C编译器知道如何制作结构,然后再一次让Python知道数据的位置,以及它的名称。
C没有内省能力,所以你不能(例如)在运行时获取结构的成员列表。 PyMemberDef数组提供了这些信息。
答案 1 :(得分:1)
好的所以我做了我的研究,是的实例变量和属性是不同的,因为类实例和类有单独的字典。如documentation ::
中所述通过调用创建类实例 一个类对象(见上文)。一类 instance实现了一个名称空间 作为第一个字典 属性引用的位置 被搜查。当属性不是 发现那里,以及实例的类 有一个该名称的属性, 继续搜索课程 属性。
所以基本上Noddy结构包含实例变量。 Noddy_members拥有属性。此外:
属性分配和删除 更新实例的字典, 从来没有班级的字典。如果 class有 setattr ()或 delattr ()方法,调用此方法而不是更新实例 字典直接。
此外:
如果找到的是class属性 用户定义的函数对象或 未绑定的用户定义方法对象 其关联的类是类 (称之为C)的实例 属性引用已启动 或其中一个基地,它被改造 到用户定义的绑定方法 im_class属性为C的对象 并且其im_self属性是 实例。静态方法和类 方法对象也被转换, 好像他们是从那里取回来的 C级;见上文“课程”。 请参阅实现描述符部分 另一种方式,其中的属性 通过其实例检索的类 可能与实际的对象不同 存储在班级的 dict 中。如果不 找到class属性,然后 object的类有一个 getattr () 方法,被称为满足 查找。