7

I just started learning python, just got struck by the default argument concept.

It is mentioned in python doc that the default argument value of a function is computed only once when the def statement is encountered. This makes a large difference between values of immutable and mutable default function arguments.

>>> def func(a,L=[]):
      L.append(a)
      return L
>>> print(func(1))
[1]
>>> print(func(2))
[1, 2]

here the mutable function argument L retains the last assigned value (since the default value is calculated not during function call as like in C)

is the lifetime of the default argument's value in python is lifetime of the program (like static variables in C) ?

Edit :

>>> Lt = ['a','b']
>>> print(func(3,Lt))
['a', 'b', 3]
>>> print(func(4))
[1, 2, 4]

here during the function call func(3,Lt) the default value of L is preserved, it is not overwritten by Lt.

so is default argument have two memory? one for actual default value (with program scope) and other for when an object is passed to it (with scope of function call)?

ParokshaX
  • 277
  • 5
  • 15
  • I think the key point is that `def` is a statement in Python that gets executed. Default arguments are evaluated at the time the function is created, not the time the function is called. – Steven Rumbalski May 14 '13 at 18:19
  • 1
    In your edit, in the first call you passed a new list into the function, so the default argument is being ignored at that moment. That list (`Lt)` is not being referred to by the function once the function returns. – Martijn Pieters May 16 '13 at 11:42
  • 1
    If you call `func()` without a second argument, the local name `L` will refer to the default value list, if you pass in a list `Lt`, then `L` will refer to that list. In both cases, when the function returns, that reference will be cleared again, `L` seizes to exist. The value it referred to however, continues to exist because it has other names refer to it. – Martijn Pieters May 16 '13 at 11:44
  • 1
    CPython uses reference counting; each value counts how many references are pointing to it. Once the count reaches 0, the value is destroyed. There is a garbage collection routine that finds circular references and breaks them to help that process. – Martijn Pieters May 16 '13 at 11:46

2 Answers2

14

As the argument is an attribute of the function object, it normally has the same lifetime as the function. Usually, functions exist from the moment their module is loaded, until the interpreter exits.

However, Python functions are first-class objects and you can delete all references (dynamically) to the function early. The garbage collector may then reap the function and subsequently the default argument:

>>> def foo(bar, spam=[]):
...     spam.append(bar)
...     print(spam)
... 
>>> foo
<function foo at 0x1088b9d70>
>>> foo('Monty')
['Monty']
>>> foo('Python')
['Monty', 'Python']
>>> foo.func_defaults
(['Monty', 'Python'],)
>>> del foo
>>> foo
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'foo' is not defined

Note that you can directly reach the func_defaults attribute (__defaults__ in python 3), which is writable, so you can clear the default by reassigning to that attribute.

ParokshaX
  • 277
  • 5
  • 15
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • 1
    Couldn't the lifetime of the default be shorter then the lifetime of the function? `foo.func_defaults = ([],)` – Steven Rumbalski May 14 '13 at 18:16
  • @StevenRumbalski: Indeed, the attribute is writable. – Martijn Pieters May 14 '13 at 18:18
  • @MartijnPieters so the default arguments will exist in memory as long as the reference to the function exists? '>>> Lt = ['a','b'] >>> print(func(3,Lt)) ['a', 'b', 3] >>> print(func(4)) [1, 2, 4]' so default argument has two memory? one for actual default value and other for when an object is passed to it? – ParokshaX May 16 '13 at 11:31
  • @SamEmrys: no, that's the point; it is *one* default value, and it is the default value that is being manipulated directly. Lists are mutable, they are a sequence of references to other values. You can add and remove references from that sequence. So the function default points to a list, and that list is manipulated directly. That's why the changes persist between calls to the function. – Martijn Pieters May 16 '13 at 11:41
  • @MartijnPieters Ya I got it... the function default arguments are maintained in `func_defaults` attribute (`__defaults__` in case of python 3) as a list – ParokshaX May 16 '13 at 11:58
  • @SamEmrys: A tuple, but yes, you got it. :-) – Martijn Pieters May 16 '13 at 11:58
3

It has at least the same lifetime as the function object (absent something funky). Accordingly, if the module it was loaded from is unloaded by all other modules, and there are no other references, then the function object, and its members, will likely be destroyed.

Because Python is garbage collected, you don't really need to worry about this in any practical sense. If the object escapes, and some other part of the programme has a reference, it will hang around.

If your point is that you would like to rely on the object hanging around and not being reset, then yes, you can do that, unless you have something funky unloading modules, or if you have some code assigning to variable on the function object which stores the default value.

Marcin
  • 48,559
  • 18
  • 128
  • 201
  • **Any** live object with a reference to the default value will keep that value alive, even if the function is unloaded. Thus, using the definition in the question, `X=func('q')` will give X a reference to the list, which will contain 'q' and anything else appended by other function calls. Delete func(), and X will keep the list alive. – Jerry B Oct 05 '13 at 06:37
  • @JerryB True, and not in any way contradictory of what I have said. – Marcin Oct 05 '13 at 10:40