[Python-3000] callable()

Andrew Koenig ark-mlist at att.net
Tue Jul 25 05:19:23 CEST 2006


> 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.

I don't see why you should say that; it's certainly not my intent.  What did
I say that makes you think that that dependency exists?

> 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.

Perhaps we are using "idempotent" to mean different things.  I think of a
function f as being idempotent if f(x) == x for all x in dom(f).  If
__hash__ fails to return a value, you've made a mistake by calling it on an
object outside its domain.  But if it does return a value, I intend for it
always to return that same value on subsequent calls.

> Hash values should only be cached if they will never change.

Agreed.

> Furthermore, hash values are formally required to be consistant
> (not change). The "value" of the component may never change but|
> it's __hash__ may.

I should certainly hope not.

> 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.

If you think my examples make that possible, then I've stated them poorly,
and would appreciate knowing where the error lies.  That was not my intent.

> 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.

I don't know why you think that __call__ and __iter__ are the only similar
properties that any object might ever have.

> 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.

It's OK with me, but I still think it strikes me as strange, because it
makes a commitment about the implementation that I think would be better
concealed behind an abstraction layer.

I freely admit that I'm not as steeped in Python culture as many on this
list--which may or may not be a good thing as far as this discussion goes.
I guess I've just seen enough cases where people have exposed
implementations and then regretted it later that little alarm bells go off
in my head when I see designs such as these.  Sometimes, of course, they are
false alarms.




More information about the Python-3000 mailing list