# [Tutor] function remember calls?

Peter Otten __peter__ at web.de
Tue Aug 9 10:16:03 CEST 2011

```Robert Johansson wrote:

> This is my attempt to generate all pairs of relatively prime pairs of
> nonnegative integers (n, m) such that n + m <= N, using the Stern-Brocot
> tree.
>
> def rp_bounded_sum(n, i = 0, p = (0, 1), q = (1, 1), S = set([(0, 1), (1,
> 1)])):
>     # Returns a set S with all relatively prime pairs (a, b)
>     # such that 0 <= a <= b and a + b <= n.
>     r = p[0] + q[0], p[1] + q[1]
>     if r[0] + r[1] <= n:
>         rp_bounded_sum(n, 1, p, r, S)
>         rp_bounded_sum(n, 1, r, q, S)
>     if not i:
>         return S

Default values for function arguments are shared across function
invocations. If you have mutable defaults, e. g. a list or set, and modify
that default value during the function call the modifications will be
visible the next time you invoke the function. A simple example:

>>> def f(x, items=[]):
...     items.append(x)
...     return items
...
>>> f(1)
[1]
>>> f(2)
[1, 2]
>>> f(3)
[1, 2, 3]
>>> f(1, [42])
[42, 1]
>>> f(4)
[1, 2, 3, 4]

The standard idiom to avoid this issue is to use a special default value to
signal that the argument was not provided. In most cases that special value
is None:

>>> def f(x, items=None):
...     if items is None:
...             items = [] # if no list was provided make a new one
...     items.append(x)
...     return items
...
>>> f(1)
[1]
>>> f(2)
[2]
>>> f(3)
[3]
>>> f(1, [42])
[42, 1]
>>> f(4)
[4]

```