Python Macros

Alex Martelli aleaxit at yahoo.com
Wed Oct 6 07:28:22 EDT 2004


gabriele renzi <rff_rff at remove-yahoo.it> wrote:
   ...
> > Please explain how this syntax choice "discriminates" anything
> > whatsoever?  __getattr__ is called when some message isn't understood by
> > the "normal" mechanisms of the object, too.
> 
> I actually meant __getattribute__ sorry.

Python lets you have either, sure.  But the very existence of
__getattr__ (WAY more used and useful of __getattribute__) appears to
deny your point.


> The point is that when you write
> x.foo(y)
> in py you're looking up foo, then calling it with y.
> Actually you can even store x.foo away and call it later
> f=x.foo
> 
> in ST you can't cause you're not doing a dict lookup when you write
> x foo: y
> 
> obviously you could send another message asking for x to give you a 
> method foo: object

Exactly because of this 'obviously' part, I claim there is no deep
difference whatsoever.  Currently, Python factors every fetch-and-call
operation into separate fetching and calling sub-operations, while a
typical Smalltalk implementation optimizes the common case of
fetch-and-call wrt the rarer case where you only want to fetch for now,
store the method object somewhere, and call it later.  This is an
implementation detail, actually an _optimization_ detail.

Say that Python 2.5 introduced an optional __getattr_and_call__ special
method and one related bytecode.  Where now a call c.z() compiles to
    LOAD_FAST c
    LOAD_ATTR z
    CALL_FUNCTION 0
it would then compile into
    LOAD_FAST c
    CALL_ATTR z, 0

If c's class did define __getattr_and_call__, the latter would boil down
to type(c).__getattr_and_call__(c, 'z'); otherwise, it would instead
boil down to (like today) the equivalent of:
    _temp = getattr(c, 'z')
    _temp.__call__()
(for some hypothetical _temp which actually -- yet another irrelevant
implementation detail -- only lives on Python's runtime stack).

Observable differences?  Essentially nil -- hopefully some potential to
be faster (otherwise it would hardly be worth the bother), but
semantically intended to have identical effects.  Similarly for other
possible implementation choices for CALL_ATTR (adding a __get_and_call__
method to descriptors, to be used, if present, instead of just __get__
in such cases, for example).

A language completely unable to get a first-class "bound method" object
WOULD be substantially impoverished, sure.  But as long as you can get
that kind of object, then whether you use that "getting" as the only
mechanism for calling, or introduce some "rolled-up" mechanism to
(hopefully) optimize common use cases, is a mere implementation detail
-- simplicity on one side, perhaps a tad more speed on the other.

> Not that one is better than other just a subtle difference.

An _implementation_ difference, and in fact a pretty minor detail too,
not any real _language_ difference.


Alex



More information about the Python-list mailing list