[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