Python | Scope resolution when a function is called or defined

Python resolves the scope of the parameters of a function in two ways:

  • When the function is defined
  • When the function is called

When the function is defined
Consider this sample program which has a function adder(a, b) which adds an element a to the list b and returns the list b. The default value of b is [1, 8, 11].

Code :

filter_none

edit
close

play_arrow

link
brightness_4
code

def adder(a, b = [1, 8, 11]):
    b.append(a)
    return b
  
print(adder(1))
print(adder(2))
print(adder(9))
print(adder(2, [3, 6]))

chevron_right


Expected Output : 

[1, 8, 11, 1]
[1, 8, 11, 2]
[1, 8, 11, 9]
[3, 6, 2]
Actual Output : 

[1, 8, 11, 1]
[1, 8, 11, 1, 2]
[1, 8, 11, 1, 2, 9]
[3, 6, 2]

Observe that even though we don’t pass a parameter in the 2nd and 3rd call, the default value of b no longer remains [1, 8, 11]. It is because of the fact that Python resolves the reference to name of a default parameter in the scope of a function only once, when it is defined and not every time it is called. Even if a and b were to be any other mutable type like dict and set, the program would have worked in the same way.
What do we do if we want the default value of b to always be [1, 8, 11] ? Inside the function, we can check if b was passed while calling the function or not. If it was not, then we reassign the value of b to [1, 8, 11].
 
When the function is called
Now, consider this program which tries to store lambda function objects (to calculate the square of numbers between 0 and 4) inside a list and call them one by one.
Code :



filter_none

edit
close

play_arrow

link
brightness_4
code

l = []
for i in range(5):
    l.append(lambda : i**2)
for j in range(5):
    print(l[j]())

chevron_right


Expected Output : 

0
1
4
9
16
Actual Output : 

16
16
16
16
16

However, the result is not what was expected from the program. It is because Python resolves the reference to names of non-default parameters in the scope of a function when it is called and not when it is defined. Here the parameter is i. When the loop terminates, the value of i is 4 and when we call any of the lambda functions stored in l, 4**2 = 16 is returned.
What do we do to make the program work the way we expected? Just make i a default parameter for the lambda function and let python’s scope resolution behaviour do that for you.



My Personal Notes arrow_drop_up

Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.




Article Tags :

2


Please write to us at contribute@geeksforgeeks.org to report any issue with the above content.