What is a function parameter =[] for?

Chris Angelico rosuav at gmail.com
Wed Nov 18 18:22:04 EST 2015


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.

>> 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:

>>> def demo(factory):
...     def func(x=factory()):
...         x.append("Hello!")
...         return x
...     return func
...
>>> def make_list():
...     print("I'm making a list!")
...     return []
...
>>> f1 = demo(make_list)
I'm making a list!
>>> f2 = demo(make_list)
I'm making a list!
>>> f3 = demo(make_list)
I'm making a list!
>>> f1()
['Hello!']
>>> f1()
['Hello!', 'Hello!']
>>> f1()
['Hello!', 'Hello!', 'Hello!']
>>> f2()
['Hello!']
>>> f2()
['Hello!', 'Hello!']
>>> f3()
['Hello!']
>>> f1.__defaults__
(['Hello!', 'Hello!', 'Hello!'],)
>>> id(f1())
140470001247688
>>> id(f1())
140470001247688
>>> id(f1())
140470001247688
>>> id(f1())
140470001247688
>>> id(f1())
140470001247688
>>> id(f1.__defaults__[0])
140470001247688

If you want the expression (eg the empty list display) to be evaluated
every time the body of the function is executed, you put it into the
body of the function. There is no magic here.

ChrisA



More information about the Python-list mailing list