Common Pitfall: Late Binding in Closures

Posted by Afsal on 12-Jul-2024

Hi Pythonistas!

In the previous post we learned what is late binding?. Today we are discussing a pitfall while using late binding. When we define functions inside a loop, the function retains a reference to the variable, not its value at the time the function was created. This often leads to unexpected results. Let me explain with a example

Code

greetings = ['Hi', 'Hello', 'Hola']

functions = []

for greeting in greetings:
    def say_it():
        print(greeting)
    functions.append(say_it)

for function in functions:
    function()

Expecting output

Hi
Hello
Hola

Actual Ouput

Hola
Hola
Hola

Reason

The function binds the greeting variable only at the runtime so while executing the function the value of the greeting variable will be hola. That’s why it is returning this unexpected result. 

Solution

As an argument to the function and use it inside the function. At that time local reference will be used

Code

functions = []

for greeting in greetings:
    def say_it(greeting_word=greeting):
        print(greeting_word
    functions.append(say_it)

for function in functions:
    function()

Output

Hi
Hello
Hola

Late binding in Python is a powerful feature that enables dynamic method resolution, flexibility, and the ability to write more generic and reusable code. Understanding how late binding works, especially in the context of closures and class methods, can help you avoid common pitfalls and leverage the full potential of Python's dynamic nature.