On 2013-09-16, Nils Bruin <nbr...@sfu.ca
> If we change the first line to base=SageObject, we get an attribute error,
> which can be traced back to the definition of __hash__ (defined on
> SageObject) trying to call __repr__ . Thus, we can say that SageObject
> breaks pickling on circular structures, in that things that work perfectly
> fine when inheriting from "object", break when we use SageObject instead.
I am of course not the person who created SageObject. But I think I can
see the rationale for how its hash is implemented: In Python's <object>,
the default is that comparison is by identity, and hence the hash is
obtained from the object's address in memory, id(). In Sage, we are more
likely in a situation where non-identical objects evaluate equal. Hence,
if we want a default hash at all, then it should take this into account.
And it is a good guess that two Sage objects evaluate equal only if their
string representations are equal (but not "if and only if").
Some problems, though: The string representation is not always available
when we need the hash. Computing the string representation is quite
expensive, and hence the default hash is very slow; but at least it is
cached now, as of version Sage-5.12.beta5. And, worst: The string
representation can be customized after object creation, and so the hash
value depends on whether the hash was first called before or after
sage: class MyParent(Parent): pass
sage: P1, P2, P3 = MyParent(), MyParent(), MyParent()
Hence, the hash of P2 and P3 are different, simply since the hash of P2
has been computed before the name was reset.
I have no recommendation what we should do.