默认值和变量范围

default values and variable scope

我想我遗漏了一些有关变量范围和/或默认值如何工作的信息 lua。考虑以下函数:

function printtable(x, indentation_level)

   indentation_level = indentation_level or 0

   function indent()
      dent = ''
      for i=1,indentation_level do
         dent = dent..'__'
      end
      return dent
   end

   if type(x) ~= 'table' then
      return tostring(x)
   end

   rpr = ''
   for k, v in pairs(x) do
      rpr = rpr..indent()..'['..printtable(k)..']'..' = '..printtable(v, indentation_level+1)
   end
   return rpr
end

当我用

调用它时
t = {1,2,3}

print(printtable(t))

我会得到[1] = 1__[2] = 2__[3] = 3

我期望的是[1] = 1[2] = 2[3] = 3

我重写了python中的函数,看看我的逻辑错误在哪里:

def printdict(x, indentation_level=0):

    def indent():

        dent = ''
        for i in range(indentation_level):
            dent += '__'
        return dent

    if type(x) != dict:
        return str(x)

    rpr = ''
    for k, v in x.items():
        rpr = rpr+indent()+'['+printdict(k)+'] = '+printdict(v, indentation_level+1)

    return rpr

当我调用它时:

t = {1:1,2:2,3:3}

print(printdict(t))

我得到了我所期望的:[1] = 1[2] = 2[3] = 3

那么,lua 版本是怎么回事?关于变量范围或导致差异的其他一些机制,我缺少什么?

在Lua中,变量是"global by default."如果没有局部(包括参数)"above"使用一个变量,它被绑定到全局环境。如果有,它绑定到上面最近的一个。

首先,你应该声明indentdentrpr,可能printtablelocal。 (与 Python 不同,Lua 要求我们声明变量以指定它们的范围。参数和循环变量自动位于定义它们的块中。)

问题是由于 indent 是全局的。

请注意 indentation_level 对于 printtable 是局部的,因为它是一个参数。 indent 引用了 indentation_level,这意味着 indent 是一个 闭包 。闭包是存储对外部局部变量的引用的函数。

每次调用 printtable 时,它都会定义 indent 的新化身,无论 indentation_level 在当时的范围内。在您的代码中,indent 是一个全局变量,因此 indent 的每个新定义都会覆盖之前的定义。

在此循环中:

for k, v in pairs(x) do
  rpr = rpr..indent()..'['..printtable(k)..']'..' = '..printtable(v, indentation_level+1)
end

...您调用 printtable,它定义 indentindentation_level 为 1。这是在第一次之后的每次迭代中调用的 indent .

请注意,您的输入 table 没有子table,因此递归仅下降一级。该循环仅在初始调用中运行。这就是为什么 indentation_level 永远不会高于 1(这对您要尝试做的事情有意义)。

您可以通过 indent local.

来解决这个问题