【问题标题】:How do Interpreted Languages Declare and Reference Variables?解释语言如何声明和引用变量?
【发布时间】:2021-10-31 09:50:44
【问题描述】:

我们以一些简单的 pyhton 代码为例:

var = 10
print(var)

我想知道这里的var 何时以及如何被声明和引用。我目前正在使用 C++ 编写我自己的受 Lisp 启发的脚本语言,这将是等效代码:

(def var 10)
(print var)

该语言分为三部分:tokenizer、“compiler”和executor

这里的(def var 10) 更像是一个“编译”时间构造,它使用“var”键值对虚拟机放置一个新变量。在此之后,(def...) 函数被转换为一个初始化器,在 execution 阶段执行时重新初始化其变量。 (print var) 然后将指向“var”的指针置于其参数列表中,作为 编译 的一部分,它再次在 执行 阶段执行。基本上在编译结束时,执行具有所有数据集,不需要额外的“运行时”搜索即可获得所需的数据。

所以实际上(def...) 不参与实际执行阶段,而只是编译。这会导致结构有点不一致,因为所有其他功能都是在执行时执行的。

其他解释语言如何解决这个问题? python 会在运行时到达var = 10 时声明“var”,然后在执行print(var) 时动态定位并绑定指向“var”的指针吗?以这种方式建立变量声明有什么好处,或者由于减少了语言运行时搜索,是否应该接受设计不一致以提高性能?

【问题讨论】:

标签: python variables scripting compilation


【解决方案1】:

在模块级别,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 对局部变量使用整数索引槽,而不是字典。编译函数时,在函数中分配的变量被认为是局部变量,并转换为此槽表中的索引。

>>> 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 在这两种情况下做不同的事情的原因是它希望其他模块或模块中的函数在他们想要的任何时候动态地为模块分配变量。类定义也是一样的。但功能不同。每次执行函数时,都会创建一个新对象来保存函数局部变量。没有简单的方法可以从函数外部访问该对象,并且具有此外部分配功能确实没有用。

所以这是python本身的两个例子。动态但慢一点,或者静态但快一点。对你来说更好的是你的语言目标。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-07-11
    • 1970-01-01
    • 1970-01-01
    • 2012-05-31
    • 1970-01-01
    • 2014-06-25
    • 1970-01-01
    相关资源
    最近更新 更多