<分区>
下面的 Python 程序 A 输出 1
,正如预期的那样,而下面的 Python 程序 B 引发了一个未绑定(bind)的局部变量 x
错误,这是违反直觉的。
- 程序 A:
def f(): print(x)
x = 1
f()
- 程序 B:
def f(): print(x); x = 2
x = 1
f()
Javascript 具有完全相同的行为。
- 程序 A:
function f() { console.log(x); }
let x = 1;
f();
- 程序 B:
function f() { console.log(x); let x = 2; }
let x = 1;
f();
但是,在这两种情况下,C++ 都按预期输出 1
。
- 程序 A:
#include <iostream>
int x;
void f() { std::cout << x; }
int main() { x = 1; f(); return 0; }
- 程序 B:
#include <iostream>
int x;
void f() { std::cout << x; int x = 2; }
int main() { x = 1; f(); return 0; }
所以所有程序A输出1
。一方面,Python 和 Javascript 与 C++ 之间的程序 B 差异源于它们不同的范围规则:在 C++ 中,变量的范围从其声明开始,而在 Python 和 Javascript 中,它从声明变量的 block 的开头开始。因此,在 C++ 中,函数 f
中的打印变量 x
解析为全局变量 x
的值 1
,因为它是执行时上下文中的唯一变量。在 Python 和 Javascript 中,函数 f
中的打印变量 x
解析为空,并引发未绑定(bind)的局部变量 x
错误,因为局部变量 x
在这个执行点已经在上下文中,因此它屏蔽了全局变量 x
而没有绑定(bind)到值 2
。 Python 和 Javascript 的这种违反直觉的行为也称为变量提升,因为它在 block 的开头“提升”变量声明(但不是定义)。
编程语言中变量提升的优点和缺点是什么?