超级详细的Lua语言的基础教程

本文介绍了Lua编程语言的基础概念,包括其动态类型、数据类型(如nil、boolean、number、string、userdata、function、thread和table)、变量、赋值、循环结构、函数定义与调用、运算符、数组、迭代器以及table的使用。
摘要由CSDN通过智能技术生成

由于编写测试脚本,不光Python好用,Lua也很好用,整理了一下Lua的基础教程,有需要的可以了解一下,以下是自己总结出来的

lua

数据类型

lua 是动态类型语言,变量不需要类型定义,可直接赋值。 值可以存储在变量中,作为参数传递或结果返回。lua 中有 8 个基本类型分别为:nil、boolean、number、string、userdata、function、thread 和 table。

数据类型描述
nil这个最简单,只有值nil属于该类,表示一个无效值(在条件表达式中相当于false)
boolean包含两个值:false和true
number表示双精度类型的实浮点数
string字符串由一对双引号或单引号来表示
function由 C 或 lua 编写的函数
userdata表示任意存储在变量中的C数据结构
thread表示执行的独立协程,用于执行协同程序
table表(table)其实是一个"关联数组"(associative arrays),数组的索引可以是数字、字符串或表类型。在 lua 里,table 的创建是通过"构造表达式"来完成,最简单构造表达式是{},用来创建一个空表
nil(空)
  • nil 类型表示一种没有任何有效值,它只有一个值 – nil,例如打印一个没有赋值的变量,便会输出一个 nil 值
  • 对于全局变量和 table,nil 还有一个"删除"作用,给全局变量或者 table 表里的变量赋一个 nil 值,等同于把它们删掉
  • nil 作比较时应该加上双引号 "
boolean(布尔)
  • boolean 类型只有两个可选值:true(真) 和 false(假),lua 把 false 和 nil 看作是 false,其他的都为 true,数字 0 也是 true
number(数字)
  • 默认只有一种 number 类型 – double(双精度)类型(默认类型可以修改 luaconf.h 里的定义)
string(字符串)
  • 字符串由一对双引号或单引号来表示
  • 也可以用 2 个方括号 “[[]]” 来表示"一块"字符串
  • 在对一个数字字符串上进行算术操作时,会尝试将这个数字字符串转成一个数字
  • 使用 # 来计算字符串的长度,放在字符串前面
function(函数)
  • 函数是被看作是"第一类值(First-Class Value)",函数可以存在变量里
  • function 可以以匿名函数(anonymous function)的方式通过参数传递
thread(线程)
  • 最主要的线程是协同程序(coroutine)。它跟线程(thread)差不多,拥有自己独立的栈、局部变量和指令指针,可以跟其他协同程序共享全局变量和其他大部分东西
  • 线程跟协程的区别:线程可以同时多个运行,而协程任意时刻只能运行一个,并且处于运行状态的协程只有被挂起(suspend)时才会暂停
userdata(自定义类型)
  • userdata 是一种用户自定义数据,用于表示一种由应用程序或 C/C++ 语言库所创建的类型,可以将任意 C/C++ 的任意数据类型的数据(通常是 struct 和 指针)存储到 lua 变量中调用

变量

变量在使用前,必须在代码中进行声明,即创建该变量。

编译程序执行代码之前编译器需要知道如何给语句变量开辟存储区,用于存储变量的值。

lua 变量有三种类型:全局变量、局部变量、表中的域。

lua 中的变量全是全局变量,那怕是语句块或是函数里,除非用 local 显式声明为局部变量。

局部变量的作用域为从声明位置开始到所在语句块结束。

变量的默认值均为 nil。

赋值语句
  • 赋值是改变一个变量的值和改变表域的最基本的方法。
  • 可以对多个变量同时赋值,变量列表和值列表的各个元素用逗号分开,赋值语句右边的值会依次赋给左边的变量
  • 遇到赋值语句会先计算右边所有的值然后再执行赋值操作
  • 当变量个数和值的个数不一致时,.变量个数 > 值的个数,按变量个数补足nil.变量个数 < 值的个数,多余的值会被忽略
索引
  • 对 table 的索引使用方括号 []

循环

很多情况下我们需要做一些有规律性的重复操作,因此在程序中就需要重复执行某些语句。

一组被重复执行的语句称之为循环体,能否继续重复,决定循环的终止条件。

循环结构是在一定条件下反复执行某段程序的流程结构,被反复执行的程序被称为循环体。

循环语句是由循环体及循环的终止条件两部分组成的

循环类型描述
while 循环在条件为 true 时,让程序重复地执行某些语句。执行语句前会先检查条件是否为 true。
for 循环重复执行指定语句,重复次数可在 for 语句中控制。
repeat…until重复执行循环,直到 指定的条件为真时为止
循环嵌套可以在循环内嵌套一个或多个循环语句(while do … end;for … do … end;repeat … until;)
循环控制语句
  • 循环控制语句用于控制程序的流程, 以实现程序的各种结构方式
    - 控制语句描述
    - break 语句退出当前循环或语句,并开始脚本执行紧接着的语句。
    - goto 语句将程序的控制点转移到一个标签处
无限循环
  • 在循环体中如果条件永远为 true 循环语句就会永远执行下
流程控制
  • 流程控制语句通过程序设定一个或多个条件语句来设定。在条件为 true 时执行指定程序代码,在条件为 false 时执行其他指定代码

  • 控制结构的条件表达式结果可以是任何值,lua认为false和nil为假,true和非nil为真。

  • 要注意的是 0 为 true

    语句描述
    if 语句if 语句 由一个布尔表达式作为条件判断,其后紧跟其他语句组成。
    if…else 语句if 语句 可以与 else 语句搭配使用, 在 if 条件表达式为 false 时执行 else 语句代码。
    if 嵌套语句你可以在if 或 else if中使用一个或多个 if 或 else if 语句

函数

函数是对语句和表达式进行抽象的主要方法。既可以用来处理一些特殊的工作,也可以用来计算一些值。提供了许多的内建函数,你可以很方便的在程序中调用它们,如print()函数可以将传入的参数打印在控制台上。

函数主要有两种用途:

1.完成指定的任务,这种情况下函数作为调用语句使用

2.计算并返回值,这种情况下函数作为赋值语句的表达式使用

函数定义
  • lua 编程语言函数定义格式如下:

    optional_function_scope function function_name( argument1, argument2, argument3..., argumentn)
        function_body
        return result_params_comma_separated
    end
    
  • optional_function_scope: 该参数是可选的制定函数是全局函数还是局部函数,未设置该参数默认为全局函数,如果你需要设置函数为局部函数需要使用关键字 local。

  • function_name: 指定函数名称。

  • argument1, argument2, argument3…, argumentn: 函数参数,多个参数以逗号隔开,函数也可以不带参数。

  • function_body: 函数体,函数中需要执行的代码语句块。

  • result_params_comma_separated: 函数返回值,lua语言函数可以返回多个值,每个值以逗号隔开

多返回值
  • 函数可以返回多个结果值用逗号(,)隔开
可变参数
  • 函数可以接受可变数目的参数,和 C 语言类似,在函数参数列表中使用三点 … 表示函数有可变的参数

    function add(...)  
        local s = 0  
        for i, v in ipairs{...} do   --> {...} 表示一个由所有变长参数构成的数组  
            s = s + v  
        end  
        return s  
    end  
    print(add(3,4,5,6,7))  --->25
    
  • 我们可以将可变参数赋值给一个变量。

    function average(...)
        result = 0
        local arg={...}    --> arg 为一个表,局部变量
        for i,v in ipairs(arg) do
            result = result + v
        end
        print("总共传入 " .. #arg .. " 个数")
        return result/#arg
    end
    
    print("平均值为",average(10,5,3,4,5,6))
    
    --以上代码执行结果为:
    --总共传入 6 个数
    --平均值为    5.5
    
  • 通过 select("#",…) 来获取可变参数的数量:

    function average(...)
        result = 0
        local arg={...}
        for i,v in ipairs(arg) do
            result = result + v
        end
        print("总共传入 " .. select("#",...) .. " 个数")
        return result/select("#",...)
    end
    
    print("平均值为",average(10,5,3,4,5,6))
    --以上代码执行结果为:
    
    --总共传入 6 个数
    --平均值为    5.5
    
    

  • 可能需要几个固定参数加上可变参数,固定参数必须放在变长参数之前

    function fwrite(fmt, ...)  ---> 固定的参数fmt
        return io.write(string.format(fmt, ...))     
    end
    
    fwrite("runoob\n")       --->fmt = "runoob", 没有变长参数。  
    fwrite("%d%d\n", 1, 2)   --->fmt = "%d%d", 变长参数为 1 和 2
    
    -- 输出结果为:
    
    -- runoob
    -- 12
    
    
  • 通常在遍历变长参数的时候只需要使用 {…},然而变长参数可能会包含一些 nil,那么就可以用 select 函数来访问变长参数了:select(’#’, …) 或者 select(n, …)

      select('#', …) 返回可变参数的长度
      select(n, …) 用于访问 n 到 select('#',…) 的参数
    
  • 调用select时,必须传入一个固定实参selector(选择开关)和一系列变长参数。如果selector为数字n,那么select返回它的第n个可变实参,否则只能为字符串"#",这样select会返回变长参数的总数

    do  
        function foo(...)  
            for i = 1, select('#', ...) do  -->获取参数总数
                local arg = select(i, ...); -->读取参数
                print("arg", arg);  
            end  
        end  
    
        foo(1, 2, 3, 4);  
    end
    --输出结果为:
    --arg    1
    --arg    2
    --arg    3
    --arg    4 
    
    

运算符

运算符是一个特殊的符号,用于告诉解释器执行特定的数学或逻辑运算。lua提供了以下几种运算符类型:

算术运算符

关系运算符

逻辑运算符

其他运算符

算术运算符
  • 下表列出了 lua 语言中的常用算术运算符,设定 A 的值为10,B 的值为 20

    操作符描述实例
    +加法A + B 输出结果 30
    -减法A - B 输出结果 -10
    *乘法A * B 输出结果 200
    /除法B / A w输出结果 2
    %取余B % A 输出结果 0
    ^乘幂A^2 输出结果 100
    -负号-A 输出结果 -10
关系运算符
  • 下表列出了 lua 语言中的常用关系运算符,设定 A 的值为10,B 的值为 20:

    操作符描述实例
    ==等于,检测两个值是否相等,相等返回 true,否则返回 false(A == B) 为 false。
    ~=不等于,检测两个值是否相等,相等返回 false,否则返回 true(A ~= B) 为 true。
    >大于,如果左边的值大于右边的值,返回 true,否则返回 false(A > B) 为 false。
    <小于,如果左边的值大于右边的值,返回 false,否则返回 true(A < B) 为 true。
    >=大于等于,如果左边的值大于等于右边的值,返回 true,否则返回 false(A >= B) 返回 false。
    <=小于等于, 如果左边的值小于等于右边的值,返回 true,否则返回 false(A <= B) 返回 true。
逻辑运算符
  • 下表列出了 lua 语言中的常用逻辑运算符,设定 A 的值为 true,B 的值为 false:

    操作符描述实例
    and逻辑与操作符。 若 A 为 false,则返回 A,否则返回 B。(A and B) 为 false。
    or逻辑或操作符。 若 A 为 true,则返回 A,否则返回 B。(A or B) 为 true。
    not逻辑非操作符。与逻辑运算结果相反,如果条件为 true,逻辑非为 false。not(A and B) 为 true。
位操作符
  • 下表列出了 lua 语言中的常用位操作符

    操作符描述
    &(按位与)操作法。
    Ι(按位或)操作
    ~(按位异或)操作。
    ~(按位非)操作。
    <<(左移)操作。
    >>(右移)操作。
其他运算符
  • 下表列出了 lua 语言中的连接运算符与计算表或字符串长度的运算符:

    操作符描述实例
    连接两个字符串a…b ,其中 a 为 "Hello " , b 为 “World”, 输出结果为 “Hello World”。
    #一元运算符,返回字符串或表的长度。#“Hello” 返回 5
运算符优先级
  • 从高到低的顺序:
    ^
    not    - (unary)
    *      /
    +      -
    ..
    <      >      <=     >=     ~=     ==
    and
    or 
    

数组

数组,就是相同数据类型的元素按一定顺序排列的集合,可以是一维数组和多维数组。

lua 数组的索引键值可以使用整数表示,数组的大小不是固定的

一维数组
  • 一维数组是最简单的数组,其逻辑结构是线性表。一维数组可以用for循环出数组中的元素

    array = {"lua", "Tutorial"}
    
    for i= 0, 2 do
        print(array[i])
    end
    
    --输出结果为 nil Lua Tutorial
    
  • 我们可以使用整数索引来访问数组元素,如果知道的索引没有值则返回nil。

  • 索引值是以 1 为起始,但你也可以指定 0 开始。

  • 除此外我们还可以以负数为数组索引值

多维数组
  • 多维数组即数组中包含数组或一维数组的索引键对应一个数组。

    -- 初始化数组
    array = {}
    for i=1,3 do
        array[i] = {}
            for j=1,3 do
                array[i][j] = i*j
            end
    end
    
    -- 访问数组
    for i=1,3 do
        for j=1,3 do
            print(array[i][j])
        end
    end
    
    --输出结果 1 2 3 2 4 6 3 6 9
    

迭代器

迭代器(iterator)是一种对象,它能够用来遍历标准模板库容器中的部分或全部元素,每个迭代器对象代表容器中的确定的地址。

迭代器是一种支持指针类型的结构,它可以遍历集合的每一个元素。

在lua中我们常常使用函数来描述迭代器,每次调用该函数就返回集合的下一个元素。lua 的迭代器包含以下两种类型:无状态的迭代器
和多状态的迭代器

泛型 for 迭代器
  • 泛型 for 在自己内部保存迭代函数,实际上它保存三个值:迭代函数、状态常量、控制变量。

  • 泛型 for 迭代器提供了集合的 key/value 对,语法格式如下:

    array = {"Google", "Runoob"}
    
    for key,value in ipairs(array) do
       print(key, value)
    end
    
    --输出结果为  1 Google  2 Runoob
    
  • 以上实例中我们使用了 lua 默认提供的迭代函数 ipairs。

  • 下面我们看看泛型 for 的执行过程:

    • 首先,初始化,计算 in 后面表达式的值,表达式应该返回泛型 for 需要的三个值:迭代函数、状态常量、控制变量;与多值赋值一样,如果表达式返回的结果个数不足三个会自动用 nil 补足,多出部分会被忽略。
    • 第二,将状态常量和控制变量作为参数调用迭代函数(注意:对于 for 结构来说,状态常量没有用处,仅仅在初始化时获取他的值并传递给迭代函数)。
    • 第三,将迭代函数返回的值赋给变量列表。
    • 第四,如果返回的第一个值为nil循环结束,否则执行循环体。
    • 第五,回到第二步再次调用迭代函数
无状态的迭代器
  • 无状态的迭代器是指不保留任何状态的迭代器,因此在循环中我们可以利用无状态迭代器避免创建闭包花费额外的代价。

  • 每一次迭代,迭代函数都是用两个变量(状态常量和控制变量)的值作为参数被调用,一个无状态的迭代器只利用这两个值可以获取下一个元素。

  • 这种无状态迭代器的典型的简单的例子是 ipairs,它遍历数组的每一个元素。

  • 以下实例我们使用了一个简单的函数来实现迭代器,实现 数字 n 的平方:

    function square(iteratorMaxCount,currentNumber)
        if currentNumber<iteratorMaxCount then
            currentNumber = currentNumber+1
            return currentNumber, currentNumber*currentNumber
        end
    end
    
    for i,n in square,3,0  do
        print(i,n)
    end
    
    -- 输出结果  1  1      2  4       3  9
    
  • 迭代的状态包括被遍历的表(循环过程中不会改变的状态常量)和当前的索引下标(控制变量),ipairs 和迭代函数都很简单,我们在 lua 中可以这样实现:

    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
    
  • 当 lua 调用 ipairs(a) 开始循环时,他获取三个值:迭代函数 iter、状态常量 a、控制变量初始值 0;然后 lua 调用 iter(a,0) 返回 1, a[1](除非 a[1]=nil);第二次迭代调用 iter(a,1) 返回 2, a[2]……直到第一个 nil 元素

多状态的迭代器
  • 很多情况下,迭代器需要保存多个状态信息而不是简单的状态常量和控制变量,最简单的方法是使用闭包,还有一种方法就是将所有的状态信息封装到 table 内,将 table 作为迭代器的状态常量,因为这种情况下可以将所有的信息存放在 table 内,所以迭代函数通常不需要第二个参数。

  • 以下实例我们创建了自己的迭代器:

    array = {"Google", "Runoob"}
    
    function elementIterator (collection)
        local index = 0
        local count = #collection
        -- 闭包函数
        return function ()
            index = index + 1
            if index <= count then
                --  返回迭代器的当前元素
                return collection[index]
            end
        end
    end
    
    for element in elementIterator(array) do
        print(element)
    end
    
    --以上输出结果为:Google Runoob
    
    --以上我们可以看到,elementIterator 内使用了闭包函数,实现计算集合大小并输出各个元素
    
lua中文教程,原名:programming in lua 目录 版权声明..............i 译序..i 目录iii 第一篇语言.......1 第0章序言.......1 0.1 序言..........1 0.2 Lua的使用者................2 0.3 Lua的相关资源............3 0.4 本书的体例.................3 0.5 关于本书...3 0.6 感谢..........4 第1章起点.......5 1.1 Chunks.......5 1.2 全局变量...7 1.3 词法约定...7 1.4 命令行方式.................7 第2章类型和值9 2.1 Nil..............9 2.2 Booleans....9 2.3 Numbers...10 2.4 Strings......10 2.5 Functions.12 2.6 Userdata and Threads.12 第3章表达式..13 3.1 算术运算符...............13 3.2 关系运算符...............13 3.3 逻辑运算符...............13 3.4 连接运算符...............14 3.5 优先级.....15 3.6表的构造..15 第4章基本语法................18 4.1 赋值语句.18 4.2 局部变量与代码块(block)......19 4.3 控制结构语句...........20 Programming in Lua iv Copyright ® 2005, Translation Team, www.luachina.net 4.4 break和return语句......23 第5章函数......24 5.1 返回多个结果值.......25 5.2可变参数..27 5.3 命名参数.28 第6章再论函数................30 6.1 闭包........32 6.2 非全局函数...............34 6.3 正确的尾调用(Proper Tail Calls)...36 第7章迭代器与泛型for....40 7.1 迭代器与闭包...........40 7.2 范性for的语义...........42 7.3 无状态的迭代器.......43 7.4 多状态的迭代器.......44 7.5 真正的迭代器...........45 第8章编译·运行·调试47 8.1 require函数.................49 8.2 C Packages.................50 8.3 错误........51 8.4 异常和错误处理.......52 8.5 错误信息和回跟踪(Tracebacks)....53 第9章协同程序................56 9.1 协同的基础...............56 9.2 管道和过滤器...........58 9.3 用作迭代器的协同...61 9.4 非抢占式多线程.......63 第10章完整示例..............68 10.1 Lua作为数据描述语言使用........68 10.2 马尔可夫链算法.....71 第二篇 tables与objects........75 第11章数据结构..............76 11.1 数组......76 11.2 阵和多维数组.........77 11.3 链表......78 11.4 队列和双端队列.....78 11.5 集合和包.................80 11.6 字符串缓冲.............80 第12章数据文件与持久化..................84 12.1 序列化...86 Programming in Lua v Copyright ® 2005, Translation Team, www.luachina.net 第13章 Metatables and Metamethods...92 13.1 算术运算的Metamethods............92 13.2 关系运算的Metamethods............95 13.3 库定义的Metamethods................96 13.4 表相关的Metamethods................97 第14章环境..103 14.1 使用动态名字访问全局变量...103 14.2声明全局变量........104 14.3 非全局的环境.......106 第15章 Packages.............109 15.1 基本方法...............109 15.2 私有成员(Privacy)................111 15.3 包与文件................112 15.4 使用全局表............113 15.5 其他一些技巧(Other Facilities)...115 第16章面向对象程序设计.................118 16.1 类.........119 16.2 继承.....121 16.3 多重继承...............122 16.4 私有性(privacy)...................125 16.5 Single-Method的对象实现方法127 第17章 Weak表...............128 17.1 记忆函数...............130 17.2 关联对象属性.......131 17.3 重述带有默认值的表...............132 第三篇标准库134 第18章数学库................135 第19章 Table库...............136 19.1数组大小................136 19.2 插入/删除..............137 19.3 排序.....137 第20章 String库..............140 20.1 模式匹配函数.......141 20.2 模式.....143 20.3 捕获(Captures).146 20.4 转换的技巧(Tricks of the Trade)151 第21章 IO库..157 21.1 简单I/O模式..........157 21.2 完全I/O 模式........160 Programming in Lua vi Copyright ® 2005, Translation Team, www.luachina.net 第22章操作系统库........165 22.1 Date和Time............165 22.2 其它的系统调用...167 第23章 Debug库..............169 23.1 自省(Introspective)..............169 23.2 Hooks...173 23.3 Profiles.174 第四篇 C API..177 第24章 C API纵览..........178 24.1 第一个示例程序...179 24.2 堆栈.....181 24.3 C API的错误处理..186 第25章扩展你的程序....188 25.1 表操作.189 25.2 调用Lua函数.........193 25.3 通用的函数调用...195 第26章调用C函数..........198 26.1 C 函数..198 26.2 C 函数库................200 第27章撰写C函数的技巧..................203 27.1 数组操作...............203 27.2 字符串处理...........204 27.3 在C函数中保存状态.................207 第28章 User-Defined Types in C........212 28.1 Userdata.................212 28.2 Metatables..............215 28.3 访问面向对象的数据...............217 28.4 访问数组...............219 28.5 Light Userdata........220 第29章资源管理............222 29.1 目录迭代器...........222 29.2 XML解析...............225
在互联网上有很多可以下载的Lua脚本编写教程,我将为你提供一种方法来下载这些教程。首先,你可以在搜索引擎中输入“Lua脚本编写教程下载”,为了方便,你还可以添加一些关键词如“免费”、“详细”等。搜索结果中会显示很多网站或资源,你可以选择其中一种下载方式。 一种常见的下载方式是在网站上直接下载。例如,你可以找到一些IT学习网站或技术分享网站,它们通常提供各种编程教程,包括Lua脚本编写。在网站上,你可以找到适合你的能力水平的教程,并点击下载按钮。这样,你就能获取到相应的教程文件,一般是PDF或文本格式。 另外一种下载方式是通过在线教育平台。有一些在线教育平台专门提供各种编程教程,包括Lua脚本编写。你可以在这些平台上注册账号,然后搜索关于Lua脚本编写的教程。在你找到合适的教程后,你可以选择下载到你的设备上,方便随时学习。 无论你选择哪种方式进行下载,建议你在下载前先了解一下这些资源的评价和质量,确保下载到的教程详细并且适合你的学习需求。另外,如果你有编程的基础,还可以参考Lua官方网站提供的文档和教程,这些资源通常是免费提供的。 总之,通过以上方法你应该能够找到并下载到详细Lua脚本编写教程。希望这些教程能够帮助你更好地学习Lua脚本编程。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值