[Python-3000] callable()

Michael Chermside mcherm at mcherm.com
Tue Jul 25 00:27:28 CEST 2006


Earlier in the thread:
> two troublesome cases:
        [...]
> 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.
        [...]

> 2) An object for which computing the hash for the first time requires human
> action.


Andrew Koenig writes:
> > In both cases, __hash__ is not idempotent, and is thus an abomination.
>
> Why do you say it's not idempotent?  The first time you call it, either it
> works or it doesn't.  If it doesn't work, then you shouldn't have called it
> in the first place.  If it does work, all subsequent calls will return the
> same result.

Which case are you considering? In case 1, __hash__ of the parent object
is not idempotent because it depends on whether __hash__ of the child
object has a cached value or not. In case 2, __hash__ either returns
a value or raises an exception (or perhaps blocks forever if poorly
written) depending on the behavior of the human being. Neither is
idempotent.

Andrew some more:
> What is perverse about case 1?  I'm not being disingenuous here; I really
> don't know.  I am assuming, of course, that the object in question never
> changes the value of its component once constructed.

Hash values should only be cached if they will never change. Furthermore,
hash values are formally required to be consistant (not change). The
"value" of the component may never change but it's __hash__ may. Consider
the following series of calls:
      x1 = hash(x)
      y1 = hash(y)
      x2 = hash(x)
      y2 = hash(y)
After this series of calls, x1 != x2 and y1 != y2. That breaks the contract
for __hash__ which I would call perverse.

Andrew concludes:
> ...the original point, which is that it is entirely plausible for  
> objects to have properties
> that trigger side effects when used, and for which it may be useful to have
> a way of asking about their presence without triggering the side effects.

I don't doubt that some properties like the behavior of __call__ or
__iter__ may trigger side effects, and it would nice  to be able to test
for the property without triggering the side effects. Your argument is
bolstered if you add __hash__ to the list because hashability is something
that *must* be tested for (by dict at least!). But I object... __hash__
cannot trigger side effects (well, it must be idempotent anyhow) thus you
are limited to __call__ and __iter__ as examples, of which the best we
can say is that it would *nice* to be able to test for them.

This is all moot anyway, because I think everyone agrees to make
hasattr(x, '__call__') and hasattr(x, '__iter__') be the tests and to
ensure in Python3000 that (unlike older CPythons) those work for all
objects.

But-moot-means-debatable-so-I-guess-that's-what-we're-doing-lly, yours

Michael Chermside



More information about the Python-3000 mailing list