Lua基础入门

本文对Lua的基础知识做一些简介,帮助读者入门。

一、基本变量

Lua的最常见变量类型有:nil,number,string,boolean。

和python类似,Lua也是一种弱类型的语言。变量的类型可以随意更改,不会报错。

和很多编程语言不同,在Lua里,即使该变量从未被声明和初始化,调用它也不会出错,只是会返回nil。

lua 复制代码
b = 4.5
c = "I love bad muslim"
d = true
print("a=", a) --even if a non-existing variable is called, no error is triggered. Just give nil
print("b=", b) --just number, no int or double
print("c=", c) 
print("d=", d)

print("type of a is ", type(a))
print("type of b is ", type(b))
print("type of c is ", type(c))
print("type of d is ", type(d))

输出:

复制代码
a= nil
b= 4.5
c= I love bad muslim
d= true
type of a is  nil
type of b is  number
type of c is  string
type of d is  boolean

变量a未被声明或初始化,所以类型是nil。如果想要返回它的值,也是nil。

另外,通过type函数返回的变量的类型是string(字符串)。

lua 复制代码
print("type of type is ", type(type(a)))

输出:

复制代码
type of type is  string

二、Lua的常见操作符

Lua里的+,-,*,/,^等常见数学运算符,和大多数编程语言类似,但Lua里没有+=或者++等写法。另外Lua不需要分号结束句子。

以下是Lua中常见的和其他编程语言不同的操作符:

1、注释

Lua注释的前缀是--

lua 复制代码
-- The following does not run

2、不等号

Lua里表示"不等于"的符号是~=,和Matlab一样。

lua 复制代码
neq = 4~=3
print('neq')

输出:

复制代码
true

3、字符串连接

Lua里,连接两个字符串,使用..

lua 复制代码
ssconcat = "Tom's best friend is ".."Jerry"

输出:

复制代码
Tom's best friend is Jerry

4、字符串长度

Lua里求字符串长度可以在变量前面加#

lua 复制代码
print("length of c is ", #c)

输出:

复制代码
length of c is  17

5、字符串的拼接

字符串的拼接和很多编程语言类似,用%s%d放在要插入字符的地方。使用函数string.format(),按照以下格式进行字符串拼接。

lua 复制代码
ssformat = string.format("Both %d and %d are even number", 4, 6)

输出

复制代码
formatted string: Both 4 and 6 are even number

6、代码块

和C++,Java的{},Python的缩进不同,Lua的代码块表示和Matlab比较类似,也以if,while等表示开始,end表示代码块结束。具体在后面几章会详述。

三、分支结构

Lua的if语句的格式是if ... elseif ... else ... end

lua 复制代码
g = 4
if g == 4 then
    print("g=4")
elseif g == 7 then
    print("g=7")
else
    print("neither")
end

Lua里没有switch ... case ...的语句

四、循环结构

Lua里有固定次数的for循环,也有条件循环。

1、for循环

for循环,可以让一个变量从起始值到终点值逐步增加。步长默认唯一,也可自定义。

句法为for ... do ... end

lua 复制代码
for i = 2,5 do --from 2 to 5 step 1. Both start and end are included
    print("i=",i)
end

以上语句是i从2到5,步长为1的for循环。

注意:和python的range()不同,lua里,最大值和最小值都包括。

所以输出是:

复制代码
i= 2
i= 3
i= 4
i= 5

也可以步数不为1,例如:

lua 复制代码
for j = 3,12,3 do --from 3 to 12 step 3
    print("j=",j)
end

以上语句是i从3到12,步数为3的循环。

输出是:

复制代码
j= 3
j= 6
j= 9
j= 12

2、while循环

while循环是一种"当循环"结构,表明在符合某条件时执行循环。

句法为while ... do ... end。

lua 复制代码
num = 0
while num < 5 do
    print("num=",num)
    num = num + 1 --Don't use num += 1 or num++
end

该语句表示当num < 5时执行循环。

3、repeat循环

repeat循环是一种"知道循环"结构,表明在符合某条件时退出循环。

句法为repeat ... until ...。注意这里不需要end。

lua 复制代码
repeat
    print("num=",num)
    num = num - 1
until num < 0

该语句表示当num < 0时退出循环。

五、函数

1、函数的定义

Lua中的函数也是一个变量,类似Swift里的closure(闭包)。

有两种定义函数的方式:

第一种:

lua 复制代码
function F1()
    print("This is function F1")
end

第二种:

lua 复制代码
F2 = function()
    print("This is function F2")
end

注意,F1可以被当成一个变量。现在运行下列语句:

lua 复制代码
F1D = F1

此时函数F1D()F1()一模一样。

2、函数的输入和输出

同样,函数很多时候是需要有输入和输出的。

下面构建一个有4个输入,4个输出的函数:

lua 复制代码
function getEachVariablePlus1(v1, v2, v3, v4) --a function can have multiple inputs and also multiple outputs
    if type(v1) == "number" then
        out_v1 = v1 + 1
    end
    if type(v2) == "number" then
        out_v2 = v2 + 1
    end
    if type(v3) == "number" then
        out_v3 = v3 + 1
    end
    if type(v4) == "number" then
        out_v4 = v4 + 1
    end
    return out_v1, out_v2, out_v3, out_v4

现在运行这个函数:

lua 复制代码
a, b, c, d = getEachVariablePlus1(3,13,23,"nn")
print(string.format("values of a, b, c, d are %s, %s, %s, %s", a, b, c, d))

显然,v4的类型不是number,所以out_v4不会被赋值。因此,out_v4的输出值为nil。

复制代码
values of a, b, c, d are 4, 14, 24, nil

那么,如果一个函数没有输出,我把函数输出赋予一个变量,Python,Matlab,C++,Java等都会出错。那么在Lua中呢?

lua 复制代码
rF1 = F1()
print("The return of F1 is ", rF1)

答案是不会。既然F1()无输出,rF1就被赋予nil。

复制代码
The return of F1 is  nil

同样,如果函数的实际输入参数个数超过了定义的个数,运行时也不会报错。

lua 复制代码
getEachVariablePlus1(4,6,1,3,8)

最后一个输入8就会被忽略。

如果我函数有多个输出,我只要前几个输出呢?

lua 复制代码
aq, bq = getEachVariablePlus1(4,6,1,3)

此时函数的前两个输出out_v1out_v2分别被赋予aqbq。另外两个输出被舍弃。

那我想要后几个输出呢?答案是把前几个输出用_代替。

lua 复制代码
_, _, cq, dq = getEachVariablePlus1(4,6,1,3)

此时,函数的后两个输出out_v3out_v4分别被赋予cqdq

不过,如果把函数的运行结果直接放入print,将会打印函数的所有输出

lua 复制代码
print("return of the function is ", getEachVariablePlus1(4,6,1,3))

输出:

复制代码
return of the function is  5 7 2 4

3、函数输出函数

不像在C++中函数定义不允许嵌套,在Lua以及Swift等,函数也可以输出另一个函数。

lua 复制代码
calculator = function(operator)
    if operator == '+' then
        return function(a,b)
            return a+b
            end
    elseif operator == '-' then
        return function(a,b)
            return a-b
            end
    else
        return function()
            end
    end
end

这个函数返回的也是一个函数。

lua 复制代码
getCalc = calculator('t')
print("getCalc(2,3)=", getCalc(2,3))

输出:

复制代码
getCalc(2,3)=

因为getCalc是由calculator函数里的分支结构里依据第三种情况给出的,是没有输出的函数,所以getCalc(2,3)是nil。

4、局部变量和全局变量

和大多数常见编程语言不同,Lua中的变量,在没有特别说明时,都是全局变量。

lua 复制代码
function loc()
    gbv = 10
end
loc()
print("gbv, which is a global variable, is now ", gbv)

在该函数中,gbv是全局变量。所以尽管loc()已经运行完毕,gbv仍然存在,且值为10

复制代码
gbv, which is a global variable, is now  10

但,可以通过关键字local,规定一个变量是局部变量

lua 复制代码
function loc2()
    local lcv = 10
end
loc2()
print("lcv, which is a local variable, is now", lcv)

在该函数中,以local为前缀的lcv是局部变量。一旦loc2()运行完毕,lcv就不再存在,成为nil。

复制代码
lcv, which is a local variable, is now  nil

六、表

在Lua中,表和Python的list一样,每个元素的类型不一定要相同。

Lua中的表用大括号表示。

lua 复制代码
tab1 = {"Good", 30, nil, "tg", true, nil}

1、表的长度

和字符串类似,表的长度也可用#。

注意:这个用#算出的长度,不包括最后的nil

lua 复制代码
print("the length of tab1 is ", #tab1)

输出:

复制代码
the length of tab1 is  5

显然,只计到第五个true为止。

2、表的元素提取

和Python,C++,Swift不同,在Lua中,表的默认索引值和Matlab类似,以1开头。

lua 复制代码
print("element 2 of tab1 is", tab1[2]) --in Lua, table index starts from 1
print("element 10 of tab1 is", tab1[10]) --even it is out of index, no error will be triggered, just return nil

输出:

复制代码
element 2 of tab1 is 30
element 10 of tab1 is nil

同样,索引号为10时,虽然超出了表的长度,但不会报错,只返回nil。

3、表的自定义索引

除了Lua给每个元素自动赋予的从1开始的索引值外,也可以自行给元素赋予数字或非数字索引。

lua 复制代码
Tom = {['job']="sales", ["age"]=45, [5]="really?"}

这里,表Tom有三个索引:'job''age'5。这个表有些类似Python、Swift里的字典。

根据非数字索引提取元素的方式有两种:Tom['job']或者Tom.job,两者等价。但是根据数字索引提取元素的方式只有一种:Tom[5]

lua 复制代码
print("Tom's job is ", Tom["job"], " and his age is ", Tom.age, " and 5 element is ", Tom[5]) --even the index is string '5', still can not use dot to get element

输出:

复制代码
Tom's job is  sales  and his age is  45  and 5 element is  really?

4、更改或添加或删除元素

更改元素

更改元素的方法:Tom.age=50

添加元素

添加元素的方法也类似,可以理解为把一个索引对应的元素的值从nil改为非nil值。

如果想附加一个元素到最后一个索引后面,使用table.insert(Tom, 'China')

删除元素

删除元素,如果是依据数字索引值,请用table.remove(Tom, 1),移除第一个元素;也可以用Tom[1] = nil,效果一致。如果是依据非数字索引值,只能用Tom['age'] = nil

如果运行table.remove(Tom, 'age')则会出错!

5、遍历表中元素

有两种方法遍历表中元素

pairs

pairs函数遍历表中所有的非nil元素。输出索引及其对应的元素。

lua 复制代码
Linda = {[1] = 'ele1', ['age'] = 20, ['e']=nil}
for i,v in pairs(Linda) do
    print('the element ', i, ' of Linda is ', v)
end

输出:

复制代码
the element  1  of Linda is  ele1
the element  age  of Linda is  20

ipairs

ipairs只遍历索引为数字的元素,从1开始,出现元素值为nil的就停止。

lua 复制代码
Linda = {[1] = "ele1", ['age'] = 20, ['e']=nil}
for i,v in ipairs(Linda) do
    print('the element ', i, ' of Linda is ', v)
end

输出:

复制代码
the element  1  of Linda is  ele1

6、一个Lua自带的表

Lua自带了一个表叫_G。该表包括所有已加载的元素。

lua 复制代码
function hello()
    print("Hello Lua")
end

for i,v in pairs(_G) do
    print(i,v)
    end

输出:

复制代码
pairs function: 0x1006ad9ac
select function: 0x1006addac
rawset function: 0x1006add50
print function: 0x1006b63d8
rawget function: 0x1006add00
__lua_objc userdata: 0x140bcbe60
os table: 0x15a60b140
io table: 0x15a60b080
string table: 0x15a60b180
coroutine table: 0x15a60b000
package table: 0x15a60ae00
ipairs function: 0x1006ad774
table table: 0x15a60b040
pcall function: 0x1006ada40
warn function: 0x1006adb8c
loadfile function: 0x1006ad7c8
require function: 0x157b77000
hello function: 0x157b762e0
debug table: 0x15a60b2c0
utf8 table: 0x15a60b280
getmetatable function: 0x1006ad71c
math table: 0x15a60b200
collectgarbage function: 0x1006ad444
type function: 0x1006ae180
rawlen function: 0x1006adc9c
dofile function: 0x1006b64c4
next function: 0x1006ad954
rawequal function: 0x1006adc4c
assert function: 0x1006ad3c4
tostring function: 0x1006ae148
load function: 0x1006ad84c
error function: 0x1006ad6a0
setmetatable function: 0x1006ade68
tonumber function: 0x1006adf0c
_VERSION Lua 5.4
_G table: 0x15a60a580
xpcall function: 0x1006ae1e4
相关推荐
码云骑士43 分钟前
29-Python-logging日志模块-print不是日志的生产级实战
开发语言·python
WWW65261 小时前
代码随想录 打卡第五十八天
开发语言·c++·算法
少司府1 小时前
C++基础入门:_stack_queue 底层奥秘
开发语言·数据结构·c++·栈和队列·queue·stack
Cheng小攸1 小时前
协议分析与分析工具(二)
开发语言·php
z_鑫1 小时前
深入理解MyBatis:collection集合封装的底层原理与实现细节
java·开发语言·数据库·spring boot·mybatis
贺国亚1 小时前
06-奢侈零售VIP-Clienteling-Agent
开发语言·python·零售
我命由我123451 小时前
Android 开发问题:获取到的 Android ID 发生了变化
android·java·开发语言·java-ee·android studio·android jetpack·android runtime
nix.gnehc1 小时前
Python 内存管理深度解析
开发语言·python
码上有光1 小时前
c++: AVL树
开发语言·c++·avl树