Search code examples
pythonmutablefunction-declarationdefault-argumentssymbol-table

Where does a mutable object argument of a function lives? Is there a symbol table? (Python tutorial 4.7.1)


Going through the python tutorial, in section 4.7.1, a mutable default argument is stored somewhere but I can't seem to find it using dir(), globals(), locals() or f.__dict__. I'm referring to this code:

def f(a, L=[]):
    L.append(a)
    return L

behaves as:

>>> print(f(1))
[1]
>>> print(f(2))
[1, 2]
>>> print(f(3))
[1, 2, 3]

I would expect to see this in the namespace of the function, say when I do dir(f) but it is not there.

I had a look at this but this is way more than I'm probably looking for.


Solution

  • As per the Python Data Model:

    __defaults__ A tuple containing default argument values for those arguments that have defaults, or None if no arguments have a default value

    >>> def foo(a=[]):
    ...    a.append(1)
    ...
    ... foo()
    ... foo.__defaults__
    ([1],)
    

    There is also __kwdefaults__ for keyword-only arguments.

    >>> def foo(a=1, *, b=2):
    ...     pass
    ...
    ... foo.__defaults__, foo.__kwdefaults__
    ((1,), {'b': 2})
    

    Note that things in Python are not necessarily stored anywhere accessible. For example, the reference count of an object is not available as an attribute. It only exists in the C layer of the CPython implementation and requires builtin magic to access.

    In fact, __defaults__ is not a "real" attribute either. It is a builtin property fetching the defaults from wherever the implementation stores them.

    # python3
    >>> type(foo).__defaults__
    <attribute '__defaults__' of 'function' objects>
    # pypy3
    >>>> type(foo).__defaults__
    <getset_descriptor object at 0x00000001110adc98>