@decorator syntax is sugar, but for what exactly?

Dan Sommers me at privacy.net
Sun Aug 8 12:01:48 EDT 2004

On 8 Aug 2004 13:20:34 GMT,
Duncan Booth <duncan.booth at invalid.invalid> wrote:

> Dan Sommers <me at privacy.net> wrote in 
> news:m2u0vdj1bn.fsf at unique.fully.qualified.domain.name.yeah.right:

>> On Sun, 8 Aug 2004 18:24:58 +1000,
>> Anthony Baxter <anthonybaxter at gmail.com> wrote:
>>> In many cases, these new features actually lead to smaller, simpler
>>> code. I challenge _anyone_ to tell me that
>>> apply(func, args, kwargs) 
>>> is better than 
>>> func(*args, **kwargs)
>> Okay, I will.  The old way is better than the new way.
>> Explicit is better than implicit, after all.
>> Given your second example, is func the name of a function or an object
>> that references a function?  Can I grep my source code to find a
>> function named func?  (Okay, I'll find the variable named func, so at
>> least I'll have some clue as to what's going on.)  Is there a "from
>> module import func" statement in sight?  What happens when I look up
>> "func" in the Python documentation to see if it's a built in name?

> Why do you ask this about the second form only? func is a name that
> references a function in both cases. It doesn't matter whether that
> name was assigned directly with a def statement, or is the result of a
> subsequent binding.

Technically, that is correct.  Optimally, I can treat any application of
any function like a black box that takes some inputs and returns a value
(and possibly changes the inputs or has other (desireable) side effects,
but that's another topic entirely).  I shouldn't have to care where it
is, or who defined it, or how they defined it, or whether it's always
the same function throughout the execution of the program, as long as it
does what it's supposed to do when I invoke it.  Maybe that's my
problem.  I want to know a little more when I'm looking at code that
calls a function.

When I see f( x ), I think that f is a function bound by def (or an
extremely close relative, such as class or staticmethod), and that I can
grep for it somewhere, either in the source code or the library
reference.  I also think, rightly or wrongly, that f *was* bound,
*before* I needed it, and *does not change over time*.

When I see apply( f, x ), I think that f varies over time, and is some
sort of a callback or plugin or whatever, and is *not* the name of an
actual function bound by def.  I also accept (and expect) that a
different function may be called the next time this particular code
executes; those functions have their own names in their own contexts and

Yes, I know that all functions are free to redefine anything, but
functions that do are usually labelled pathological and then blamed for
the lack of optimizing python compilers.

ObDecorator Question:  Does some decorator that specify that a function
is not knowingly rebound within its own namespace, such that f( x ) now
means the same as f( x ) later, assuming that x is the same?  What about
at least that f is the same (and need not be looked up again), even if x
isn't?  This question lurks in the minds of every potential Python
optimizing compiler author.

If the two forms of function application are truly interchangeable, then
why do we have both of them in the first place?

>> C did the same thing recently.
>> Old C:  (*f)( argument );
>> New C:  f( argument );

[snip my reasons for not liking that bit of New C]

> For 'recently' read 1987. In fact most C compilers probably
> implemented this feature before the ISO standard came out, but it was
> a feature of the first standardised version of C. I remember around
> that time being extremely glad that I could finally omit those
> extraneous parentheses.

I must be getting old.  :-/

My Second Edition K&R confirms that you are correct on all counts except
that bit about you being happy, but I'll take your word for that <wink>.
It seems more recent than that, or it might be that I spent an awful lot
of time in environments (office/political and target system) where the
difference remained important for design, documentation, extensibility,
performance, resource usage, testing, and/or debugging purposes.


Dan Sommers
Never play leapfrog with a unicorn.

More information about the Python-list mailing list