美文网首页Lua
【Lua】Lua基础语法

【Lua】Lua基础语法

作者: LittleFatSheep | 来源:发表于2023-03-20 00:02 被阅读0次

    1 Lua 简介

    Lua 是一个小巧的脚本语言,用标准C语言编写而成,由巴西里约热内卢天主教大学的 Roberto Ierusalimschy、Waldemar Celes 和 Luiz Henrique de Figueiredo 三人于 1993 年开发,设计目的是为了灵活嵌入应用程序,实现灵活的扩展和定制功能。

    Lua 具有以下特性:

    • 脚本语言、解释型语言
    • 嵌入程序开发
    • 容易与其他语言相互调用
    • 轻量级
    • 面向过程编程
    • 函数式编程
    • 热更新

    2 Lua 环境搭建

    1)下载 bin 包

    点击 https://luabinaries.sourceforge.net/download.html,根据系统类型下载相应 bin 文件,如:Windows 系统下载[ lua-5.4.2_Win64_bin.zip](https://sourceforge.net/projects/luabinaries/files/5.4.2/Tools Executables/lua-5.4.2_Win64_bin.zip/download),如下:

    2)解压并重命名文件

    将下载的 bin 文件解压,如笔者解压路径:D:\Program Files\Lua\bin,并将 lua54.exe 文件重命名为:lua.exe,如下:

    3)配置环境变量

    右键此电脑,依次选择【属性→高级系统设置→环境变量→系统变量→Path】,将解压的 bin 目录添加到系统环境变量 Path 中。

    4)验证环境

    在 cmd 命令行窗口输入:lua -v,如果打印了版本号,说明环境配置成功,如下:

    3 Lua 输出、输入和注释

    3.1 输出

    1)在命令行中输入 Lua 代码

    在命令行中输入 lua,回车后进入 Lua 解释器环境,再输入 print("Hello World"),运行如下:

    按 Ctrl + C 即可退出 Lua 解释器环境。

    2) 调用文件中 Lua 代码

    用记事本创建一个文件,重命名为 test.lua,编辑内容如下:

    print("Hello World")
    

    使用命令行进入 test.lua 文件所在目录,输入:lua test.lua,打印如下:

    3.2 输入

    inputStr = io.read() --运行后会等待用户输入, 按回车键结束输入
    

    3.3 注释

    1)单行注释

    --单行注释
    

    2)多行注释

    --[[
      多行注释
    ]]
    

    4 运算符

    4.1 算术运算符

    加(+)、减(-)、乘(*)、除(/)、幂(^)、取余(%)
    

    4.2 比较运算符

    小于(<)、大于(>)、小于等于(<=)、大于等于(>=)、等于(==)、不等于(~=)
    

    4.3 逻辑运算符

    与(and)、或(or)、非(not)
    a and b --如果a为false, 则返回a, 否则返回b
    a or b --如果a为true, 则返回a, 否则返回b
    not a --如果a为true, 则返回 false, 否则返回false
    

    补充:Lua 中只有 false 和 nil 为假, 其他任何值都为真,0 也为真。

    案例:

    print(1 and 2) --2
    print(0 and nil) --nil
    print(0 or 1) --0
    print(not 0) --false
    print(not nil) --true
    

    5 Lua 变量

    变量的名称必须由字母、数字或下划线字符组成,且必须以字母或下划线开头。 大写++-和小写字母是不同的,因为 Lua 区分大小写。

    5.1 数据类型

    nil --空值,所有没有使用过的变量都是 nil,nil 既是值,又是数据类型
    boolean --布尔型, 只有2个值, true和false
    number --数值类型, 相当于C语言里的double
    string --字符串
    table --关系类型
    function --函数类型
    

    获取数据类型:

    --nil     number  string  boolean
    print(type(nil), type(1), type("xxx"), type(true))
    

    5.2 变量声明与赋值

    1)全局变量与局部变量

    --声明全局变量
    a = 5
    b = true
    --声明局部变量
    local name = "zhang san"
    print(a, b, c, name) --5       true    nil     zhang san
    

    说明:nil 是 Lua 中的空值,所有没有使用过的变量都是 nil,nil 既是值,又是数据类型。

    2)一组变量赋值

    a, b, c = 1, true, "zhang san"
    print(a, b, c) --1       true    zhang san
    d, e = 2
    print(d, e) --2       nil
    f, g = 3, 4, 5
    print(f, g) --3       4
    

    3)交换变量的值

    a, b = 1, 2
    a, b = b, a
    print(a, b) --2       1
    

    6 字符串

    6.1 字符串定义

    a = "xxx"
    b = 'yyy'
    c = [["zzz"]]
    d = [['www']]
    print(a, b, c, d) --xxx     yyy     "zzz"   'www'
    

    6.2 字符串链接

    print("xxx".."yyy") --xxxyyy
    print("xxx"..123) --xxx123
    

    6.3 字符串与其他类型转换

    tonumber("123") --字符串转换为数字
    tostring(123) --其他类型数据转换为字符串
    

    6.4 字符串比较

    print("abc" > "ab") --true
    print("abc" < "ab") --false
    print("zhang" > "wang") --true
    print("zhang" < "wang") --false
    print("xyz" == "xyz") --true
    print("abc" == "xyz") --false
    

    6.5 字符串函数

    string.len(arg) --计算字符串长度
    string.upper(str) --字符串全部转为大写字母
    string.lower(str) --字符串全部转为小写字母
    string.reverse(arg) --字符串反转
    string.char(arg) --将整型数字转成字符并连接
    string.byte(arg[,int]) --转换字符为整数值(可以指定某个字符,默认第一个字符)
    --截取字符串, str: 待截取的字符串, i: 截取开始位置, j: 截取结束位置, 默认为-1, 表示最后一个位置
    string.sub(str, i [, j])
    --字符串替换, mainStr: 要操作的字符串, findStr: 要匹配的字符串, replaceStr: 替换的字符串, num: 替换次数(可以忽略,忽略后表示全部替换), return: 替换后的字符串和替换次数
    string.gsub(mainStr, findStr, replaceStr, num)
    --在str中查找subStr的, 如果找到了返回匹配的起点和终点索引, 否则返回nil
    string.find (str, subStr, [init, [end]])
    string.rep(string, n) --返回字符串string的n个拷贝
    --字符串格式转换
    string.format(...)
    

    应用:

    str = "abcdefg"
    print(string.len(str), str:len()) --7       7
    print(string.sub(str, 2, 5), str:sub(2, 5)) --bcde    bcde
    

    7 表格 table

    7.1 字典

    1)字典初始化

    tab = {
        name = "zhang san",
        age = 23,
        single = true
    }
    --zhang san       23      true    nil     nil
    print(tab["name"], tab["age"], tab.single, tab.xxx, tab[yyy])
    

    2)字典赋值

    tab = {}
    tab[0] = 1
    tab["name"] = "zhang san"
    tab.single = true
    --1       zhang san       true
    print(tab[0], tab["name"], tab.single)
    

    7.2 列表

    1)列表初始化

    tab = {1, 2, 3}
    --nil     1       2       3
    print(tab[0], tab[1], tab[2], tab[3])
    

    说明:如果不设置下标,元素从 1 开始计数。

    2)列表初始化(通过索引指定元素位置)

    tab = {
        1, 2, 3,
        [0] = "Hello",
        [10] = true
    }
    --Hello   1       2       3       true
    print(tab[0], tab[1], tab[2], tab[3], tab[10])
    

    7.3 table 常用函数

    #tab --获取数组长度
    --连接数组, 返回连接后的字符串, tab: 待连接的table, sep: 连接符(可省, 默认nil), start: 连接的起点位置(可省, 默认0), end: 连接的结束位置(可省, 默认最后一个元素位置)
    table.concat(tab, sep,  start, end)
    --插入元素, tab: 待插入的table, pos: 待插入的位置(可省, 默认最后位置), value: 插入的元素
    table.insert(tab, pos, value)
    --删除元素, tab: 待删除的table, pos: 待删除的位置
    table.remove(tab, pos)
    --待排序的table, comp: 比较函数(可省, 默认升序)
    table.sort(tab, comp)
    

    应用:

    a = {"a", "b", "c", "d", "e"}
    print(table.concat(a, ",")) --a,b,c,d,e
    function sortFunc(a, b) 
        return b < a
    end
    table.sort(a, sortFunc)
    print(table.concat(a, ":")) --e:d:c:b:a
    

    8 流程控制语句

    8.1 if 条件语句

    1)if 语句

    if conditions then
        then-part
    end
    

    2)if - else 语句

    if conditions then
        then-part
    else
        else-part
    end
    

    3)if - elseif - else 语句

    if conditions then
        then-part
    elseif conditions then
        then-part
    else
        else-part
    end
    

    8.2 循环语句

    1)for 循环语句

    --start: 起点(包含), end: 终点(包含), step: 步长或增量(可省略)
    for var = start, end, step do
        loop-part
    end
    

    2)泛型 for 循环语句

    --只打印列表元素
    for i, v in ipairs(table) do
        loop-part
    end
    
    --打印所有元素
    for k, v in pairs(table) do
        loop-part
    end
    
    案例 1:
    
    tab = {10, true, "xxx"}
    for i, v in ipairs(tab) do
        print(i, v)
    end
    --[[打印如下: 
    1       10
    2       true
    3       xxx
    ]]
    

    案例 2:

    tab = {10, true, "xxx"}
    tab[0] = "yyy"
    tab["zzz"] = 100
    for i, v in ipairs(tab) do
        print(i, v)
    end
    --[[打印如下: 
    1       10
    2       true
    3       xxx
    ]]
    

    案例 3:

    tab = {10, true, "xxx"}
    tab[0] = "yyy"
    tab["zzz"] = 100
    for k, v in pairs(tab) do
        print(k, v)
    end
    --[[打印如下: 
    1       10
    2       true
    3       xxx
    0       yyy
    zzz     100
    ]]
    

    3)while 循环语句

    while condition do
        loop-part
    end
    

    4)repeat 循环语句

    --类似C语言的do-while语句
    repeat
        loop-part
    until condition 
    

    5)break

    在循环过程中提前跳出循环,用法同C语言,如:

    for i = 1, 10, 2 do
        if i > 6 then
            break
        end
    end
    

    9 函数

    9.1 函数定义与使用

    1)函数定义

    function function_name(args)
        function-body
    end
    

    说明:Lua 函数不支持重载,对于不同参数的同名函数,只有最后一个定义的同名函数生效。

    2)函数使用

    function show(str)
        print(str)
    end
    --直接调用函数
    show("xxx") --xxx
    --可以省去括号
    show "yyy" --yyy
    --函数赋值后再调用, 类似C语言的函数指针
    func = show
    func("zzz") --zzz
    

    注意:函数调用应该放在函数声明后面,否则会报错。

    9.2 函数返回值

    Lua 支持多返回值,并且接收变量个数不一定要和函数返回参数个数一致。

    function get()
        return 1, 2, 3
    end
    --接收变量个数=返回参数个数
    a, b, c = get()
    print(a, b, c) --1       2       3
    --接收变量个数<返回参数个数
    a, b = get()
    print(a, b) --1       2
    --接收变量个数>返回参数个数
    a, b, c, d = get()
    print(a, b, c, d) --1       2       3       nil
    

    9.3 匿名函数

    func = function()
        print("anonymous function")
    end
    
    func()
    

    9.4 常用 math 函数

    --幂函数
    sqrt、pow
    --指数与对数函数
    exp、log、log10
    ldexp --如: math.ldexp(10, 3), 值为10*2^3=80
    --三角函数
    sin、cos、tan、acos、asin、atan
    --取整函数
    ceil、floor
    --最值函数
    min、max
    --双曲线函数
    cosh、sinh、tanh
    --角度与弧度转换函数
    deg、rad
    --随机函数
    random --如: math.random(1, 100), 获取1-100的随机数
    randomseed --设置随机数种子, 如: math.randomseed(os.time())
    --其他函数
    abs
    modf --把数分为整数和小数, 如: math.modf(10.12), 返回10 12
    --常量
    pi --3.1415926535898
    

    说明:使用 math 函数,都需要在前面加上 “math.”,如:math.abs(-1)。

    10 模块

    myMath.lua

    function add(a, b)
        return a + b
    end
    
    function mul(a, b)
        return a * b
    end
    

    test.lua

    require("myMath")
    
    print(add(1, 2)) --3
    print(mul(2, 3)) --6
    

    11 元表 metatable

    元表的作用主要是为了模拟面向对象特性,元表主要有 __index、__newindex、__call、__tostring 元方法。

    11.1 设置元表

    son = {}
    parent = {}
    newSon = setmetatable(son, parent)
    print(newSon == son) --true
    print(newSon == parent) --false
    

    11.2 __index 元方法

    1)__index 是个表格

    在读取子表的属性或函数时,若子表里不存在,就去元表的 __index 表里搜索,若元表也没有,就递归搜索元表的元表。

    son = {
        name = "son name",
        func = function()
            print("son func")
        end
    }
    
    parent = {
        __index = {
            name = "parent name",
            age = 23,
            func = function()
                print("parent func")
            end,
            show = function()
                print("show")
            end
        }
    }
    
    setmetatable(son, parent)
    print(son.name) --son name
    print(son.age) --23
    son.func() --son func
    son.show() --show
    

    2)__index 是个方法

    在读取子表的属性时,若子表里不存在,就调用元表的 __index 函数。

    案例一:

    son = {}
    parent = {
        __index = function()
            print("parent __index")
        end
    }
    
    setmetatable(son, parent)
    print(son.age)
    --[[打印:
    parent __index
    nil
    ]]
    

    案例二:

    son = {}
    parent = {
        __index = function(tab, key)
            print(tab, key)
        end
    }
    
    setmetatable(son, parent)
    print(son.age)
    --[[打印:
    table: 0000000000179fd0 age
    nil
    ]]
    

    11.3 __newindex 元方法

    1)__newindex 是个表格

    在修改子表的属性时,若子表里不存在,就在元表的 __newindex 表里添加该属性。

    tempTab = {}
    son = {}
    parent = {
        __newindex = tempTab
    }
    
    setmetatable(son, parent)
    son.name = "son name"
    print(son.name) --nil
    print(tempTab.name) --son name
    

    2)__newindex 是个方法

    在修改子表的属性时,若子表里不存在,就调用元表的 __newindex 函数。

    案例一:

    son = {}
    parent = {
        __newindex = function()
            print("parent __newindex")
        end
    }
    
    setmetatable(son, parent)
    son.name = "son name"
    print(son.name)
    --[[打印:
    parent __newindex
    nil
    ]]
    

    案例二:

    son = {}
    parent = {
        __newindex = function(tab, key, value)
            print(tab, key, value)
        end
    }
    
    setmetatable(son, parent)
    son.name = "zhangsan"
    print(son.name)
    --[[打印:
    table: 0000000000099cd0 name    zhangsan
    nil
    ]]
    

    11.4 __call 元方法

    在以函数形式调用子表时(如:tab()),会调用元表的 __call 函数。

    1)无参 call

    son = {}
    parent = {
        __call = function()
            print("parent __call")
        end
    }
    
    setmetatable(son, parent)
    son() --parent __call
    

    2)有参 call

    son = {}
    parent = {
        __call = function(sonTab, arg)
            print(sonTab, arg)
        end
    }
    
    setmetatable(son, parent)
    son("xxx") --table: 0000000001019c90 xxx
    

    说明:第一个参数是调用的子表。

    11.5 __tostring 元方法

    在获取子表输出内容时,会调用元表的 __tostring 函数。

    son = {10, 20, name = "zhangsan"}
    parent = {
        __tostring = function(sonTab)
            str = "{"
            for k, v in pairs(sonTab) do
                str = str..k..": "..v..", "
            end
            str = str.."}"
            return str
        end
    }
    
    setmetatable(son, parent)
    print(son) --{1: 10, 2: 20, name: zhangsan, }
    

    12 面向对象编程

    Lua 是面向过程编程语言,不支持面向对象编程,但可以使用元表模拟面向对象编程。本节将通过一个案例展示 lua 面向对象编程的写法。

    student.lua

    --使用lua模拟一个类
    
    --1、创建表格, 添加字段
    Student = {
        name = "xxx",
        age = 0,
        sex = "0"
    }
    
    --2、定义类的构造函数
    --function Student.new(self, name, age, sex)
    function Student:new(name, age, sex)
        o = {}
        setmetatable(o, self)
        self.__index = self;
        self.__tostring = function()
            return "{name: "..self.name..", age: "..self.age..", sex: "..self.sex.."}"
        end
        self.name = name
        self.age = age
        self.sex = sex
        return o
    end
    
    --3、定义类的成员方法
    --function Student.show(self)
    function Student:show()
        print(self.name, self.age, self.sex)
    end
    
    --4、定义静态字段
    Student.hair = "black"
    
    --5、定义静态方法
    function Student.showHair()
        print("hair=" .. Student.hair)
    end
    

    说明:Student:new(name, age, sex) 等价于 Student.new(self, name, age, sex),Student:show() 等价于 Student.show(self)。

    test.lua

    require("student")
    --创建Student实例
    stu = Student:new("zhang san", 23, "male")
    --调用Student的元表的tostring方法, 打印: {name: zhang san, age: 23, sex: male}
    print(stu)
    --访问stu实例的字段, 打印: zhang san       23      male
    print(stu.name, stu.age, stu.sex)
    --调用stu实例的方法, 打印: zhang san       23      male
    --stu.show(stu)
    stu:show()
    --访问Student的静态字段, 打印: black
    print(Student.hair)
    --调用Student的静态方法, 打印: hair=black
    Student.showHair()
    

    说明:stu:show() 等价于 stu.show(stu)。

    声明:本文转自【Lua】Lua基础语法

    相关文章

      网友评论

        本文标题:【Lua】Lua基础语法

        本文链接:https://www.haomeiwen.com/subject/lhcurdtx.html