精华内容
下载资源
问答
  • lua教程
    更多相关内容
  • 串口屏LUA教程-如何显示文本.pdf(通过LUA教程demo讲述如何设置文本控件的API函数使用以及编写程序的注意事项。)
  • Lua教程

    千次阅读 多人点赞 2020-03-10 17:11:40
    Lua简介 参考文章 Lua1.x 对于学术用途是免费的,但是商业用途则需要协商 Lua2.x table作为对象和类的基础,table索引,算术操作符,字符串拼接,顺序比较,函数调用, Lua作为无限制免费软件发布, Lua3.x 我们解决...

    1 Lua简介

    参考文章

    Lua1.x
    对于学术用途是免费的,但是商业用途则需要协商
    Lua2.x
    table作为对象和类的基础,table索引,算术操作符,字符串拼接,顺序比较,函数调用, Lua作为无限制免费软件发布,
    Lua3.x
    我们解决了fallback冲突问题。我们将fallback替换为tag方法:钩子是以(event, tag)的形式挂在字典里的。

    • Lua应用场景:游戏开发,独立应用脚本,扩展和数据库插件,安全系统

    2 Lua编程工具

    Lua在线编程

    Lua在线编程
    第一个Lua程序
    Lua开发工具LuaEdit下载
    lua开发工具安装教程
    在这里插入图片描述

    3 起点

    3.1 编程方法

    lua [options] [script [args]]

    -e:直接将命令传入Lua

    prompt> lua -e "print(math.sin(12))" --> -0.53657291800043

    -l:加载一个文件.

    -i:进入交互模式.

    _PROMPT内置变量作为交互模式的提示符

    prompt> lua -i -e "_PROMPT=' lua> '"`
    
    lua>
    

          Lua的运行过程,在运行参数之前,Lua会查找环境变量LUA_INIT的值,如果变量存在并且值为@filename,Lua将加载指定文件。如果变量存在但不是以@开头,Lua假定filename为Lua代码文件并且运行他。利用这个特性,我们可以通过配置,灵活的设置交互模式的环境。可以加载包,修改提示符和路径,定义自己的函数,修改或者重命名函数等。

    全局变量arg存放Lua的命令行参数。

    prompt> lua script a b c

    在运行以前,Lua使用所有参数构造arg表。脚本名索引为0,脚本的参数从1开始增加。脚本前面的参数从-1开始减少。

    prompt> lua -e "sin=math.sin" script a b

    arg表如下:

    arg[-3] = “lua”

    arg[-2] = “-e”

    arg[-1] = “sin=math.sin”

    arg[0] = “script”

    arg[1] = “a”

    arg[2] = “b”
    交互式编程,在控制台交互界面直接输入lua代码运行:
    交互式编程
    脚本式编程,通过调用lua文件,使lua文件中的代码直接运行:
    在这里插入图片描述
    开发工具编程,在Lua开发工具里进行编译,开发工具里可以对代码进行调试,方便上手:
    在这里插入图片描述

    3.2注释

    单行注释

    -- 单行注释
    

    多行注释

    --[[
     多行注释
     多行注释
     ]]--
    

    3.3关键字(21个)

    andbreakdoelse
    elseifendfalsefor
    functionifinlocal
    nilnotorrepeat
    returnthentrueuntil
    while

    3.4 标识符

    注:lua是大小写敏感的,比如a和A是两个不同的标识符
    标识符:用于定义一个变量,函数获取其他用户定义的项目,以字母(a-z或A-Z)或者 下划线_ 开头的字母、下划线、数字序列。

    4 数据类型和值

    Lua是动态类型语言,变量不要类型定义。变量没有预定义的类型,每一个变量都可能包含人一种类型的值。Lua中有8个基本类型分别是nil,boolean,number,string,userdata,function,thread和table,函数type可以测试指定变量或者值的类型。
    在这里插入图片描述
    在这里插入图片描述
    一般情况下同一变量代表不同类型的值会造成混乱,最好不要用,但是特殊情况下可以带来便利,比如nil

    4.1 nil

    一个取值nil;一个全局变量没有被赋值前为nil,给全局变量赋nil可以删除该变量

    4.2 boolean

    两个取值false和true。在控制结构中除了false和nil为假,其他的值都为真。比如0和空串都是真

    4.3 number

    表示实数,Lua中没有整数。数据常量的小数部分和指数部分都是可选的,数据常量的例子:

    4		0.4		4.57e-3		0.3e12		5e+12
    

    4.4 string

        字符的序列,lua是8位字节,所以字符串可以包含任何数值字符,包括嵌入的0。意味着你可以存储任意的二进制数据在一个字符串里。Lua中字符串是不可以修改的,你可以创建一个新的变量存放你要的字符串,如下:

    
    

        string和其他对象一样,Lua自动进行内存分配和释放,一个string可以只包含一个字母也可以包含一本书,Lua可以高效地处理长字符串,1M的string在Lua中很是常见的。可以使用单引号或者双引号表示字符串,也可以使用[[]]间的字符表示字符串,最好使用一种,除非两种引号嵌套情况,

    a = "a line"
    b = 'another line'
    

    可以通过#来计算字符串的长度,放在字符串前面

    • 转义字符
    \a 响铃(BEL)
    \b 退格
    \f 换页
    \n 换行
    \r 回车
    \t 水平制表tab
    \v 垂直指标
    \\ 反斜线字符\
    \" 双引号字符
    \' 单引号字符
    \ddd 13位八进制数所代表的任意字符
    \xhh  12位十六进制所代表的任意字符
    

    4.5 table

    table的创建是通过构造表达式来完成,最简单的构造表达式是{},用来创建一个空表。

    local tb1 = {}
    local tb2 = {"yu","an","rui"}
    

    table其实是一个关联数组,数组的索引可以是数字也可以是字符串(相当于map)

    a = {}
    a["key1" ]= "v1"
    a[1] = 22;
    a[1] = a[1]+11;
    for k,v in pairs(a) do
    	print(k,":",v)
    end
    -- key1:v1
    -- 1:33
    

    Lua里表的默认初始索引一般以1开始

    local tb2 = {"yu","an","rui"}
    for k,v in pairs(tb2) do
    	print(k,v)
    end
    --1yu
    --2an
    --3rui
    

    4.6 function

    函数可以存在变量里

    function say(n)
    	print(n)
    end
    say2 = say
    say2(10)
    

    函数可以以你们函数的方式作为参数传递

    function test(t1,fun)
    	for k,v in pairs(t1) do
    		print(fun(k,v))
    	end
    end
    tab = {"a","b"}
    test(tab,
    function(key,val)
    	return key .. " = ".. val
    end
    );
    

    4.7 thread

    线程和协程的区别:线程可以同时多个运行,而协程任意时刻只能运行一个

    • lua里,最主要的线程是协同程序。和线程差不多,拥有自己独立的栈,局部变量和指令指针,可以跟其他协同程序共享全局变量和其他大部分东西。

    4.8 userdata

    userdata是一种用户自定义数据,用于表示一种由应用程序或c/c++语言库所创建胡类型,可以将任意c/c++的任意数据类型的数据(通常是struct和指针)存储到Lua变量中调用。

    5 变量

    变量有三种里类型:全局变量,局部变量,表中的域
            默认情况下,变量总是认为是全局的,全局变量不需要声明,给一个变量赋值后即创建了全局变量,访问一个没有初始化的全局变量也不会出错,只不过得到的结果是nil。如果你想删除一个全局变量,只需要讲变量赋值为nil。
          用local显式声明为局部变量,局部变量的作用域为从声明位置开始到所在语句块结束。变量的默认值为nil。访问局部变量胡速度比全局变量更快

    6 表达式(运算符)

    • 算术运算符:+ - * / ^ %
    • 关系运算符:< > <= >= == ~=
    • 逻辑运算符:and or not
    • 连接运算符: ..

    字符串连接,如果操作数为数字,Lua将数字转成字符串。

    print("Hello " .. "World")      --> Hello World
    print(0 .. 1)                   --> 01
    
    • 其他运算符:#

    返回字符串或表的长度

    print(#"Hello") --->5
    
    • 运算符优先级

    从高到低。

    ^
    
    not    - (unary)
    
    *      /
    
    +      -
    
    ..
    
    <      >      <=     >=     ~=     ==
    
    and
    
    or
    
    

    其中除了^和…外所有的二元运算符都是左连接的
    x^y^z <--> x^(y^z)

    7 基本语法

    7.1 赋值语句

    • 赋值改变一个变量的值和改变表域的最基本方法
    a = "hello" .. "world"
    t.n = t.n+1
    
    • 多个变量同时赋值
    a,b = 10,2*x   <-->       a=10; b=2*x
    

    遇到赋值语句Lua先计算右边所有的值然后再执行赋值操作,这样我们就可以进行交换变量胡值

    • 多变量赋值,数和值的个数不一致
      值个数不足够,补nil;变量个数不足,多余的值会被忽略
    • 多值赋值经常用来交换变量,或将函数调用返回给变量
    a, b = f() --f()返回两个值,第一个赋给a,第二个赋给b。
    

    7.2 控制结构语句

    控制结构的条件表达式结果可以是任何值,Lua认为false和nil为假,其他值为真

    • if语句-三种形式
    if conditions then
    	then_part
    end
    
    if conditions then
    	then_part
    else
    	else_part
    end
    
    if conditions then
    	then_part
    elseif conditions then
    	elseif_part
    .. -->多个elseif
    else
    	else_part
    end
    
    • while语句
    while conditon do
    	statements;
    end
    
    • repeat-untile语句
    repeat
    	statements;
    until conditons;
    
    • for-两大类语句

    第一 ,数值for循环

    for var = exp1,exp2,exp3 do
    	loop-part
    end
    

        for将用exp3作为stept从exp1到exp2,执行loop-part.其中exp3可以省略,默认step=1
    有几点需要注意:三个表达式只会在循环前计算一次;控制变量var是局部变量自动被声明,并且只能在循环内有效;循环过程中最好不要改变控制变量的值。
    第二,范式for循环
        iparis一般用来遍历数组从1,2…;paris一般用来遍历表(键值对),它也可以遍历数组,数组实质上就是键为1,2…的,元素为值的表;如果表的元素里从1,2连续开始的,也可以使用ipairs访问1,2…等的键值对。

    --print all values of array 'a'
    for i,v in iparis(a) do
    	print(v)
    end
    
    --print all keys of table 't'
    for k in pairs(t) do
    	print(k)
    end
    

    eg:构造反向表

    days = {"Sunday", "Monday", "Tuesday", "Wednesday",
    
                  "Thursday", "Friday", "Saturday"}
    revDays = {}
    for i,v in ipairs(days) do 
    	revDays[v] = i
    	
    end
    x = "Tuesday" 
    print(revDays[x])        --> 3
    

    8 函数

       函数的用途:调用语句-完成指定任务;赋值语句的表达式-计算并返回值
     语法:

    function func_name(arguments-list)
    					statements-list;
    end
    

    调用函数时,如果参数列表为空,必须使用()表明是函数调用。

    print(8*9,9/8)
    print(os.data())
    function show()
     print("heiren,are you ?")
    end
    show();
    

    当函数只有一个参数并且这个参数是字符串或表构造的时候,()可有可无

    print "Hello World"      <-->       print("Hello World")
    dofile 'a.lua'           <-->       dofile ('a.lua')
    print [[a multi-line     <-->       print([[a multi-line
             message]]                          message]])
    f{x=10, y=20}            <-->       f({x=10, y=20})
    type{}                   <-->       type({})
    
    • 面向对象方式调用函数的语法,比如o:foo(x)与o.foo(o.x)等价

    • Lua使用的函数,即可是Lua编写的,也可是其他语言编写的,对于Lua程序员,用什么语言实现的函数使用起来都一样。

    • Lua函数实参和形参的匹配与赋值语句类似,多余部分被忽略,缺少部分用nil补足。

    • 在这里插入图片描述

      8.1 多返回值

      Lua函数可以返回多个结果值,比如:

      s.e = string.find("hello lua users","Lua");
      print(s,e)          -->7  9
      

      Lua函数中,在return后列出要返回的值的列表即可返回多值,比如:

      function test()
      	local arg1,arg2 = 1,3;
      	return arg1,arg2;
      end
      print(test())     -->1,3
      

      8.2 可变参数

      Lua函数可以接收可变数目的参数,和C语言类似,在函数参数列表中使用三点…表示函数有可变的参数

    function add(...)
    	result = 0
    	for i,v in ipairs(arg) do
    		result = result+v;
    	end
    	print(#arg,"个数");--6个数
    	print(result)--21
    end
    add(1,2,3,4,5,6)
    print(result)--21
    

    8.3 命名参数

    Lua的函数参数是和位置相关的,调用时实参会按顺序依次传给形参。有时候指定参数是很有用的。比如下面

    function rename(arg)
    	return os.rename(org.old,org.new)
    end
    
    • 当函数的参数很多的时候,这种函数参数的传递方式很方便的。比如:传递坐标,颜色等
    c = Color{
    r = 0,g = 256,b=100
    }
    

    9 字符串(string)

    9.1 字符串操作

    string.upper(argument) --转换成大写字母
    string.lower(argument) -- 转换成小写字母
    string.gsub(mainString,findString,replaceString) --在字符串中替换
    string.reverse(arg) --字符串反转
    string.format(...) --返回一个类似printf的格式化的字符串
    string.char(arg) string.byte(arg[,int]) --将整型数字转换成字符并连接   转换字符为整型数字
    string.len(arg) --计算字符串的长度
    string.rep(string,n) --返回字符串str的n个拷贝
    .. -- 连接两个字符串 如果其中有一个是nil,会报错
    string.gmatch(str,pattern) -- 返回一个在字符串str找到的下一个符号pattern描述的字串,如果没有找到,迭代函数返回nil
    string.match(str,pattern,init) --寻找str中的第一个配对,init可选,搜寻的起点,默认为1,没有成功的配对,返回nil
    

    tonumber(str)将字符串转换成数字

    9.2 字符串格式化

    string.format()
    格式字符串包含的转义符:

    • %c 接收一个数字,并将其转换为ASCII码表中的对应的字符
    • %d,%i 接收要给数字并将其转化为有符号的整数格式
    • %o 接收一个数字并将其转换为八进制数格式
    • %u 接收一个数字并将其转换为无符号整数格式
    • %x 接收一个数字并将其转换为十六进制数格式,小写字母
    • %X 接收一个数字并将其转换为十六进制数格式,大写字母
    • %e 接收一个数字并将其转换为科学计数格式,使用小写字母e
    • %E 接收一个数字并将其转换为科学计数格式,使用大写字母E
    • %f 接收一个数字并将其转换为浮点数
    • %g(%G) 接收一个数字并将其转换为%e及%f中较短的形式
    • %q 接收一个字符串并将其转换为可安全被lua编译器读入的格式
    • %s 接收要给字符串并按照给定的参数格式化该字符串
      为进一步细化格式,可以在%后添加参数,参数将以如下顺序读入:
    • 符号:+
    • 占位符 :0 默认为空格
    • 对齐标识:指定了字串宽度是,默认右对齐,增加-号可以改为左对齐
    • 宽度数值
    • 小数位数/字串裁切:%5.3f 只显示小数3位,%5.3s只显示字符串前3位等

    9.3 字符串模式匹配(pattern)

    单个字符(除^$()%.[]*±?外)与该字符自身配对

    • .点 与任何字符配对
    • %a 与任何字母配对
    • %c 与任何控制符配对,比如\n
    • %l 与任何小写字母配对
    • %d 与任何数字配对
    • %p 与任何标点配对
    • %s 与空白字符配对
    • %u 与任何大写字母配对
    • %w 与任何字母/数字配对
    • %x 与任何十六进制数配对
    • %z 与任何代表0的字符配对
    • %x
    • [数个字符类] 与任何[]中包含的字符类配对,比如[%w_]与任何字母/数字或下划线配对
    • [^数个字符类] 与任何不包含在[]内的字符配对
      当上述的字符类用大写书写时,表示与非此字符类的任何字符配对。

    10 数据结构

    10.1 数组

        在Lua中通过整数下标访问table中元素,即是数组。并且数组大小不固定,可以动态增长。通常我们初始化数组时,就间接地定义了数组的大小,例如:

    array = {"lua","Tutorial"}
    for i = 1,2 do 
    	print(array[i])
    end
    
    --输出
    lua
    Tutorial
    

    我们可以用构造器在创建数组的同时初始化数组:

    array = {1,3,5,14,24,234};
    

    10.2 矩阵和多维数组

    Lua中有两种表示矩阵的方法,一是数组的数组,也就是说,table的每个元素是另一个table;二是将行和列组合起来,如果索引下标都是整数,通过第一个索引乘一个常量(列)再加上第二个索引,如果索引是字符串,可以用一个单子符讲两个字符串索引连接起来

    mt = {}
    for i = 1,10 do
    	mt[i] = {}
    	for j = 1,10 do
    		mt[i][j] = 0
    	end
    end
    mt = {}
    for i = 1,10 do
    	for j = 1,12 do
    		mt[i*12 + j] = 0
    	end
    end
    
    

        Lua中table实现的数据本省就具有稀疏性。不管采用那种方式,只需要存储那些非nil的元素,该特性可用于稀疏矩阵中。

    10.3 链表

    根节点:可以理解为尾节点

    `list = nil
    

    在链表表头插入一个值为v的节点:

    list = {next = list,value = v};
    

    遍历链表

    local l = list
    while l do
    	print(l.value)
        l = l.next
    end
    

    其他类型的链表,像双向链表和循环链表类似的也是很容易实现的。

    10.4 队列和双向队列

    可以使用lua的table库提供的insert和remove操作来实现队列,但这种方式实现的队列针对大数据量时效率太低,有效的方式是使用两个索引下表,一个表示第一个元素,另一个表示最后一个元素。

    function ListNew()
    	return {first = 0,last = -1}
    end
    

    为了避免污染全局命名空间,重写代码

    List = {}
    function List.new()
    	return {first = 0,last = -1}
    end
    

    队列的插入和删除

    function List.pushleft(list,value)
    	local first = list.ifrst - 1;
    	list.first = first
    	list[first] = value
    end
    
    function List.pushright(list,value)
      local last = list.last+1
      list.last = last
      list[last] = value
    end
    
    function List.popleft(list)
      local first = list.first
      if first > list.last then error("list is empty") end
      local value = list[first]
      list[first] = nil
      list.first = first + 1
      return value
    end
    function List.popright(list)
      local last= list.last
      if first > list.last then error("list is empty") end
      local value = list[last]
      list[last] = nil
      list.last= last+ 1
      return value
    end
    

        对严格意义上的队列来讲,我们只能调用pushright和popleft,这样一来,first和last的索引值都随之增加,幸运的是我们使用的是Lua的table实现的,你可以访问数组的元素,通过使用下表从1到20,也可以使用16777216到16777236。另外Lua使用双精度表示数字,假定你每秒中执行100万次插入操作,在数值溢出前你的程序可以运行200年。

    10.5 集合和包

        将所有集合中的元素作为下标存放在一个table里,下面不需要查找table,只需要测试看对于给定的元素,表的对应下标的元素值是否为nil。比如:

    reserved = {
     ["while"] = true,["end"] = true;
     ["function"] = true,["local"] = true,
    }
    for w in allwords() do
     if reserved[w] then
     --'w' is a reserved word
     ...
    end
    

    还可以使用辅助函数更加清晰的构造集合:

    function Set(list)
      local set = {}
      for _,l in ipairs(list) do set[l] = true end
      return set
    end
    reserved = Set{"while","end","function","local"}
    

    11 迭代器

    11.1 泛型for迭代器

    泛型for在自己内部实际上保存了迭代函数,状态常量,控制变量。泛型for迭代器提供了集合的key/vlue对,语法格式如下:

    for k,v in pairs(t) do
     print(k,v)
    end
    

    11.2无状态迭代器

    无状态迭代器是指一种自身不保存任何状态的迭代器。因此,我们可以在多个循环中使用同意无状态的迭代器来避免创建新闭包的开销。迭代器状态就是需要遍历的table及当前的索引值(控制变量),使用代码重写ipairs,如下:

    local function iter(a,i)
    	i = i+1
    	local v = a[i]
    	if v then
    		return i,v
    	end
    end
    
    function ipairs(a)
     return iter,a,0
    end
    

    12 table(表)

    Table 操作
    以下列出了 Table 操作常用的方法:

    序号方法用途
    1table.concat (table [, step [, start [, end]]]):concat是concatenate(连锁, 连接)的缩写. table.concat()函数列出参数中指定table的数组部分从start位置到end位置的所有元素, 元素间以指定的分隔符(sep)隔开。
    2table.insert (table, [pos,] value);在table的数组部分指定位置(pos)插入值为value的一个元素. pos参数可选, 默认为数组部分末尾.
    3table.maxn (table)指定table中所有正数key值中最大的key值. 如果不存在key值为正数的元素, 则返回0。(Lua5.2之后该方法已经不存在了,本文使用了自定义函数实现)
    4table.remove (table [, pos])返回table数组部分位于pos位置的元素. 其后的元素会被前移. pos参数可选, 默认为table长度, 即从最后一个元素删起。
    5table.sort (table [, comp])对给定的table进行升序排序。

    接下来我们来看下这几个方法的实例。

    • Table 连接:我们可以使用 concat() 方法来连接两个 table:
    fruits = {"banana","orange","apple"}
    -- 返回 table 连接后的字符串
    print("连接后的字符串 ",table.concat(fruits))
    
    -- 指定连接字符
    print("连接后的字符串 ",table.concat(fruits,", "))
    
    -- 指定索引来连接 table
    print("连接后的字符串 ",table.concat(fruits,", ", 2,3))
    

    执行以上代码输出结果为:

    连接后的字符串 	bananaorangeapple
    连接后的字符串 	banana, orange, apple
    连接后的字符串 	orange, apple
    
    • 插入和移除:以下实例演示了 table 的插入和移除操作:
    fruits = {"banana","orange","apple"}
    
    -- 在末尾插入
    table.insert(fruits,"mango")
    print("索引为 4 的元素为 ",fruits[4])
    
    -- 在索引为 2 的键处插入
    table.insert(fruits,2,"grapes")
    print("索引为 2 的元素为 ",fruits[2])
    
    print("最后一个元素为 ",fruits[5])
    table.remove(fruits)
    print("移除后最后一个元素为 ",fruits[5])
    

    执行以上代码输出结果为:

    索引为 4 的元素为  mango
    索引为 2 的元素为   grapes
    最后一个元素为     mango
    移除后最后一个元素为   nil
    
    • Table 排序:以下实例演示了 sort() 方法的使用,用于对 Table 进行排序:
    fruits = {"banana","orange","apple","grapes"}
    print("排序前")
    for k,v in ipairs(fruits) do
      print(k,v)
    end
    
    table.sort(fruits)
    print("排序后")
    for k,v in ipairs(fruits) do
       print(k,v)
    end
    

    执行以上代码输出结果为:

    排序前
    1   banana
    2   orange
    3   apple
    4    grapes
    排序后
    1  apple
    2    banana
    3   grapes
    4   orange
    
    • Table 最大值:table.maxn 在 Lua5.2 之后该方法已经不存在了,我们定义了 table_maxn 方法来实现。
      以下实例演示了如何获取 table 中的最大值:
    function table_maxn(t)
        local mn = 0
        for k, v in pairs(t) do
            if mn < k then
                mn = k
            end
        end
        return mn
    end
    tbl = {[1] = "a", [2] = "b", [3] = "c", [26] = "z"}
    print("tbl 长度 ", #tbl)
    print("tbl 最大值 ", table_maxn(tbl))
    

    执行以上代码输出结果为:

    tbl 长度    3
    tbl 最大值  26
    

    13 模块与包

    模块类似于一个封装库,从 Lua 5.1 开始,Lua 加入了标准的模块管理机制,可以把一些公用的代码放在一个文件里,以 API 接口的形式在其他地方调用,有利于代码的重用和降低代码耦合度。

    Lua 的模块是由变量、函数等已知元素组成的 table,因此创建一个模块很简单,就是创建一个 table,然后把需要导出的常量、函数放入其中,最后返回这个 table 就行。以下为创建自定义模块 module.lua,文件代码格式如下:

    -- 文件名为 module.lua
    -- 定义一个名为 module 的模块
    module = {}
    
    -- 定义一个常量
    module.constant = "这是一个常量"
    
    -- 定义一个函数
    function module.func1()
       io.write("这是一个公有函数!\n")
    end
    
    local function func2()
       print("这是一个私有函数!")
    end
    
    function module.func3()
       func2()
    end
    
    return module
    

    加载模块require

    require("<模块名>")require "<模块名>"
    

    执行 require 后会返回一个由模块常量或函数组成的 table,并且还会定义一个包含该 table 的全局变量。

    require("module")
    
    print(module.constant)
    
    module.func3()
    

    14 元表

    • setmetatable(table,metatable): 对指定table设置元表(metatable),如果元表(metatable)中存在__metatable键值,setmetatable会失败 。
    • getmetatable(table): 返回对象的元表(metatable)。
      以下实例演示了如何对指定的表设置元表:
    mytable = {}                          -- 普通表 
    mymetatable = {}                      -- 元表
    setmetatable(mytable,mymetatable)     -- 把 mymetatable 设为 mytable 的元表 
    

    以上代码也可以直接写成一行:

    mytable = setmetatable({},{})
    

    以下为返回对象元表:

    getmetatable(mytable)                 -- 这回返回mymetatable
    

    一、__index 元方法
    这是 metatable 最常用的键。
    当你通过键来访问 table 的时候,如果这个键没有值,那么Lua就会寻找该table的metatable(假定有metatable)中的__index 键。如果__index包含一个表格,Lua会在表格中查找相应的键。
    我们可以在使用 lua 命令进入交互模式查看:

    $ lua
    Lua 5.3.0  Copyright (C) 1994-2015 Lua.org, PUC-Rio
    > other = { foo = 3 } 
    > t = setmetatable({}, { __index = other }) 
    > t.foo
    3
    > t.bar
    nil
    

    如果__index包含一个函数的话,Lua就会调用那个函数,table和键会作为参数传递给函数。
    __index 元方法查看表中元素是否存在,如果不存在,返回结果为 nil;如果存在则由 __index 返回结果。

    mytable = setmetatable({key1 = "value1"}, {
      __index = function(mytable, key)
        if key == "key2" then
          return "metatablevalue"
        else
          return nil
        end
      end
    })
    
    print(mytable.key1,mytable.key2)
    

    实例输出结果为:

    value1	metatablevalue
    

    实例解析:

    • mytable 表赋值为 {key1 = “value1”}。
    • mytable 设置了元表,元方法为 __index。
    • 在mytable表中查找 key1,如果找到,返回该元素,找不到则继续。
    • 在mytable表中查找 key2,如果找到,返回该元素,找不到则继续。
    • -判断元表有没有__index方法,如果__index方法是一个函数,则调用该函数。
    • 元方法中查看是否传入 “key2” 键的参数(mytable.key2已设置),如果传入 “key2” 参数返回 “metatablevalue”,否则返回 mytable 对应的键值。

    我们可以将以上代码简单写成:

    mytable = setmetatable({key1 = "value1"}, { __index = { key2 = "metatablevalue" } })
    print(mytable.key1,mytable.key2)
    

    二、__newindex 元方法
    __newindex 元方法用来对表更新,__index则用来对表访问 。

    当你给表的一个缺少的索引赋值,解释器就会查找__newindex 元方法:如果存在则调用这个函数而不进行赋值操作。

    以下实例演示了 __newindex 元方法的应用:

    mymetatable = {}
    mytable = setmetatable({key1 = "value1"}, { __newindex = mymetatable })
    
    print(mytable.key1)
    
    mytable.newkey = "新值2"
    print(mytable.newkey,mymetatable.newkey)
    
    mytable.key1 = "新值1"
    print(mytable.key1,mymetatable.newkey1)
    

    以上实例执行输出结果为:

    value1
    nil    新值2
    新值1    nil
    

    以上实例中表设置了元方法 __newindex,在对新索引键(newkey)赋值时(mytable.newkey = “新值2”),会调用元方法,而不进行赋值。而如果对已存在的索引键(key1),则会进行赋值,而不调用元方法 __newindex。

    以下实例使用了 rawset 函数来更新表:

    mytable = setmetatable({key1 = "value1"}, {
      __newindex = function(mytable, key, value)
           rawset(mytable, key, "\""..value.."\"")
    
      end
    })
    
    mytable.key1 = "new value"
    mytable.key2 = 4
    
    print(mytable.key1,mytable.key2)
    

    以上实例执行输出结果为:

    new value  "4"
    

    三、为表添加操作符
    以下实例演示了两表相加操作:

    -- 计算表中最大值,table.maxn在Lua5.2以上版本中已无法使用
    -- 自定义计算表中最大值函数 table_maxn
    function table_maxn(t)
        local mn = 0
        for k, v in pairs(t) do
            if mn < k then
                mn = k
            end
        end
        return mn
    end
    
    -- 两表相加操作
    mytable = setmetatable({ 1, 2, 3 }, {
      __add = function(mytable, newtable)
        for i = 1, table_maxn(newtable) do
          table.insert(mytable, table_maxn(mytable)+1,newtable[i])
        end
        return mytable
      end
    })
    
    secondtable = {4,5,6}
    
    mytable = mytable + secondtable
    	for k,v in ipairs(mytable) do
    print(k,v)
    end
    

    以上实例执行输出结果为:

    1	1
    2	2
    3	3
    4	4
    5	5
    6	6
    

    __add 键包含在元表中,并进行相加操作。 表中对应的操作列表如下:

    模式描述
    __add对应的运算符 ‘+’.
    __sub对应的运算符 ‘-’.
    __mul对应的运算符 ‘*’.
    __div对应的运算符 ‘/’.
    __mod对应的运算符 ‘%’.
    __unm对应的运算符 ‘-’.
    __concat对应的运算符 ‘…’.
    __eq对应的运算符 ‘==’.
    __lt对应的运算符 ‘<’.
    __le对应的运算符 ‘<=’.

    四、__call 元方法
    __call 元方法在 Lua 调用一个值时调用。以下实例演示了计算表中元素的和:

    -- 计算表中最大值,table.maxn在Lua5.2以上版本中已无法使用
    -- 自定义计算表中最大值函数 table_maxn
    function table_maxn(t)
        local mn = 0
        for k, v in pairs(t) do
            if mn < k then
                mn = k
            end
        end
        return mn
    end
    
    -- 定义元方法__call
    mytable = setmetatable({10}, {
      __call = function(mytable, newtable)
    	sum = 0
    	for i = 1, table_maxn(mytable) do
    		sum = sum + mytable[i]
    	end
        for i = 1, table_maxn(newtable) do
    		sum = sum + newtable[i]
    	end
    	return sum
      end
    })
    newtable = {10,20,30}
    print(mytable(newtable))
    

    以上实例执行输出结果为:

    70
    

    五、__tostring 元方法
    __tostring 元方法用于修改表的输出行为。以下实例我们自定义了表的输出内容:

    mytable = setmetatable({ 10, 20, 30 }, {
      __tostring = function(mytable)
        sum = 0
        for k, v in pairs(mytable) do
            sum = sum + v
     end
        return "表所有元素的和为 " .. sum
      end
    })
    print(mytable)
    

    以上实例执行输出结果为:

    表所有元素的和为 60
    

    15 面向对象

     Person = {age = 0}
    function Person:new(o,a)
    	o = o or {}
    	setmetatable(o,self)
    	self.__index = self;
    	a = a or 0
    	self.age = a;
    	return o;
    end
    function Person:say()
    	print("age = ",self.age);
    end
    --创建对象
    p1 = Person:new(nil,10)
    --使用点号访问d对象的属性
    p1.age =11;
    --使用冒号来访问对象的成员函数
    p1:say(); -- 或者使用p1.say(p1)  使用点访问时,系统不会自动传递当前的table给self
    
    
    --继承
    Student = Person:new()
    function Student:new(o,side)
    	o = o or Person:new(o,side)
    	setmetatable(o,self)
    	self.__index = self;
    	return o;
    end
    function Student:say()
    	
    	print("学生年龄 = ",self.age)
    	Person:say()--调用父类方法
    end
    s1 = Student:new(nil,10);
    s1:say()
    
    --输出
    age = 11
    学生年龄= 10
    age = 10
    

    16 lua与C++交互

    Lua与C++交互

    17 参考

    W3CSchoolLua教程
    在这里插入图片描述

    展开全文
  • 主要介绍了Lua教程(十七):C API简介,本文讲解了基础知识、栈、C API中的错误处理、Lua调用C程序、C程序调用Lua代码的错误处理等内容,需要的朋友可以参考下
  • 无涯教程网(learnfk)整理提供:Lua的设计目的是成为一个很容易嵌入其它语言中使用的语言。
  • 主要介绍了Lua教程(二十):Lua调用C函数,本文讲解了C函数作为应用程序的一部分、C函数库成为Lua的模块等内容,需要的朋友可以参考下
  • 主要介绍了Lua教程(一):Lua脚本语言介绍,需要的朋友可以参考下
  • 主要介绍了Lua教程(十九):C调用Lua,本文讲解了C调用Lua基础知识、table操作、调用Lua函数等内容,需要的朋友可以参考下
  • 主要介绍了Lua教程(二十二):userdata,这里我们通过一个简单完整的示例来学习一下Lua中userdata的使用方式,需要的朋友可以参考下
  • 主要介绍了Lua教程(四):函数详解,本文讲解了多重返回值、变长参数、具名实参、闭合函数、匿名函数、非全局函数等内容,需要的朋友可以参考下
  • 主要介绍了Lua教程(十): 全局变量和非全局的环境,本文讲解了老的全局变量环境和Lua5中新的非全局环境相关知识,需要的朋友可以参考下
  • 主要介绍了Lua教程(十三):弱引用table,一个table的弱引用类型是通过其元表的__mode字段来决定的,如果该值为包含字符"k",那么table就是key弱引用,如果包含"v",则是value弱引用,如果两个字符均存在,就是key/value...
  • 主要介绍了Lua教程(十二):面向对象编程,本文讲解了类、继承、私密性等面向对象编程知识,需要的朋友可以参考下
  • 主要介绍了Lua教程(八):数据持久化,本文讲解了数据文件持久化、序列化两部份内容,需要的朋友可以参考下
  • Lua教程.pdf

    2019-05-19 15:20:37
    lua电子书,可以帮助初学者更快了解lua,快速掌握基本语法
  • 主要介绍了Lua教程(十四):字符串库详解,本文讲解了基础字符串函数、模式匹配函数、模式、捕获(capture):、替换等内容,需要的朋友可以参考下
  • 主要介绍了Lua教程(一):简介、优势和应用场景介绍,本文是Lua教程系列文章的第一篇,需要的朋友可以参考下
  • 主要介绍了Lua教程(十六):系统库(os库)本文着重讲解了OS库中的日期和时间操作和其他系统调用两部份内容,需要的朋友可以参考下
  • 主要介绍了Lua教程(二十一):编写C函数的技巧,本文讲解了数组操作、字符串操作、在C函数中保存状态等内容,需要的朋友可以参考下
  • 主要介绍了Lua教程(三):值与类型介绍,本文起讲解了Lua的八种基本类型、userdata、thread、table等内容,需要的朋友可以参考下
  • 主要介绍了Lua教程(五):迭代器和泛型for,本文讲解了迭代器与Closure、泛型for的语义、 无状态迭代器的例子、 具有复杂状态的迭代器等内容,需要的朋友可以参考下
  • 主要介绍了Lua教程(六):编译执行与错误,本文讲解了、C代码、错误、错误处理与异常、错误消息与追溯等内容,需要的朋友可以参考下
  • 主要介绍了Lua教程(三):表达式和语句,本文讲解了算术操作符、关系操作符、逻辑操作符、字符串连接、table构造器、控制结构等内容,需要的朋友可以参考下
  • 广州大彩物联型串口屏开发 LUA教程11-循环播放视频:物联型串口屏通过 LUA 脚本配合工程可以实现播放循环屏内部或者外部视频的功能
  • 主要介绍了Lua教程(十五):输入输出库,本文讲解了简单模型、完整I/O模型、性能小技巧、其它文件操作等内容,需要的朋友可以参考下
  • 主要介绍了Lua教程(七):数据结构详解,本文讲解了数组、二维数组、链表、队列与双向队列、 集合和包(Bag)、StringBuilder等内容,需要的朋友可以参考下
  • 串口屏LUA教程-文本保存V1.0.pdf(主要讲述在LUA脚本中使用文件IO系统把数据保存到内存中,并在重新上电后把数据读出来。)
  • 串口屏LUA教程-自定义串口指令V1.0.pdf(本文将介绍通过LUA脚本的自定义串口指令设置按钮按下、设置文本、设置蜂鸣器响。并在按下按钮或通过键盘输入数据后发送自定义指令。)
  • 主要介绍了Lua教程(十一):模块与包详解,本文讲解了require函数、 编写模块的基本方法、使用环境、module函数等内容,需要的朋友可以参考下
  • Python-Python和Lua教程

    2019-08-10 04:59:52
    Python和Lua教程

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 20,394
精华内容 8,157
关键字:

lua教程