Learning Python 1

Tue 08 April 2008 by Thejaswi Puthraya

Interesting aspect of Python : 1

Yesterday I learnt an interesting aspect of python called closures.

def a(aa1, aa2=10):
     def b(bb1, bb2=aa2):
             print aa1, aa2, bb1, bb2
     aa1+=100
     aa2+=100
     return b

>>> a(20)(5)

What is the output?

The answer by intuition would have been 20 10 5 10. The answer however is 120 110 5 10.

I was amazed by this result and wanted to figure out how this works. I ran pdb on this function using

$ python -m pdb test_fn.py

The result of it was:

> /home/theju/test_fn.py(1)<module>()
-> def a(aa1, aa2=10):
(Pdb) s
> /home/theju/test_fn.py(8)<module>()
-> a(20)(5)
(Pdb)
--Call--
> /home/theju/test_fn.py(1)a()
-> def a(aa1, aa2=10):
(Pdb)
> /home/theju/test_fn.py(2)a()
-> def b(bb1, bb2=aa2):
(Pdb) dir()
['aa1','aa2']
(Pdb) s
> /home/theju/test_fn.py(4)a()
-> aa1+=100
(Pdb) dir()
['aa1', 'aa2', 'b']
(Pdb) dir(b)
['__call__', '__class__', '__delattr__', '__dict__', '__doc__', '__get__', '__getattribute__', '__hash__', '__init__',
'__module__', '__name__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__', 'func_closure',
'func_code', 'func_defaults', 'func_dict', 'func_doc', 'func_globals', 'func_name']
(Pdb) p b.func_defaults
(10,)
(Pdb) s
> /home/theju/test_fn.py(5)a()
-> aa2+=100
(Pdb)
> /home/theju/test_fn.py(6)a()
-> return b
(Pdb)
--Return--
> /home/theju/test_fn.py(6)a()-><functio...b7c6adbc>
-> return b
(Pdb)
--Call--
> /home/theju/test_fn.py(2)b()
-> def b(bb1, bb2=aa2):
(Pdb)
> /home/theju/test_fn.py(3)b()
-> print aa1, aa2, bb1, bb2
(Pdb)
120 110 5 10
--Return--
> /home/theju/test_fn.py(3)b()->None
-> print aa1, aa2, bb1, bb2
(Pdb)
--Return--
> /home/theju/test_fn.py(8)<module>()->None
-> a(20)(5)
(Pdb)
--Return--
> <string>(1)<module>()->None
(Pdb)

The default parameter values are evaluated when the function definition is executed. See this for more details.

Thanks to Gopi for helping me learn this concept and more.