【Lua】Lua基础语法

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,如下:

        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.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

表格 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)。

猜你喜欢

转载自blog.csdn.net/m0_37602827/article/details/128323611