[Python-Dev] == on object tests identity in 3.x

Steven D'Aprano steve at pearwood.info
Tue Jul 8 05:12:02 CEST 2014


On Tue, Jul 08, 2014 at 02:59:30AM +0100, Rob Cliffe wrote:

> >- "*Every object has an identity, a type and a value.*"
>
> Hm, is that *really* true?

Yes. It's pretty much true by definition: objects are *defined* to have 
an identity, type and value, even if that value is abstract rather than 
concrete.


> Every object has an identity and a type, sure.
> Every *variable* has a value, which is an object (an instance of some 
> class).  (I think? :-) )

I don't think so. Variables can be undefined, which means they don't 
have a value:

py> del x
py> print x
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'x' is not defined


> But ISTM that the notion of the value of an *object* exists more in our 
> minds than in Python.

Pretty much. How could it be otherwise? Human beings define the 
semantics of objects, that is, their value, not Python.


[...]
> If I came across an int object and had no concept of what an integer 
> number was, how would I know what its "value" is supposed to be?

You couldn't, any more than you would know what the value of a Watzit 
object was if you knew nothing about Watzits. The value of an object is 
intimitely tied to its semantics, what the object represents and what it 
is intended to be used for. In general, we can say nothing about the 
value of an object until we've read the documentation for the object.

But we can be confident that the object has *some* value, otherwise what 
would be the point of it? In some cases, that value might be nothing 
more than it's identity, but that's okay.

I think the problem we're having here is that some people are looking 
for a concrete definition of what the value of an object is, but there 
isn't one.


[...]
> And can the following *objects* (class instances) be said to have a 
> (obvious) value?
>     obj1 = object()
>     def obj2(): pass
>     obj3 = (x for x in range(3))
>     obj4 = xrange(4)

The value as understood by a human reader, as opposed to the value as 
assumed by Python, is not necessarily the same. As far as Python is 
concerned, the value of all four objects is the object itself, i.e. its 
identity. (For avoidance of doubt, not its id(), which is just a 
number.) 

A human reader could infer more than Python:

- the second object is a "do nothing" function;
- the third object is a lazy sequence (0, 1, 2);
- the fourth object is a lazy sequence (0, 1, 2, 3);

but since the class designer didn't deem it important enough, or 
practical enough, to implement an __eq__ method that takes those things 
into account, *for the purposes of equality* (but perhaps not other 
purposes) we say that the value is just the object itself, its identity.



> And is there any sensible way of comparing two such similar objects, e.g.
>     obj3  = (x for x in range(3))
>     obj3a = (x for x in range(3))
> except by id?

In principle, one might peer into the two generators and note that they 
perform exactly the same computations on exactly the same input, and 
therefore should be deemed to have the same value. But since that's 
hard, and "exactly the same" is not always well-defined, Python doesn't 
try to be too clever and just uses a simpler idea: the value is the 
object itself.


> Well, possibly in some cases.  You might define two functions as equal 
> if their code objects are identical (I'm outside my competence here, so 
> please no-one correct me if I've got the technical detail wrong).  But I 
> don't see how you can compare two generators (other than by id) except 
> by calling them both destructively (possibly an infinite number of 
> times, and hoping that neither has unpredictable behaviour, side 
> effects, etc.).

Generator objects have code objects as well.

py> x = (a for a in (1, 2))
py> x.gi_code
<code object <genexpr> at 0xb7ee39f8, file "<stdin>", line 1>

> >- "An object's /identity/ never changes once it has been created; .... 
> >The /value/ of some objects can change. Objects whose value can change 
> >are said to be /mutable/; objects whose value is unchangeable once 
> >they are created are called /immutable/."
>
> ISTM it needs to be explicitly documented for each class what the 
> "value" of an instance is intended to be.

Why? What value (pun intended) is there in adding an explicit statement 
of value to every single class?

"The value of a str is the str's sequence of characters."
"The value of a list is the list's sequence of items."
"The value of an int is the int's numeric value."
"The value of a float is the float's numeric value, or in the case of 
 INFs and NANs, that they are an INF or NAN."
"The value of a complex number is the ordered pair of its real and 
 imaginary components."
"The value of a re MatchObject is the MatchObject itself."

I don't see any benefit to forcing all classes to explicitly document 
this sort of thing. It's nearly always redundant and unnecessary.



-- 
Steven


More information about the Python-Dev mailing list