What is a function parameter =[] for?

BartC bc at freeuk.com
Wed Nov 18 20:41:47 EST 2015


On 18/11/2015 23:22, Chris Angelico wrote:
> On Thu, Nov 19, 2015 at 10:14 AM, BartC <bc at freeuk.com> wrote:
>> On 18/11/2015 22:11, Ian Kelly wrote:
>>>
>>> On Wed, Nov 18, 2015 at 2:08 PM, fl <rxjwg98 at gmail.com> wrote:
>>>>
>>>> Hi,
>>>>
>>>> I have tried the below function and find that it can remember the
>>>> previous
>>>> setting value to 'val'. I think the second parameter has something on
>>>> this
>>>> effect, but I don't know the name and function of '=[]' in this
>>>> application.
>>>>
>>>> Could you explain a little to me?
>>>> Thanks,
>>>>
>>>>
>>>> def eList(val, list0=[]):
>>>>       list0.append(val)
>>>>       return list0
>>>> list1 = eList(12)
>>>> list1 = eList('a')
>>>
>>>
>>> The list0 parameter has a default value, which is [], an initially
>>> empty list. The default value is evaluated when the function is
>>> defined, not when it is called, so the same list object is used each
>>> time and changes to the list are consequently retained between calls.
>>
>>
>> That is really bizarre behaviour.
>>
>> So, looking at some source code, a default value for certain types is only
>> certain to be that value for the very first call of that function?
>
> On the contrary, it is certain always to be that exact object.

But, not the same value that appears as the default?

  >>> The default value is evaluated when the function is
>>> defined, not when it is called
>>
>> Given the amount of pointless dynamic stuff that goes on in Python, I'm
>> surprised they've overlooked this one!
>>
>> It seems simple enough to me to check for a missing parameter, and to assign
>> whatever default value was designated ([] in this case). (How does the
>> default mechanism work now?)
>
> It's exactly the way Ian described it. Functions are defined, not
> declared - it's an executable statement. When the 'def' statement is
> reached, the expressions in the argument defaults get evaluated, and
> the results get saved into the function's attributes:
....

Sorry, I didn't understand any of that. Let's try a simpler example like 
the OP's. There's this innocuous looking function that you are 
interested in calling:

  def fn(a=[]):
  #   print ("Function fn called with",a)
  |   a.append(10)
  |   return a

It appends a value to its argument and returns the result.

It looks like at first like, if called with no argument, it will return 
[10].

But what it actually returns depends on the entire call history since 
the program started executing, something you probably have no knowledge 
of and no control over. So if fn has previously been called a million 
times with no argument, then after this call:

  x=fn()

x contains a list of a million tens, not one. I'd say most people would 
be rather surprised by that.

I suspect those same people (unless they are experts in the murky 
corners of the language) would expect:

   x=fn()

when fn specifies a default argument of [], to be the same as writing:

   x=fn([])

and not be dependent on fn's entire call history.

Your solution of using:

   def fn(a=None):

is not really satisfactory. Partly because it now utilities two 
mechanisms for the default: first to get None, then some extra code to 
get []. But also it's no longer obvious how the function works and what 
the default is. At least, you can't tell from a glance at the start of 
the function that [] is the default.

-- 
Bartc





More information about the Python-list mailing list