Lua查找表元素过程(元表、__index方法是如何工作的)

原创 2013年06月05日 11:22:11

近日开始频繁使用Lua,于是把这块东西理了一下,特此记录。


Lua的表本质其实是个类似HashMap的东西,其元素是很多的Key-Value对,如果尝试访问了一个表中并不存在的元素时,就会触发Lua的一套查找机制,也是凭借这个机制来模拟了类似“类”的行为



举例说明:

tempTable = {}
print(tempTable.memberA) --这里试图打印tempTable并不存在的成员memberA
执行结果:nil
输出为nil的原因很简单,tempTable中并没有memberA这个成员,这符合我们平时对HashMap的认知。但对于Lua表,如果tempTable有元表,情况就不同了。


什么是元表:
元表像是一个“操作指南”,里面包含了一系列操作的解决方案,例如__index方法就是定义了这个表在索引失败的情况下该怎么办。


__index元方法:
很多人对此都有误解,这个误解是:如果A的元表是B,那么如果访问了一个A中不存在的成员,就会访问查找B中有没有这个成员。而这个理解是完全错误的,实际上,即使将A的元表设置为B,而且B中也确实有这个成员,返回结果仍然会是nil,原因就是B的__index元方法没有赋值。别忘了我们之前说过的:“元表是一个操作指南”,定义了元表,只是有了操作指南,但不应该在操作指南里面去查找元素,而__index方法则是“操作指南”的“索引失败时该怎么办”。这么说有点绕。所以:


举个栗子:)

father = {
	house=1
}
son = {
	car=1
}
setmetatable(son, father) --把son的metatable设置为father
print(son.house)
输出的结果是nil,但如果把代码改为
father = {
	house=1
}
father.__index = father -- 把father的__index方法指向自己
son = {
	car=1
}
setmetatable(son, father)
print(son.house)

输出的结果为1,符合预期


这样一来,结合上例,来解释__index元方法的含义:

在上述例子中,访问son.house时,son中没有house这个成员,但Lua接着发现son有元表father,注意:此时,Lua并不是直接在father中找名为house的成员,而是调用father的__index方法,如果__index方法为nil,则返回nil,如果是一个表(上例中father的__index方法等于自己,就是这种情况),那么就到__index方法所指的这个表中查找名为house的成员,于是,最终找到了house成员。
注:__index方法除了可以是一个表,还可以是一个函数,如果是一个函数,__index方法被调用时将返回该函数的返回值。


到这里,总结一下Lua查找一个表元素时的规则,其实就是如下3个步骤:


1.在表中查找,如果找到,返回该元素,找不到则继续

2.判断该表是否有元表(操作指南),如果没有元表,返回nil,有元表则继续

3.判断元表(操作指南)中有没有关于索引失败的指南(即__index方法),如果没有(即__index方法为nil),则返回nil;如果__index方法是一个表,则重复1、2、3;如果__index方法是一个函数,则返回该函数的返回值

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

lua 的元表和元表的__index字段

众所周知,lua的继承是通过元表的__index字段来实现的,比如child类要继承自parent类,就需要把child的元表设为parent,并且要把child的元表(此时是parent)的__in...

lua中查找表的过程已经(以及对元表和__index方法的理解)

Lua的表本质其实是个类似HashMap的东西,其元素是很多的Key-Value对,如果尝试访问了一个表中并不存在的元素时,就会触发Lua的一套查找机制,也是凭借这个机制,才能够实现“面向对象”的。 ...

理解Lua语言中的__index,__newindex,rawget和rawset

在谈及Lua中的__index,__newindex,rawget和rawset前,需要理解Lua中的元表这个概念。 零、元表的概念 对Lua中元表的解释: 元表可以改变表的行为模式。 这里举个例子:...

cocos2dx 3.4 lua mvc代码解析

使用3.4python新建一个lua工程,进去一看,我去,这个都是个啥!!!仔细研究,在研究,终于看懂了一点,先记下来。 程序入口,main.m 无变化,AppDelegate::applicati...

关于工作的心得。

1、关于工作。明确工作目标,不要听他要做什么,要明确他想要做什么。 要做的东西和想要做的东西完全不一样 2、尽可能多的考虑问题,不要满足于一个问题一个问题的分析。这是程序员的思维,不涉及具体方案的...

使用muduo-0.9.3的程序编译不过的问题解决

编译报错信息: /home/xocoder/ThirdParty/muduo-0.9.3/muduo/muduo/net/TcpConnection.cc:302:对‘muduo::Logger::L...

猪说她要减肥

猪说她要减肥。说了两遍。从昨天墨迹到今天。还要me写点东西作为监督。me就纳闷了。猪如果都减肥了。那人吃肉的话怎么办。2006年12月13日的猪重125市斤。半年后的目标110市斤。110。有创意的数...
  • Gooing
  • Gooing
  • 2006-12-13 11:00
  • 1271

面向对象的lua

使用lua很久了,对于如何面向对象使用lua还是想说些什么。 1. 首先我想说的是lua不适合面向对象,或者说他的基因不是为面向对象设计的。 2. lua可以使用面向对象,作为lua的一个特性可以...

lua之__index

当我们访问一个表的不存在的域,返回结果为nil,这是正确的,但并不一定正确。实际上,这种访问触发lua解释器去查找__index metamethod:如果不存在,返回结果为nil;如果存在则由__i...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)