0

I have a python programming question, I am using a caching pattern to speed up computation, here is an example code:

def f(a=1, a_dict={}):
    try:
        b=a_dict['one']
        print 'fetched from cache'
    except:
        b=10
        a_dict['one']=10
        print 'put in cache'
    return b

Now if I call this function the first time the result is:

>>> f(1)
put in cache
10

I call again:

>>> f(1)
fetched from cache
10

This is nice a behaviour since it uses caching. However, I find it strange because the variable a_dict has been defined within the function, so once the function is over it should be out of scope... Note that this variable is not visible from outside the function:

>>> a_dict
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'a_dict' is not defined

I would have guessed that when I call the function the second time, the default variable a_dict should have been initialized to {}, so I find it strange that when I call f() the second time the previous value of a_dict is somehow still in scope.

In summary, I would have expected to achieve the desired behaviour like this:

the_dict={}
f(1, the_dict) 
# call second time
f(1, the_dict) 

Because the object the_dict is passed by reference and hence stays in scope.

Can someone please explain the semantics of parameter initialization in a function and their scope?

Mannaggia
  • 4,559
  • 12
  • 34
  • 47
  • Functions are objects, so the default parameters are stored as a member variable in that object. They're only created once, when the function is first called. – flau Aug 12 '14 at 08:41

1 Answers1

1

Functions are objects in python, so default parameters can be thought of as 'members'. It is explained fully: http://effbot.org/zone/default-values.htm

To get the behaviour you expect, you can have the function defined as follows:

def f(a=1, a_dict=None):
    if a_dict is None:
        a_dict = {}
    try:
        b=a_dict['one']
        print 'fetched from cache'
    except:
        b=10
        a_dict['one']=10
        print 'put in cache'
    return b

This means that, rather than the {} being made when the function is defined (and therefore retained in it's object def), it's made when the function is run (and therefore is a local variable).