解释型语言如何声明和引用变量?
How do Interpreted Languages Declare and Reference Variables?
我们以一些简单的pyhton代码为例:
var = 10
print(var)
我想知道何时以及如何声明和引用这里的 var
。我目前正在使用 C++ 开发我自己的受 Lisp 启发的脚本语言,这将是等效的代码:
(def var 10)
(print var)
该语言分为三个部分:tokenizer、“compiler”和 executor .
这里 (def var 10)
更像是一个 'compile' 时间构造,它使用“var”的键值将一个新变量放置到虚拟机中。在此之后,(def...)
函数被转换为一个初始化器,在 execution 阶段执行时重新初始化其变量。 (print var)
然后将指向“var”的指针作为 compilation 的一部分放置到其参数列表中,它再次在 execution 阶段执行.基本上,在编译结束时,执行将拥有所有数据集,不需要额外的 'runtime' 搜索来获得所需的数据。
所以实际上 (def...)
在实际执行阶段没有任何作用,而只是它的编译。这导致结构有点不一致,因为所有其他功能都在执行时执行。
其他解释型语言如何解决这个问题? python 会在运行时到达 var = 10
时声明“var”,然后在执行 print(var)
时动态定位并绑定指向“var”的指针吗?以这种方式建立变量声明有什么好处,或者由于减少了语言运行时搜索而带来的性能改进是否应该包含设计不一致?
在模块级别 python 维护变量字典。 .py
文件在加载时被编译成字节码,然后字节码在运行时将“var”添加到该字典。直接使用本词典
>>> var
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'var' is not defined
>>> globals()["var"] = 10
>>> var
10
功能不同。 Python 对局部变量使用整数索引槽,而不是字典。编译函数时,函数中赋值的变量被认为是局部的,并被转换为该槽中的索引 table.
>>> def foo():
... var = 10
...
>>> import dis
>>> dis.dis(foo)
2 0 LOAD_CONST 1 (10)
2 STORE_FAST 0 (var)
4 LOAD_CONST 0 (None)
6 RETURN_VALUE
请注意 STORE_FAST 0
存储在插槽 0 中。
python 在这两种情况下做事不同的原因是它希望其他模块或模块中的函数在需要时随时动态地将变量分配给模块。 Class定义同理。但功能不同。每次执行函数时都会创建一个新对象来保存函数局部变量。没有简单的方法可以从函数外部访问该对象,并且具有此外部赋值功能确实没有用。
所以这些是 python 本身的两个例子。动态但速度慢一点,或者静态但速度快一点。什么对你更好取决于你的语言目标。
我们以一些简单的pyhton代码为例:
var = 10
print(var)
我想知道何时以及如何声明和引用这里的 var
。我目前正在使用 C++ 开发我自己的受 Lisp 启发的脚本语言,这将是等效的代码:
(def var 10)
(print var)
该语言分为三个部分:tokenizer、“compiler”和 executor .
这里 (def var 10)
更像是一个 'compile' 时间构造,它使用“var”的键值将一个新变量放置到虚拟机中。在此之后,(def...)
函数被转换为一个初始化器,在 execution 阶段执行时重新初始化其变量。 (print var)
然后将指向“var”的指针作为 compilation 的一部分放置到其参数列表中,它再次在 execution 阶段执行.基本上,在编译结束时,执行将拥有所有数据集,不需要额外的 'runtime' 搜索来获得所需的数据。
所以实际上 (def...)
在实际执行阶段没有任何作用,而只是它的编译。这导致结构有点不一致,因为所有其他功能都在执行时执行。
其他解释型语言如何解决这个问题? python 会在运行时到达 var = 10
时声明“var”,然后在执行 print(var)
时动态定位并绑定指向“var”的指针吗?以这种方式建立变量声明有什么好处,或者由于减少了语言运行时搜索而带来的性能改进是否应该包含设计不一致?
在模块级别 python 维护变量字典。 .py
文件在加载时被编译成字节码,然后字节码在运行时将“var”添加到该字典。直接使用本词典
>>> var
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'var' is not defined
>>> globals()["var"] = 10
>>> var
10
功能不同。 Python 对局部变量使用整数索引槽,而不是字典。编译函数时,函数中赋值的变量被认为是局部的,并被转换为该槽中的索引 table.
>>> def foo():
... var = 10
...
>>> import dis
>>> dis.dis(foo)
2 0 LOAD_CONST 1 (10)
2 STORE_FAST 0 (var)
4 LOAD_CONST 0 (None)
6 RETURN_VALUE
请注意 STORE_FAST 0
存储在插槽 0 中。
python 在这两种情况下做事不同的原因是它希望其他模块或模块中的函数在需要时随时动态地将变量分配给模块。 Class定义同理。但功能不同。每次执行函数时都会创建一个新对象来保存函数局部变量。没有简单的方法可以从函数外部访问该对象,并且具有此外部赋值功能确实没有用。
所以这些是 python 本身的两个例子。动态但速度慢一点,或者静态但速度快一点。什么对你更好取决于你的语言目标。