Is it possible to give a formal definition of the term "value of an object" in CPython? After briefly reading some reference articles and Python tutorials, I came to the conclusion that in most cases this term means one of the following two things (depending on the context). Is this conclusion correct or not?
In a broad sense, "value of an object" means all the data stored in the object's struct (this struct is derived from the PyObject struct), excluding the type designator and reference counter. In other words, it is data (collection of bytes) stored in object's struct fields, excluding ob_type
and ob_refcnt
fields (and maybe some other bookkeeping fields related to garbage collection). It seems that Python object's instance variables are also stored in this struct. However, I am not sure about bound methods – where they are stored after creation.
For example, every object of type int
is generated by the following struct (after expanding C macros):
struct _longobject {
Py_ssize_t ob_refcnt; /* object reference counter */
PyTypeObject* ob_type; /* object type designator*/
Py_ssize_t ob_size;
digit ob_digit[1];
};
Hence, its value is the data (collection of bytes) stored in ob_size
and ob_digit[1]
.
In a narrow sense, "value of an object" means the string representation of the object that is evaluated by either obj.__repr__()
or obj.__str__()
. This representation isn't usually stored explicitly in the PyObject struct, but is evaluated by the above-mentioned bound methods, which use several fields of the PyObject struct during this evaluation. Note that for objects of some types (for example, function objects or file objects) this string representation is trivial and doesn't contain any valuable information.
The official Python reference has no definition of the value of an object. It just says that
Every object has an identity, a type, and a value.
The Python glossary doesn't have such a definition either (although the term "value" appears in it 34 times). Moreover, it is not really clear how we should interpret the term "value" in its definition of object:
Object - any data with state (attributes or value) and defined behavior (methods).
This definition contrasts "value" with "attributes". Maybe we should interpret "value" here in the narrow sense as I defined it above, but I am not sure.
The answer below is a good explanation of the concept of "value" in Python. Now, I think the definition written in my first bullet can be called the definition of "memory representation of a value of an object" (synonym: "byte representation of a value of an object"). This representation is not unique because it is machine-dependent. And the definition written in my second bullet should be called the definition of "string representation of an object" (synonym: "string representation of a value of an object").
Neither of those proposed definitions are appropriate. There is no formal definition of an object's value. It's more of an informal, intuitive concept.
The closest thing to a definition of an object's value I would be comfortable with is "the information an object represents". For example, the information represented by an int object 5
is the number 5. The sets {-1, -2}
and {-2, -1}
represent the same information, and have the same value. This is true even though the contents of the memory corresponding to these objects doesn't match, and even though they have different string representations.
The data model docs for comparison operators say
The value of an object is a rather abstract notion in Python: For example, there is no canonical access method for an object’s value. Also, there is no requirement that the value of an object should be constructed in a particular way, e.g. comprised of all its data attributes. Comparison operators implement a particular notion of what the value of an object is. One can think of them as defining the value of an object indirectly, by means of their comparison implementation.
so that's one notion of value - objects that compare equal according to ==
have the same value under this notion of value. But then there are objects that have unusual comparison implementations. float('nan')
compares unequal to itself, so what's its value? And {1: 1, 2: 2}
and {2: 2, 1: 1}
compare equal to each other, but they contain different order information. Should order be considered part of a dict's value?
Ultimately, the dev team just doesn't bother trying to write an official, formal definition of "value", or trying to force the concept of "value" into being something rigid enough to define. Doing so doesn't solve practical problems.