Default parameters

Bengt Richter bokr at oz.net
Fri Dec 19 21:31:04 EST 2003


On Sat, 20 Dec 2003 01:43:00 GMT, Carl Banks <imbosol at aerojockey.invalid> wrote:

>Paul Rubin wrote:
>> 
>> 
>> Carl Banks <imbosol at aerojockey.invalid> writes:
>>> Consider something like this:
>>> 
>>>     def func(param=((1,2),(3,4),(5,6),(7,8))):
>>>         whatever
>>> 
>>> Do you really want to be building a big-ass nested tuple every time
>>> the function is called?
>> 
>> Come on, the compiler can easily recognize that that list is constant.
>
>Yes, but that doesn't account for all expensive parameters.  What
>about this:
>
>    DEFAULT_LIST = ((1,2),(3,4),(5,6),(7,8))
>
>    def func(param=DEFAULT_LIST):
>        pass
>
>Or this:
>
>    import external_module
>
>    def func(param=external_modules.create_constant_object()):
>        pass
>
>Or how about this:
>
>    def func(param={'1': 'A', '2': 'B', '3': 'C', '4': 'D'}):
>        pass
>
>
>The compiler couldn't optimize any of the above cases.
For the DEFAULT_LIST (tuple?) and that particular dict literal, why not?

>
>
>>> Python evaluates default args at time of definition mostly for
>>> performance reasons (and maybe so we could simulate closures before we
>>> had real closures).  My gut feeling is, moving the evaluation to call
>>> time would be too much of a performance hit to justify it.
>> 
>> Python takes so many other performance hits for the sake of
>> convenience and/or clarity that this particular one would be miniscule
>> by comparison.
>
>
>Well, I don't have any data, but my gut feeling is this would be
>somewhat more than "miniscule" performance hit.  Seeing how pervasive
>default arguments are, I'm guessing it would be a very significant
>slowdown if default arguments had to be evaluated every call.
>
>But since I have no numbers, I won't say anything more about it.
>
Don't know if I got this right, but

[18:32] /d/Python23/Lib>egrep -c 'def .*=' *py |cut -d: -f 2|sum
Total = 816
[18:32] /d/Python23/Lib>egrep -c 'def ' *py |cut -d: -f 2|sum
Total = 4454

would seem to suggest pervasive ~ 816/4453
or a little less than 20%

Of course that says nothing about which are typically called in hot loops ;-)
But I think it's a bad idea as a default way of operating anyway. You can
always program call-time evaluations explicitly. Maybe som syntactic sugar
could be arranged, but I think I would rather have some sugar for the opposite
instead -- i.e., being able to code a block of preset locals evaluated and bound
locally like current parameter defaults, but not being part of the call signature.

Regards,
Bengt Richter




More information about the Python-list mailing list