文章目录
零、前言
小盆友从今天开始会不定时分享一些 Lua 学习笔记,还是老规矩文章会结合代码,讲解会融入自己的理解和工作中遇到的问题。
但毕竟是基础使用和语言性的使用,所以会少一些趣味性,话不多说,就从现在开始吧。
一、注释
1-1、单行注释
-- xxxx
1-2、多行注释
标准的多行注释如下
--[[
多行注释
多行注释
]]
但是建议使用如下注释
--[[
被注释的代码
--]]
因为这样只要在第一个注释中加多一个 -
即可打开被注释的代码
---[[
被注释的代码(会被执行)
--]]
因为 ---[[ --]]
这样的格式不满足多行注释,所以被解释为各自一行注释,所以最后一行需要多写两个 --
二、标识符
- 最好不要使用下划线加大写字母的标示符,因为 Lua 的保留字也是这样的,避免冲突。
- Lua 是一个区分大小写的编程语言,所以
and
是保留字,但And
和AND
却可用。
三、全局变量
- 在默认情况下,变量总是认为是全局的。
- 全局变量不需要声明,给一个变量赋值后即创建了这个全局变量,访问一个没有初始化的全局变量也不会出错,只不过得到的结果是:nil。
print(b) --> nil
b = 10
print(b) --> 10
- 通过将变量赋值为 nil,进行删除一个变量,Lua 会进行回收该变量所占用的内存
b = 10
print(b) --> 10
b = nil
print(b) --> nil
当且仅当一个变量不等于 nil 时,这个变量即存在。
四、数据类型
Lua 是一个动态类型语言,不存在类型定义,值带有自身的类型信息。
4-1、类型
数据类型 | 描述 |
---|---|
nil | 只有值 nil 属于该类,表示一个无效值(在条件表达式中相当于false)。 |
boolean | 包含两个值: false 和 true 。 |
number | 表示双精度类型的浮点数和整型 |
string | 字符串由一对双引号或单引号来表示 |
function | 由 C 或 Lua 编写的函数 |
userdata | 表示任意存储在变量中的 C 数据结构 |
thread | 表示执行的独立线路,用于执行协同程序 |
table | 表,是一个"关联数组"(associative arrays),数组的索引可以是数字、字符串或表类型。 |
具体每项的使用和特征会在后面的文章分享。
4-2、获取类型
通过 type
获取具体的类型,返回的是字符串
print("nil",type(nil)) --> nil nil
print("boolean",type(true)) --> boolean boolean
print("number",type(3)) --> number number
print("string",type("jiangpengyong")) --> string string
print("function",type(print)) --> function function
print("table",type({})) --> table table
五、作用域
- 全部直接申明变量均为全局变量
- 局部变量需要使用
local
进行声明
应该尽可能的使用局部变量,有三个好处:
- 避免命名冲突。
- 访问局部变量的速度比全局变量更快。
- 垃圾收集器能够更快的释放无用局部变量,因为局部变量随着其所在的作用域结束而消失。
举个例子:
-- 这里会无限循环
x = 10
local i = 1 -- 对于代码段(所在文件)来说是局部的
while x <= 10 do -- 此处 x 使用的是全局变量
local x = i * 2 -- 此处 x 对于循环体来说是局部的
print(x) --> 2,4,6,8 ..
i = i + 1
end
局部变量的生效范围限于代码块内部,代码块指的是:
- 控制结构主体
- 函数主体
- 代码段(变量被声明时所在的文件或字符串)
5-1、在交互模式中作用域
在交互模式中,每一行代码就是一个代码段(除非不是一条完整的命令)
以上面的代码为例,一旦输入示例的第二行(local i = 1), Lua 语言解释器就会直接运行他并在下一行开始一个新的代码段。这样,局部的声明就超出了原来的作用范围。
5-2、自定一个作用域 do-end
很多时候我们在一个代码段中(例如控制语句,函数体内),自然会有一个作用域,但是如果在一串连续的代码中,想增加一个作用域,则使用 do-end
。
可以通过 do-end
声明一个作用域,这样 local 的变量一旦出了 do-end
就作废了
do
local name = "jiang peng yong"
print(name) --> jiang peng yong
end
print(name) --> nil
5-3、全局变量的检查
对于全局变量和局部变量,其实最好的做法是使用前先声明,这样表明自己想要的变量的定位。
可以借助 strict.lua 检查全局变量,如果试图在一个函数中对不存在的全局变量赋值或者使用不存在的全局变量,则会抛出异常
--- 添加 strict 模块(后续文章会分享)
package.path = package.path .. ";/Users/jiangpengyong/Desktop/code/Lua/lua_study_2022/1 基础语法/?.lua"
require "strict"
name = "jiangpengyong"
print(name)
--- age 没有进行声明初始化,则运行会报错
--- age = nil
print(age )
结果如下,因为 age
没有声明,所以报错了。
5-4、全局变量转局部变量
将全局变量转为局部量的好处:
- 提高访问速度
- 隔离局部的改变影响到全局(动态替换时很有用)
age = 20
do
-- 将 age 转为局部变量
local age = age
print(age) --> 20
age = 10
print(age) --> 10
end
print(age) --> 20
六、循环语句
条件表达式 condition 的结果可以是任意值 ,所有 false 和 nil 会被当作 false,其余会被当作 true(包括数值 0 和空字符串)
6-1、while 循环
while (condition) do
statements
end
6-2、for 循环
6-2-1、数值型 for
for var= exp1,exp2,exp3 do
<执行体>
end
var 从 exp1 变化到 exp2 之前,会先执行一次 "执行体”,然后以 exp3 为步长增加到 var,exp3 是可选的,如果不指定,默认为 1。 如果不想有上限可以用 math.huge
(数值最大值)作为上限。
值得注意
- 循环开始前,三个表达式(exp1,exp2,exp3)都会运行一次
- 控制变量是被 for 语句自动声明的局部变量,且其作用范围仅限于循环体内
for i = 1, 5 do
print("for", i)
end
-- i 已经超出作用域
print("i", i)
--> for 1
--> for 2
--> for 3
--> for 4
--> for 5
--> i nil
6-2-2、泛型 for
类似 java 中的 foreach 语句,使用 ipairs
i 是数组索引值,v 是对应索引的数组元素值
a = {"one", "two", "three"}
for i, v in ipairs(a) do
print(i, v)
end
pairs 与 ipairs 区别
- pairs 能迭代所有键值对。
- ipairs 可以想象成 int + pairs,只会迭代键为数字的键值对,而且在遇到 nil 时就停住。
a = { "one", "two", nil, "three" }
for i, v in ipairs(a) do
print(i, v)
end
--> 1 one
--> 2 two
for i, v in pairs(a) do
print(i, v)
end
--> 1 one
--> 2 two
--> 4 three
6-3、repeat-until 循环
相当于 kotlin\java 中的 do-while ,至少会运行一次循环体,直到循环体条件为真时结束。
repeat
statements
until( condition )
循环体内声明的局部变量的作用域包括测试条件
repeat
local i = io.stdin:read("n")
print("input number", i)
until i == nil
七、if 语句
if ( 布尔表达式 1) then
--[ 在布尔表达式 1 为 true 时执行该语句块 --]
elseif ( 布尔表达式 2) then
--[ 在布尔表达式 2 为 true 时执行该语句块 --]
elseif ( 布尔表达式 3) then
--[ 在布尔表达式 3 为 true 时执行该语句块 --]
else
--[ 如果以上布尔表达式都不为 true 则执行该语句块 --]
end
Lua 中不支持 switch 语句,所以只能用 if-else
值得注意
Lua 将所有不是 false
和 nil
的值当作真(包括 0 和空字符串都会当作真)
八、goto
声明标签格式 ::name::
, 在使用的地方调用 goto name
在 lua 中没有 continue 语句,所以如果需要的话,可以考虑使用 goto 语句实现
i = 10
while i > 0 do
i = i - 1
if i == 5 then
goto continue
end
print("goto", i)
:: continue ::
end
九、关系符号
不等于使用 ~=
, 不是 !=
非操作用 not
,相当于 !
十、写在最后
Lua 项目地址:Github传送门 (如果对你有所帮助或喜欢的话,赏个star吧,码字不易,请多多支持)
本章相关代码传送门
如果觉得本篇博文对你有所启发或是解决了困惑,给个赞或关注我呀,小盆友会继续分享更多的优质文章。