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
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.