0%

Lua快速入门

什么是Lua

Lua 是一门强大、快速、轻量的嵌入式脚本语言。它由巴西里约热内卢 Pontifical Catholic 大学的 PUC-Rio 团队 开发。 Lua 是一个 自由软件, 广泛应用于世界上无数产品和项目

应用场景:

  • 游戏开发
  • 独立应用脚本
  • Web 应用脚本
  • 扩展和数据库插件如:MySQL Proxy 和 MySQL WorkBench
  • 安全系统,如入侵检测系统

基本语法

注释

  • 单行注释:两个减号是单行注释
  • 多行注释:
1
2
3
4
5
6
-- 这是一个单行注释

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

标识符

Lua表示符用于定义一个变量,函数获取其他用户定义的项。标示符以一个字母 A 到 Z 或 a 到 z 或下划线 _ 开头后加上0个或多个字母、下划线、数字(0到9)。最好不要使用下划线加大写字母的标示符,因为Lua的保留字也是这样的。Lua 不允许使用特殊字符如 @, $, 和 % 来定义标示符。 Lua 是一个区分大小写的编程语言。因此在 Lua 中 W3c 与 w3c 是两个不同的标示符

关键字

1
2
3
4
and       break     do          else      elseif    end
false for function goto if in
local nil not or repeat return
then true until while

数据类型

  • nil:只有值nil属于该类,表示一个无效值(在条件表达式中相当于false)
  • boolean:包含两个值:false和true
  • number:有两种内部表现方式,整数和浮点数。标准Lua使用 64 位整数和双精度
    (64位)浮点数
  • string:string表示一个不可变的字节序列,由一对双引号或单引号来表示
  • function:由C或Lua编写的函数
  • userdata:表示任意存储在变量中的C数据结构
  • thread:表示执行的独立线路,用于执行协同程序
  • table:Lua 中的表(table)其实是一个”关联数组”(associative arrays),这个数组不仅仅以数字做索引,除了nil和NaN之外的所有Lua值都可以做索引。 (Not a Number是一个特殊的数字,它用于表示未定义或表示不了的运算结果,比如 0/0),也就是说,表内可以包含任何类型的值( nil 除外)。任何键的值若为nil 就不会被记入表结构内部。table的创建是通过”构造表达式”来完成,最简单构造表达式是{},用来创建一个空表

表、函数、线程、以及完全用户数据在 Lua 中被称为 对象: 变量并不真的持有 它们的值,而仅保存了对这些对象的引用。赋值、参数传递、函数返回,都是针对引用而不是针对值的操作

我们可以使用type函数测试给定变量或者值的类型:

1
2
3
4
5
6
7
print(type("Hello world"))      --> string
print(type(10.4*3)) --> number
print(type(print)) --> function
print(type(type)) --> function
print(type(true)) --> boolean
print(type(nil)) --> nil
print(type(type(X))) --> string

变量

变量类型

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

除非用local显示声明为局部变量,否则Lua中的变量全是全局变量,哪怕是语句块或是函数里。
局部变量的作用域为从声明位置开始到所在语句块结束。
变量的默认值均为 nil。

应该尽可能的使用局部变量,有两个好处:

  • 避免命名冲突
  • 访问局部变量的速度比全局变量更快
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
-- test.lua 文件脚本
a = 5 -- 全局变量
local b = 5 -- 局部变量

function joke()
c = 5 -- 全局变量
local d = 6 -- 局部变量
end

joke()
print(c,d) --> 5 nil

do
local a = 6 -- 局部变量
b = 6 -- 全局变量
print(a,b); --> 6 6
end

print(a,b) --> 5 6

赋值语句

赋值是改变一个变量的值和改变表域的最基本的方法

1
2
a = "hello" .. "world" --字符串拼接
t.n = t.n + 1

Lua可以对多个变量同时赋值,变量列表和值列表的各个元素用逗号分开,赋值语句右边的值会依次赋给左边的变量

1
a, b = 10, 2*x       <-->       a=10; b=2*x

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

1
2
x, y = y, x                     -- swap 'x' for 'y'
a[i], a[j] = a[j], a[i] -- swap 'a[i]' for 'a[j]'

当变量个数和值的个数不一致时,Lua会一直以变量个数为基础采取以下策略:

  • 变量个数 > 值的个数: 按变量个数补足nil
  • 变量个数 < 值的个数: 多余的值会被忽略
1
2
3
4
5
6
7
8
a, b, c = 0, 1
print(a,b,c) --> 0 1 nil

a, b = a+1, b+1, b+2 -- value of b+2 is ignored
print(a,b) --> 1 2

a, b, c = 0
print(a,b,c) --> 0 nil nil

多值赋值经常用来交换变量,或将函数调用返回给变量:

1
a, b = f()     -- f()返回两个值,第一个赋给a,第二个赋给b

循环

while

基本语法:

1
2
3
4
5
6
7
8
9
10
11
12
while(condition)
do
statements
end

-- 举例
a=10
while( a < 20 )
do
print("a 的值为:", a)
a = a+1
end

for循环

数值for循环:

1
2
3
4
5
6
7
8
9
10
11
12
13
-- var从exp1变化到exp2,每次变化以exp3为步长递增var,并执行一次"执行体"。exp3是可选的,如果不指定,默认为1
for var=exp1,exp2,exp3 do
<执行体>
end

--举例
for i=1, f(5) do --f(x)只在循环开始前求值一次
print(i)
end

for i=10, 1, -1 do
print(i)
end

泛型for循环

1
2
3
for K, v in pairs/ipairs(table) do
print(v)
end

根据官方手册的描述,pairs会遍历表中所有的key-value值,而ipairs会根据key的数值从1开始加1递增遍历对应的table[i]值,直到table[i]的值是nil的时候就退出。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
stars = {[1] = "Sun", [2] = "Moon", [5] = 'Earth'}

for i, v in pairs(stars) do
print(i, v)
end
--[[
输出:
1 Sun
2 Moon
5 Earth
--]]

for i, v in ipairs(stars) do
print(i, v)
end
--[[
输出:
1 Sun
2 Moon
因为stars[3]是nil
--]]

repeat…until 循环

repeat…until 是条件后行,所以repeat…until 的循环体里面至少要运行一次
基本语法:

1
2
3
repeat
statements
while( condition )
1
2
3
4
5
6
7
--[ 变量定义 --]
a = 10
--[ 执行循环 --]
repeat
print("a的值为:", a)
a = a + 1
until( a > 15 )

输出结果

1
2
3
4
5
6
a的值为:	10
a的值为: 11
a的值为: 12
a的值为: 13
a的值为: 14
a的值为: 15

流程控制

基本语法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
if( 布尔表达式 1)
then
--[ 在布尔表达式 1 为 true 时执行该语句块 --]

elseif( 布尔表达式 2)
then
--[ 在布尔表达式 2 为 true 时执行该语句块 --]

elseif( 布尔表达式 3)
then
--[ 在布尔表达式 3 为 true 时执行该语句块 --]
else
--[ 如果以上布尔表达式都不为 true 则执行该语句块 --]
end

函数

基本使用

在Lua中,函数是对语句和表达式进行抽象的主要方法。既可以用来处理一些特殊的工作,也可以用来计算一些值。

Lua 函数主要有两种用途:

  • 完成指定的任务,这种情况下函数作为调用语句使用
  • 计算并返回值,这种情况下函数作为赋值语句的表达式使用

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

1
2
3
4
optional_function_scope function function_name( argument1, argument2, argument3..., argumentn)
function_body
return result_params_comma_separated
end
  • optional_function_scope:该参数是可选的制定函数是全局函数还是局部函数,未设置该参数末尾为全局函数,如果你需要设置函数为局部函数需要使用关键字 local
  • function_name:函数名称
  • 函数参数:多个参数以逗号隔开,函数也可以不带参数
  • 函数返回值:Lua语言函数可以返回多个值,每个值以逗号隔开

Lua中,函数是first class,我们可以将函数作为参数传递给函数,如下实例:

1
2
3
4
5
6
7
8
9
10
11
12
myprint = function(param)
print("这是打印函数 - ##",param,"##")
end

function add(num1,num2,functionPrint)
result = num1 + num2
-- 调用传递的函数参数
functionPrint(result)
end

-- myprint 函数作为参数传递
add(2,5,myprint)

多返回值

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function maximum (a)
local mi = 1 -- 最大值索引
local m = a[mi] -- 最大值
for i,val in ipairs(a) do
if val > m then
mi = i
m = val
end
end
return m, mi
end

value, key = maximum({8,10,23,12,5})
print(key) --输出3
print(value) --输出23

可变参数

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

Lua将函数的参数放在一个叫arg的表中,#arg 表示传入参数的个数
例如,我们计算几个数的平均值:

1
2
3
4
5
6
7
8
9
10
function average(...)
result = 0
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))

运算符

算术运算符

image_1arcmmj32ich15tbi15ht016ko9.png-28kB

关系运算符

image_1arcmnu3be3q1nk71nfo1d1ls24m.png-39.8kB

逻辑运算符

image_1arcmp39u3e012rs8bu1vk3vfe13.png-26.5kB

其他运算符

image_1arcmpptot0s1a611bqd13s21b431g.png-18.5kB

运算符优先级

1
2
3
4
5
6
7
8
^
not - (unary)
* /
+ -
..
< > <= >= ~= ==
and
or

table

不同于其他语言的数组把 0 作为数组的初始索引,在 Lua 里表的默认初始索引一般以 1 开始
在 Lua 里,table 的创建是通过”构造表达式”来完成,最简单构造表达式是{},用来创建一个空表。也可以在表里添加一些数据,直接初始化表:

1
2
3
4
5
6
7
8
9
10
-- 创建一个空的 table
local tbl1 = {}

-- 直接初始表
local tbl2 = {"apple", "pear", "orange", "grape"}

-- 初始化的时候设置key,注意,key不需要带引号,且初始化的时候不能以数字作为key
local tbl2 = {apple = "apple", pear = "pear", orange = "orange", grape = "grape"}

--可以通过table[i]、table['key']、table.key的方式访问数据

Lua 中的表(table)其实是一个”关联数组”(associative arrays),数组的索引可以是数字或者是字符串:

1
2
3
4
5
6
7
8
a = {}
a["key"] = "value"
key = 10
a[key] = 22
a[key] = a[key] + 11
for k, v in pairs(a) do
print(k .. " : " .. v)
end
chenhang wechat