python中实例变量和属性之间的区别?

发布于 2024-11-18 05:10:50 字数 961 浏览 3 评论 0原文

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

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

静态 PyMemberDef Noddy_members[] = {
    {“第一个”,T_OBJECT_EX,offsetof(诺迪,第一个),0,
     “名”},
    {“最后”,T_OBJECT_EX,offsetof(诺迪,最后),0,
     “姓”},
    {“数字”,T_INT,offsetof(诺迪,数字),0,
     “诺迪号码”},
    {NULL} /* 哨兵 */
};

并将定义放入 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

So, the python docs for writing extension says this:

"We want to expose our instance
variables as attributes. There are a
number of ways to do that. The
simplest way is to define member
definitions:

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 */
};

and put the definitions in the
tp_members slot:

Noddy_members,             /* tp_members */"

However, we have already put the instance variables in the Noddy struct:

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

so my question is that why we put them in both places. My impression is that, that is because we want both type and the instance to have them so that we preserve the types values once the instance get updated. But If thats the case, how does the instance value get updated if we change the class attribute? like this:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

岁月苍老的讽刺 2024-11-25 05:10:50

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

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

Writing a C extension is a complex process, because you have to write C code, and you have to provide enough information to Python so that it can manipulate your C data as if it were Python data. You have to mention the members of the struct twice: once for the C compiler to know how to make the struct, and then again so that Python knows where the data is, and what it is called.

C has no introspection ability, so you can't (for example), get a list of members of a struct at runtime. The array of PyMemberDef provides that information.

浪漫人生路 2024-11-25 05:10:50

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

通过调用创建类实例
类对象(见上文)。 A类
实例已实现命名空间
作为第一个字典
属性引用的地方
被搜查。当属性不存在时
在那里找到的,以及实例的类
有一个同名的属性,
搜索继续在课堂上进行
属性。

所以基本上 Noddy 结构保存实例变量。 Noddy_members 保存属性。此外:

属性分配和删除
更新实例的字典,
从来没有班级词典。如果
类有一个 setattr() 或
delattr() 方法,调用此方法而不是更新实例
直接字典。

还:

如果发现类属性是
用户定义的函数对象或
未绑定的用户定义方法对象
其关联类是该类
(称之为C)的实例
属性引用已启动
或其基地之一,它被改造
进入绑定的用户定义方法
im_class 属性为 C 的对象
其 im_self 属性是
实例。静态方法和类
方法对象也被转换,
就好像它们是从
C级;请参阅上文“类别”下的内容。
请参阅“实现描述符”部分
的属性的另一种方式
通过实例检索的类
可能与实际物体有所不同
存储在类的dict中。如果没有
找到类属性,并且
对象的类有一个getattr()
方法,被调用以满足
查找。

Ok So I did my research and yes instance variables and attributes are different and thats because classes instances and classes have separate dictionaries. As said in the documentation::

A class instance is created by calling
a class object (see above). A class
instance has a namespace implemented
as a dictionary which is the first
place in which attribute references
are searched. When an attribute is not
found there, and the instance’s class
has an attribute by that name, the
search continues with the class
attributes.

So basically the Noddy struct holds the instance variables. The Noddy_members holds the attributes. Furthermore:

Attribute assignments and deletions
update the instance’s dictionary,
never a class’s dictionary. If the
class has a setattr() or
delattr() method, this is called instead of updating the instance
dictionary directly.

Also:

If a class attribute is found that is
a user-defined function object or an
unbound user-defined method object
whose associated class is the class
(call it C) of the instance for which
the attribute reference was initiated
or one of its bases, it is transformed
into a bound user-defined method
object whose im_class attribute is C
and whose im_self attribute is the
instance. Static method and class
method objects are also transformed,
as if they had been retrieved from
class C; see above under “Classes”.
See section Implementing Descriptors
for another way in which attributes of
a class retrieved via its instances
may differ from the objects actually
stored in the class’s dict. If no
class attribute is found, and the
object’s class has a getattr()
method, that is called to satisfy the
lookup.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文