【问题标题】:default values and variable scope默认值和变量范围
【发布时间】:2018-02-10 19:38:53
【问题描述】:

我想我错过了一些关于变量范围和/或默认值如何工作的内容。考虑以下函数:

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 版本是怎么回事?关于变量范围或导致差异的其他一些机制,我缺少什么?

【问题讨论】:

  • 你在函数缩进前缺少了一个本地infront
  • 我推荐这个阅读:lua-users.org/wiki/ScopeTutorial
  • 再次尝试,使用本地功能。按预期工作。没关系。您还应该在 indent 函数中将凹痕值设为本地。
  • @WilliamWalsh(这是语言律师或您可能不知道的东西。)只有变量是本地或全局的;值,包括函数,没有范围。 local function 是以下语句的语法:1) 创建一个局部变量,然后 2) 评估函数定义以获得函数值并将其分配给变量。

标签: lua scope default-value


【解决方案1】:

首先,您应该将indentdentrpr 和可能的printtable 声明为local。 (与 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

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

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

你可以通过indentlocal来解决这个问题。

【讨论】:

  • 好吧,我明白了……有点。但我还不太明白会发生什么。 indent 是否在未设置为本地时每次调用 printtable 时都被定义?当我在循环中调用 printtable 两次时,我希望缩进第二次增加:rpr = rpr..indent()..'['..printtable(k, indentation_level+1)..']'..' = '..printtable(v, indentation_level+1) 但它没有。
  • @lotolmencre:编辑希望能更好地解释它。
  • 谢谢,我明白了。
【解决方案2】:

在 Lua 中,变量是“默认全局的”。如果没有局部(包括参数)“上面”使用一个变量,它就绑定到全局环境。如果有,它会绑定到上面最接近的那个。

【讨论】:

    猜你喜欢
    • 2011-07-25
    • 2022-01-22
    • 1970-01-01
    • 1970-01-01
    • 2015-07-28
    • 1970-01-01
    • 2018-06-28
    • 2017-11-04
    • 1970-01-01
    相关资源
    最近更新 更多