默认值和变量范围

时间:2018-02-09 10:55:55

标签: lua scope default-value

我认为我遗漏了关于变量范围和/或默认值如何工作的问题。考虑以下功能:

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版本发生了什么?我对变量范围或其他一些导致差异的机制缺少什么?

2 个答案:

答案 0 :(得分:1)

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

问题是indent是全球性的。

请注意,indentation_levelprinttable的本地,因为它是一个参数。 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

...您调用printtableindent定义indentation_levelindent为1.这是indentation_level,在第一次迭代后的每次迭代都会被调用。 / p>

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

您可以通过制作local {{1}}来解决此问题。

答案 1 :(得分:0)

在Lua中,变量“默认为全局”。如果没有本地(包括参数)“上面”使用变量,则它将绑定到全局环境。如果有的话,它会绑定到上面最近的一个。