Hi Maksym,
Python doesn’t need to change from late binding to early binding in
closures. Doing so would unnecessarily break code that requires late
binding and annoy people who expect the current behaviour and are
surprised by early binding.
Lambdas and closures here work with exactly the same execution model
(late binding) as functions using module or builtin variables and names,
and methods using attribute lookups and inheritence. If you write a
function or a method, you are using exactly the same model for name
lookups that is used by lambda. (Although the mechanism is different.)
Names are evaluated when the function is called, not when the function
is defined.
This is true for closures regardless of whether you use lambda or def;
it is true for methods and module-level functions regardless of whether
you use lambda or def. It is always true in Python.
You probably use this behaviour dozens, hundreds, maybe thousands of
times and take it completely for granted. You probably rely on this
behaviour and have code that would break if we shifted from late binding
to early binding.
There is one part of Python’s execution module which consistently uses
early binding instead of late binding: default arguments for function
parameters. And there people have the opposite “surprise” – they get
surprised and annoyed because parameter default values work the way you
want lambda to work, and demand that we follow the Principle Of Least
Surprise and swap to late binding.
So we can’t win. Whatever behaviour we choose, early or late binding,
people will be surprised and annoyed.
What this demonstrates is one of the weakness of the Principle Of Least
Surprise: people aren’t surprised because lambdas in closures violate
Python’s execution model, or because it violates some fundamental
principle of behaviour. It doesn’t – it follows the same rules as other
functions and methods, and many other languages.
People get “surprised” because the computer does what they told it to
do, rather than what they wanted it to do. And there’s nothing we can do
about that.