这是对这个问题的一点后续。
- 为什么在编译时而不是在执行时确定位置?纯粹是为了性能吗?
- 是否有在执行时查找其变量的语言?即每次访问变量时,首先在本地范围内搜索该变量,然后搜索升级到所有封闭范围?
- ECMA 语言如何处理这个问题?
换句话说,问题 2:是否存在以下代码(在必要的语法中)有效的语言:
def f(): print ('f')
def g():
f()
f = 42
g()
这种行为称为词法作用域。您在 #2 中描述的内容称为动态范围,尽管口头描述具有误导性(您说“封闭范围”,而“调用函数”或“激活记录”会更准确)。
几乎所有常用语言都使用词法作用域,而不仅仅是 Python。这包括 C# 和 ECMAScript/JavaScript(禁止eval
和with
),我认为这就是您所说的“ECMA 语言”。有语言,其中一些仍在使用。Emacs Lisp 就是其中之一,Perl 提供了词法和动态范围。
词法作用域的基本原理不仅仅是为了性能(包括闭包的完整词法作用域实际上有性能成本,请参阅 funcarg 问题),它是为了简单性和可靠性。虽然在第一次学习该语言时可能会感到惊讶,但规则实际上非常简单,因此有经验的程序员可以立即判断标识符的哪个使用指的是哪个范围。人们可以孤立地理解函数,因为执行不受谁调用此函数以及他们决定如何命名变量的影响。