[Python-3000] callable()

Andrew Koenig ark-mlist at att.net
Mon Jul 24 16:15:16 CEST 2006


> A __hash__ method with side effects is not formally prohibited in the
> documentation but nevertheless, a __hash__ which is not idempotent is
> an abomination.[1] Thus, there is no need for a test of whether __hash__
> will succeed: just try it.

> [1] I subtlely switched language from "side effect free" to "idempotent"
>      here because caching *IS* acceptable in __hash__ mehtods. If you're
>      not paying close attention I probably got away with it. Then I went
>      and spoiled it with a footnote.

I picked it up before seeing the footnote :-)

I can think of two troublesome cases; there may be others I haven't thought
of.


1) An object x with a component y that might be hashable.  x is hashable
apart from x.y, but hashing x for the first time has side effects, so the
value is cached.  The hash of x depends partly on the hash of x.y.

In other words:

	def __init__(self):
		self.hashmem = None

	def __hash__(self):
		if not self.hashmem:
			self.hashmem =
self.y.partialhash(self.partialhash())
		return self.hashmem

If we call x.__hash__, it will try to hash x.y; if that fails, x.__hash__
will raise an exception but the side effect of computing x.partialhash()
will already have happened.

In other words, even though hashing is idempotent when it succeeds, you may
still wish to avoid the side effects of trying to evaluate it if it is going
to fail.


2) An object for which computing the hash for the first time requires human
action.  For example, we might have an object that represents a CD in a CD
library.  Computing the hash for such an object might require someone to
load the CD into a drive so that it can be read.






More information about the Python-3000 mailing list