This is a bit of a follow-up to this question.
- Why is locality determined at compile time and not at execution time? Is it purely for performance?
- Are there languages that look up their variables at execution time? I.e. every time a variable is accessed, this variable is first searched in the local scope and then the search escalates through all enclosing scopes?
- How do ECMA languages handle this?
To put question 2 in other words: Are there languages where the following code (in the necessary syntax) works:
def f(): print ('f')
def g():
f()
f = 42
g()
This behaviour is called lexical scoping. What you describe in #2 is called dynamic scoping, though the verbal description is misleading (you say "enclosing scopes" where "calling functions" or "activation records" would be more accurate).
Virtually every language in common use uses lexical scoping, not just Python. That includes C# and ECMAScript/JavaScript (barring eval
and with
), which I assume is what you mean by "ECMA languages". There have been languages, and some of them are still in use. Emacs Lisp is one, and Perl offers both lexical and dynamic scoping.
The rationale for lexical scoping is not just for performance (full lexical scoping including closures actually has a performance cost, see the funcarg problems), it's for simplicity and reliability. While it may be surprising when first learning the language, the rules are actually dead simple so an experienced programmer can instantly tell which use of an identifier refers to which scope. One can understand functions in isolation, as execution isn't affected by who calls this functions and how they decided to name their variables.