What is a function parameter =[] for?

Steven D'Aprano steve at pearwood.info
Sat Nov 21 22:43:42 EST 2015


On Fri, 20 Nov 2015 10:59 pm, BartC wrote:

> On 20/11/2015 01:05, Steven D'Aprano wrote:

>> Here's another use for function defaults, as static storage:
[...]
>> This is a quick and easy way to memoise a function which would otherwise
>> be horribly slow. And it only works because _memo is bound to a mutable
>> object once, and once only.
> 
> We're arguing at cross-purposes then since you are obviously interested
> in these esoteric aspects, 

Memoisation isn't "esoteric", it is a simple, basic and widely-used
technique used to improve performance of otherwise expensive functions.
Quite frankly, to call it such demonstrates a considerable level of
ignorance about basic programming idioms. Not just Python, but general
purpose programming.

Instead of being so judgemental, why don't you take this as an opportunity
to open your mind to new programming styles? The purpose of learning a new
language is to open our minds to new ways of solving problems. If all we
are going to do is bitch and moan that the new language isn't exactly the
same as the old one we already know, we might as well just stick to using
the old one and not even bother learning anything new.


> but all I want to do is avoid remembering a 
> long list of defaults. Here's an example from another language, a 
> function I'm working on at the minute:
[...]
> (Here, however, the language doesn't like you doing in-place
> modification of a parameter unless the '&' is used, in which case you
> wouldn't be able to assign a default value such as () as you can only
> pass l-values.)

It sounds to me like you have implemented something like Pascal's "var"
parameters, is that right? I believe some languages (VB perhaps?) call
them "output parameters".


>> def test(arg=[]):
>>      arg.append(1)
>>      return len(arg)
>>
>>
>> The binding arg=[] is NOT inside the body of the function. Therefore, it
>> is NOT executed repeatedly, but only once.
> 
> OK, so the "=" is misleading if not a lie.

No. Why would you conclude that? If I called the function like so:

    test( [1, 2, 3, 4, 5] )

and got the result 6, would I conclude that the "=" is misleading if not a
lie? After all, the function declaration clearly shows arg being assigned
the value [], so why am I getting 6 as the result instead of 1?

The whole point of parameter default arguments is that they are bound to the
parameter *only* if the parameter otherwise isn't given a value. That's a
separate issue from *when* the default expression is evaluated. It can be
evaluated only once, or it can be evaluated every single time you call the
function. Both are legitimate techniques, both have their uses, and both
have their limitations.


>>>>> That [] doesn't look like an object that could change.
>>>>
>>>> Of course it does.
>>>
>>> You've lost me know.
> 
>> a = []
>> a.append(1)
>>
>> Are you shocked to learn that a is no longer an empty list?
> 
> No. But I would be surprised if, after this point, [] is no longer an
> empty list either!

Of course [] is an empty list. But the question isn't what [] represents, it
is what value `a` has. Since [] creates a list (not a tuple), and lists can
be modified in place, anyone familiar with Python should expect that just
because you see `a = []` somewhere doesn't mean that `a` will always be an
empty list. `a` can change.

(Of course, any variable can change if you re-assign it.)


> No, forget that; by now, I wouldn't be surprised at all!
> 
> (That [] isn't changed is probably thanks to [] being implemented with
> the BUILD_LIST byte-code, which constructs a brand-new empty list each
> time. So the next time [] is used, it will be a different one from the
> one that has just been appended to.

Right. That's not an accident either.

There isn't a single global empty list shared between all Python variables.
There *could be* (but probably isn't) a single global empty tuple, since
tuples are immutable and anything set to the empty tuple must remain the
empty tuple forever (or until re-assigned to something else), so there
would be no harm in having all such variables share the same object. But
lists don't work like that, because they are mutable.


> In my language, a construct such as [10,20,30] is evaluated just once at
> start-up.

I don't understand that explanation. How does that work? Given:

x = [10, 20, 30]
y = [10, 20, 30]


how does your language know what value y has if it doesn't evaluate the
second construct?



-- 
Steven




More information about the Python-list mailing list