为什么将参数传递给lua类方法会得到空值

我有一个在lua中从父列表指针中构建树的方法。 特别是我有这个lua表

parents = {2,3,13,5,12,7,11,9,10,11,12,13,14,0}

以及两个函数:

函数1(创建节点):

function create_node(parent, i, created, root)
  if created[i] ~= nil then
        return
  end
    print(i)
--    print(parent)
--  创建一个新节点并设置created[i]
    local new_node = Tree()
    new_node.idx = i
    created[i] = new_node

--    如果 'i' 是根节点,改变根节点指针并返回
    if parent[i] == 0 then
       root[1] = created[i] -- root[1] 表示树的根节点

       return
    end

--    如果父节点还没有创建,那么先创建父节点
    if created[parent[i]] == nil  then
        create_node(parent, parent[i], created, root )
    end
    print(i)

--    找到父指针
    local p = created[parent[i]]
    print (p)

    if #p.children <=2 then
      print(p.idx)
      print(created[i].idx)
      p.add_child(created[i])
    end

end

函数2(递归创建树): 我已经停在了一个叶节点测试了从叶到根的第一条路径,即1-2-3-13-14

function read_postorder_parent_tree(parents)
    n = #parents

--    创建一个数组created[]来跟踪
--    已创建的节点,并将所有条目初始化为None
    created = {}

    root = {}
    for i=1, 1 do
        create_node(parents, i, created, root)
    end
    return root[1]
end

create_note 方法使用下面的 Tree 类:

local Tree = torch.class('Tree')

function Tree:__init()
  self.parent = nil
  self.num_children = 0
  self.children = {}
end

function Tree:add_child(c)

  print(c)
  c.parent = self
  self.num_children = self.num_children + 1
  self.children[self.num_children] = c
end

一切都正常工作,但当我调用p.add_child(created[i])时,参数是nil为什么? (为什么 cnil) ?我已经检查过created[i]p不是nil。我该如何解决这个问题或为什么会发生这种情况?

这是我收到的错误消息:

./Tree.lua:16: attempt to index local 'c' (a nil value)
stack traceback:
    ./Tree.lua:16: in function 'add_child'
    main.lua:120: in function 'create_node'
    main.lua:109: in function 'create_node'
    main.lua:109: in function 'create_node'
    main.lua:109: in function 'create_node'
    main.lua:134: in function 'read_postorder_parent_tree'
    main.lua:153: in function 'main'
    main.lua:160: in main chunk
    [C]: in function 'dofile'
    ...3rto/torch/install/lib/luarocks/rocks/trepl/scm-1/bin/th:150: in main chunk
    [C]: at 0x00405d50
点赞
用户1424244
用户1424244

如果您以面向对象方式定义函数,则必须以相同的方式调用它。

function Tree:add_child(c)

这个声明函数以面向对象的方式使用冒号操作符。为了帮助您理解这意味着什么,它可以重写为:

Tree.add_child = function(self, c)

正如您所看到的,会创建一个隐式的 self 参数来反映调用该函数的对象。然而,您通过标准方式调用该函数:

p.add_child(created[i])

现在您可以看到实际上所做的是将 created[i] 作为 self 而不是 c 传递,然后当然会是 nil。调用这样的函数的标准方法也是通过冒号运算符:

p:add_child(created[i])

这个隐式地将 p 作为实际函数的 self 传递,现在 p 将包含实际的参数。

2017-08-02 11:02:43