[Python-ideas] Default arguments in Python - the return - running out of ideas but...

Steven D'Aprano steve at pearwood.info
Fri May 15 10:14:50 CEST 2009


On Fri, 15 May 2009 02:48:53 pm CTO wrote:
> [super-snip]
>
> > Just out of curiosity, what do you see as the drawbacks?
>
> [snip]
>
> 1) It adds to the complexity (and therefore overhead) of
>    calling functions- not just the functions which use it,
>    but even functions which operate as normal.

Without an implementation, how can you possibly predict the cost of it?


>    Python 
>    already has a hefty penalty for calling functions, 

I think you're badly mistaken. Python has a hefty cost for looking up 
names, but the overhead to *call* a function once you have looked up 
the name is minimal.

>>> from timeit import Timer
>>> def f():
...     pass
...
>>> min(Timer('f', 'from __main__ import f').repeat())
0.32181000709533691
>>> min(Timer('f()', 'from __main__ import f').repeat())
0.35797882080078125

No significant difference between looking up f and looking up f and 
calling it.

Even if you give the function a complex signature, it's still relatively 
lightweight:

>>> def g(a=1, b=2, c=3, d=4, e=5, f=6, g=7, h=8, *args, **kwargs):
...     pass
...
>>> min(Timer('g()', 'from __main__ import g').repeat())
0.55176901817321777


>    and 
>    I really don't want it to get any heavier. My 'solutions',
>    as incomplete as they are, at least don't slow down
>    anything else.

Oh the irony. Decorators are very heavyweight. Here's a decorator that 
essentially does nothing at all, and it triples the cost of calling the 
function:

>>> from functools import wraps
>>> def decorator(f):
...     @wraps(f)
...     def inner(*args, **kwargs):
...             return f(*args, **kwargs)
...     return inner
...
>>> @decorator
... def h():
...     pass
...
>>> min(Timer('h()', 'from __main__ import h').repeat())
1.1645870208740234

I think, before making claims as to what's costly and what isn't, you 
should actually do some timing measurements.


> 2) It adds to the complexity of introspecting functions.
>    Take a good look at inspect.getfullargspec- its a
>    nightmare, and either it gets worse under this (bad)
>    or it doesn't include information that is available
>    to the compiler (even worse).

Well obviously this is going to make getfullargspec more complicated. 
But tell me, what do you think your solution using decorators does to 
getfullargspec?


> In addition to those minuses, it doesn't actually add
> to the capabilities of the language. 

It's an incremental improvement. Currently, late-binding of defaults 
requires boilerplate code. This will eliminate that boilerplate code.


> If this were a 
> proposal to add early action to Python (the equivalent
> of metaclasses or, to some extent, macro replacement)
> I would be much more likely to support it, despite the
> heavier syntax.
>
> So, the existing idiom works pretty well, 

100% agreed!

> there doesn't seem to be a very good substitute, 

Not without support in the compiler.

> it slows the whole language down to implement, 

You can't know that.

> and it doesn't add any power if you do.

It reduces boilerplate, which is a good thing. Probably the *only* good 
thing, but still a good thing.



-- 
Steven D'Aprano



More information about the Python-ideas mailing list