Callable modules?

Alex Martelli aleax at aleax.it
Thu Jul 25 04:05:54 EDT 2002


Huaiyu Zhu wrote:

> Alex Martelli <aleax at aleax.it> wrote:
>>How is it more convenient to pass, say, object X, rather than
>>to pass bound method (e.g.) X.primary?  Take your example:
> 
> Well, here's one example:

I don't think we're really communicating.

 
>>>> class A:
> ...    def __call__(self, x): return x+self.x
> ...
>>>> a = A()
>>>> a.x = 3
>>>> a(2)
> 5
>>>> a.x = 4
>>>> a(2)
> 6

So, the role of an instance of A is "incrementer by an amount
that is runtime changeable".  OK, not common, but, does happen.

>>>> 
>>>> class B:
> ...    def call(self, x): return x+self.x
> ...
>>>> b = B()
>>>> b.x = 3
>>>> b.call(2)
> 5
>>>> b.x = 4
>>>> b.call(2)
> 6
>>>> 
> 
> If you take b as the object, you need to use explict call.  If you take

Right!  Explicit is better than implicit.  If __call__ didn't
exist, and by universal convention an instance's "primary method
if any" was named call, this would be exactly as expected.

> b.call as object, you can't do other things to the object.  Callable

Bound methods currently are not allowed to have arbitrary
rebindable attributes, while objects of other types can.  But
that's just how things stand today.  Not long ago, functions
were not allowed to have arbitrary rebindable attributes
either -- when that was added, it made a miniscule difference
to Python usage, possibilities, and convenience, simply because
the use cases are SO very rare.  If rebinding attributes of
callables on the fly was deemed important, it would be child's
play to add that to bound methods too, of course -- might be
even simpler than for functions, since there would be no need
to invent a dict for the purpose.

Do you REALLY think that having b.call.x = 23 become convenient
shorthand for b.call.im_self.x = 23 would make a DEEP difference
to Python?  I see it as trivial enough to not be worth the
bother -- not a frequent need, and all that.  

> objects
> can be viewed as parameterized functions.  Regarding whether the
> parameters can be modified later, it is similar to functions with
> attributes, but not similar to bound methods.

Ability to bind arbitrary attributes on functions is recent, and
adding the same ability to bound methods would be trivial.

If this is your real objection to the (totally abstract) case
for taking the time machine and going back to remove __call__,
I think it underscores my point: such a removal would make no
really significant difference.

Note that my case is NOT "you shouln't use __call__ today": as
Python actually works, __call__ is sometimes preferable (we do
NOT have a universal convention for how else a primary method
should be called -- that's the main point, and more significant
and harder to fix than trifles such as arbitrary attribute binding).
Rather, I claim Python would be OK if it had never had __call__,
but rather a convention about primary method name.  Ability to
bind arbitrary attributes on bound methods might have been added
at some point if, like for functions, it had been deemed useful
enough (I believe the case for functions was quite different from
the parallel you draw, and related instead to making it easier to
store _metadata_ about a function, such as, "what syntax production
is this function for", which some frameworks were using docstrings
for -- a likelier-sounding, if very marginal, use case, anyway).


"Ability to bind attributes on objects", now THAT is a thing well
worth generalizing.  Property lists in very old Lisps, and even
in clunkier systems such as Windows (almost nobody KNOWS, but the
generic-property-list API's STILL work perfectly well in Win32...),
showed up the usefulness.  The object to which you're binding
properties need know nothing about them -- they're still quite
useful as metadata to be used by other parts of the code.  Dicts
in Python partly obviate that (though you may have to index them
by id(object), and/or use weak variants, but that's mostly OK).


Alex




More information about the Python-list mailing list