Lua学习笔记
好久没有更新博客,在这里,我将记载一些我学习到的lua的编程知识,希望能对看到的朋友有所帮助。
一. lua的介绍
这里引用自百度百科
Lua[1] 是一个小巧的脚本语言。是巴西里约热内卢天主教大学(Pontifical Catholic University of Rio de Janeiro)里的一个研究小组,由Roberto Ierusalimschy、Waldemar Celes 和 Luiz Henrique de Figueiredo所组成并于1993年开发。其设计目的是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能。Lua由标准C编写而成,几乎在所有操作系统和平台上都可以编译,运行。Lua并没有提供强大的库,这是由它的定位决定的。所以Lua不适合作为开发独立应用程序的语言。Lua 有一个同时进行的JIT项目,提供在特定平台上的即时编译功能。
开始正式学习
1. lua中语句结尾分号可加可不加
2. lua中的单行注释是—
3. 多行注释--[[ --]],多加一个-可以直接取消掉注释
4. Lua不推荐下划线加上大写字母,因为这是Lua的保留字,Lua是一个区分大小写的语言,保留关键字不能作为标识符,当然一般标识符会在编译器里高亮显示
5. Lua中的变量都默认是全局变量,lua中有一个nil,如果你给一个变量赋值为nil,那么就相当于它是不存在的,我们经常用这种方式来销毁一个变量或者表中的变量
6. Lua和c#第一个区别,c#通常是先提供一个类,然后定义静态接口来实现方法,而lua则是直接在脚本里面书写方法运行,不需要定义类
7. Lua里面的type函数,你可以给它传递一个值,返回传值的数据类型,
语法类似;print(type(“hello world”)
8. Lua中的Boolean只有两种类型,true和false,false和nil被视为假,其他都被视为是真
9. 我们可以用[[ ]]来表示多行字符串
10. Lua中使用..来进行字符串连接
11. Lua中使用#来计算字符串长度
12. Lua中要进行数字运算的时候,会尝试将数字运算符变成number类型进行运算
13. E是科学计数法,比如e2就是10的2次方运算
14. Lua中表和遍历的写法:
其实在lua中字符串,多行字符串都是以表的形式存在,比如这里我写一个表
tab3={“apple”,”banana”,”orange”,”potato”}
然后我们要输出这个表,可以直接
Print(tab3)
要遍历这个表,可以
For key,val in pairs(tab3) do
Print(key..”:”..val)
End
这里pairs是一个返回键值对的方法,对应key和val,然后我们就可以通过这个for循环进行循环遍历输出了
15. lua中的table本身是不设最大长度的,如果想要插入和替换数值,直接用=号就可以,如果要删除表中某个数据或者删除整个表,用nil就行
16. lua中的function不需要定义类型也可以进行使用,你的数值类型和你约定好的类型对应,比如这里写一个简单的阶乘函数,比如我们这里定义了一个n是Int类型,那么它就返回数字类型的,而不用提前定义
function add(n)
if n=1;
then return n;
else
returnn*add(n-1)
这里,我们Print(add(3)),就会输出6了
17. 在lua中,我们可以将一个函数当初一个方法去进行传递
比如这里
tab1={key1=”val1”,key2=”val2”};
我们定义了一个tab,然后我们这样相当于传递一个table和一个fi方法,然后用f1对它进行处理
Function f(tab1,f1)
for k,v inpairs(tab1)
do
f1(k,v)
end
end
然后我们写一下f1的方法
Function fi(k,v)
Print(k..”:”..v)
end
这样上面就会遍历tab1然后调用f1方法了
如果我们再写个f2来输出kv中间带空格,那么可以直接
Function f2(k,v)
Print(k..” ”..v)
end
f(tab1,f2)直接调用这个方法即可
18,如果我们只想要一个函数运行一遍,后面不再使用,并且这个函数很简短,那么可以用匿名函数,这里我们就不用定义函数的名字了
F(tab1,
Function (k,v)
Print(k..”:”..v)
End
)
18. 关于局部变量与全局变量
局部变量会在所在语句块执行完后会被销毁,而全局变量不会。在Lua中数据的类型是可以随时发生改变的。我可以用do end作为区分创建出一个子的代码块出来,在lua中,局部变量相比全局变量要更节省性能,因此一般我们都选取局部变量.
如果在一个代码块内,会优先调用最近定义的变量
19. 关于lua中的多变量赋值
在Lua中,我们可以同时给多个值进行赋值
比如: a,b=10,20 这样的话,我们就可以给a赋值为10,b赋值为20,在lua中,多变量的赋值是先将右边的计算完,再依次赋值到左边
比如这里我们写 a,b=b,a 这样就相当于我们把a,b的值进行了互换,我们再输出a,b的时候,获得的就是20,10
如果我们写a,b,c=20,10的话,这个数量不够的值,比如c,我们就会默认给它赋值为nil
我们可以从方法内获取值
比如 Function test()
Return 10,20
End
a=test()
然后我们输出a,得到的就是前面的10,如果是a,b=test(),就可以接受方法内的所有值了
20. lua中的while循环的语法体
while(condition)
do
statement
end
比如这里我们想要输出一个1到20的数字
a=0
While(a<=20)
do
a=a+1
print(a)
end
21. lua中的for循环体和repeat,until循环体
for循环体的结构是
for var=start,end,step do
循环体
End
这里start是开始值,end是结束值,step是每次循环的间隔
比如这里
for i=1,10,2 do
print(i);
end
这里就是输出1,3,5,7,9执行五次,间隔是2
这里for循环也可以对结构体进行循环
比如table1={key1=”value1”,key2=”value2”}
我们要循环输出键值对
For k,v in pairs(table1) do
Print(k,v)
end
repeat,until循环体是重复执行某个循环,直到什么的时候终止
比如这里 我们想要输出1到10,就可以这么写
a=1
repeat
a=a+1
print(a)
until(a>10)
循环嵌套的写法
这里我们想要循环输出i的值并且根据数值大小输出相应数量,就可u循环嵌套这么写
For i=1,10 do
For j=i do
Print (i)
End
End
22. lua中if语句的写法,这类和c#中的多重嵌套语句写法类似
if 布尔表达式 then
为true时候执行的语句
End
If 布尔表达式
Then
为true 时候执行的语句
Else
为false时执行的语句
End
23. lua中的函数可以作为参数传递,也可以返回多个函数值
24. lua中函数可以传递多个参数
比如这里我们定义了一个计算平均值的函数,我们需要先定义一个局部的arg,它会根据索引返回它内部的数值 ,然后我们再用pair取得它的键值对,最后用#arg就可以获得你传递参数的数量,这样就可以计算平均值了
functionaverageRes(...)
localarg={...};
res=0
for k,vin pairs(arg) do
res=res+v;
end
print(res/#arg)
end
averageRes(10,20)
25lua中的逻辑运算符和关系运算符
关系运算符
下表列出了 Lua 语言中的常用关系运算符,设定 A 的值为10,B 的值为 20:
操作符 |
描述 |
实例 |
== |
等于,检测两个值是否相等,相等返回 true,否则返回 false |
(A == B) 为 false。 |
~= |
不等于,检测两个值是否相等,相等返回 false,否则返回 true |
(A ~= B) 为 true。 |
> |
大于,如果左边的值大于右边的值,返回 true,否则返回 false |
(A > B) 为 false。 |
< |
小于,如果左边的值大于右边的值,返回 false,否则返回 true |
(A < B) 为 true。 |
>= |
大于等于,如果左边的值大于等于右边的值,返回 true,否则返回 false |
(A >= B) 返回 false。 |
<= |
小于等于,如果左边的值小于等于右边的值,返回 true,否则返回 false |
(A <= B) 返回 true。 |
实例
我们可以通过以下实例来更加透彻的理解关系运算符的应用:
a =21
b =10
if( a == b )
then
print("Line 1 - a 等于 b")
else
print("Line 1 - a 不等于 b")
end
if( a ~= b )
then
print("Line 2 - a 不等于 b")
else
print("Line 2 - a 等于 b")
end
if( a < b )
then
print("Line 3 - a 小于 b")
else
print("Line 3 - a 大于等于 b")
end
if( a > b )
then
print("Line 4 - a 大于 b")
else
print("Line 5 - a 小于等于 b")
end
--修改 a 和 b 的值
a =5
b =20
if( a <= b )
then
print("Line 5 - a 小于等于 b")
end
if( b >= a )
then
print("Line 6 - b 大于等于 a")
end
以上程序执行结果为:
Line1- a 不等于 b
Line2- a 不等于 b
Line3- a 大于等于 b
Line4- a 大于 b
Line5- a 小于等于 b
Line6- b 大于等于 a
逻辑运算符
下表列出了 Lua 语言中的常用逻辑运算符,设定 A 的值为 true,B 的值为 false:
操作符 |
描述 |
实例 |
and |
逻辑与操作符。若 A 为 false,则返回 A,否则返回 B。 |
(A and B) 为 false。 |
or |
逻辑或操作符。若 A 为 true,则返回 A,否则返回 B。 |
(A or B) 为 true。 |
not |
逻辑非操作符。与逻辑运算结果相反,如果条件为 true,逻辑非为 false。 |
25. 字符串的一些基本操作
String.format:这个我们可以用来对字符串进行格式化输出,比如 在我们进行sql查询的时候就可以用到
String.format(select * from student where username=”%s”,password=”%s”,shwdjhws,273289)
还有类似string.upper把字符串变成大写,string.reverse将字符串倒置,string.find对字符串进行检索
26. lua中索引一般默认从1开始,并且数组的索引可以为负数
27. lua中的两种迭代器,pairs,ipairs,都是从索引一开始遍历整个数组,区别在于ipairs的遍历如果遇到nil就会停止
28. lua中的table可以进行置空操作
29. 关于table的一些基本操作
1. 拼接,table.concat可以拼接字符串
比如 table1={“lua”,”c#”,”c++”}
这里我们就可以table.concat(table1)对它进行拼接,后面的参数还可以指定拼接的连接符,拼接的开始索引和结束索引
2. 插入 table的插入我们可以用table.insert进行插入,后面指定表名和索引和内容就可以插入
Eg:table.insert(table1,2,”javascrpits)
3. 删除,我们可以删除指定索引的内容,这里插入和删除后,索引都会自动重新组拼连续
Eg,table.remove(table1,2)就可以删除table1中2号索引的数据
30lua中我们可以定义一个模块module类似于c#中的类和lua中的table,我们可以在其中定义一些方法和变量,然后在外界进行调用
这里我们定义了一个module
Eg: module={};
Module.var=”haha”;
Module.functionfuc1
Print(“哈哈”)
End
Renturn module
然后我们要引用这个模块,就可以通过
Rquire “module”
Print (module.var)
这种方法来访问模块中的变量
30. lua中可以通过引入c包来解决一些比较复杂的操作
31. lua中的元表可以扩充普通表的行为,我们可以通过下面两个方法来设置元表
setmetatable()
getmetatable()
一个是获取普通表然后设置给元表
一个是获得元表
32.__metatable可以用来限制外界访问和修改元表中的数值
33.元表的一个作用
__newindex,当我们对表的数据进行修改时候,也就是添加新的索引或者是添加新的键值对时候,就会触发这个方法,如果跟着函数就会触发函数,如果跟的是表,修改的新输出就会放在表里面
34.元表的加法扩展
我们想要对两个table进行加法,我们只需要给其中一个表设置元表,然后用到元表中的__add这个对元表进行加法扩展
Eg: newtable={“1”,”2”};
Newt={“3,”4”}
Setmetatable(newtable,metastable)
Metatable={
__add=new function(tab,mytable)
Local mi=0
For k,v in pairs(table)
do
If(k>mi)then
Mi=k
End
End
For k,v in(mytable) do
Mi=mi+1
Table.insert(tab,mi,v)
End
Return tab
}
V2=newtable=newt
Print(v2)
这样,就实现了加法的运算
35.当我们想要对一个表当成函数一样调用的时候,我们可以用
__call对它进行扩展,比如上面的元表,我们添加一个
__call=function(tab,arg)
Print(arg)
End
这样的话,我们就可以对表进行类似
Mytable(34)这样的操作了
36.当我们想修改表的输出方式,可以用
__tostring 修改输出方式
37.lua中我们可以将一个函数转变成为协程函数,这样我们可以在需要的时候将它重载,不需要的时候将它挂起
38.这里我们先介绍如何开启一个协同程序,这里我们创建的函数一定要是匿名函数
Co=coroutine.creat(
Function (a,b)
Print (a+b)
end
)
Coroutine.resume(co,20,50)这里参数第一个表明调用的函数,第二第三是传递给函数的值,这样,就可以开启一个协程
暂停协同是
Coroutine.yield
继续也是
Coroutine.resume,但是不用传递参数,这个方法的返回值首先是返回true和false,这些是用来判断协程是否成功执行的
39.file=io.open(“文件路径”,”r”)
这个表示开始读取一个文件并且以只读的形式打开,这返回一个值
Io.input(file)
Print(io.read())//这个会读取一行,直到读取完就会输出nil
Io.close(file)代表读取的结束
39.我们想要修改一个文件的内部信息
用io.open(“haha.txt”,”a”)这个表示以只写的模式打开文件,如果存在就会在尾部追加,如果不存在就会重新创建
后面是io.open(“haha.txt”,”w”)也是只写,但是如果是已存在的文件,会对其进行清空
Io.output表示告诉文件我要开始写入
Io.write(”想要写入的字符串”)这个表示写入一行数据
Io.read可以读取文件内部的文件,更多读取方式可以自行百度
40.在lua中,当我们通过.来调用方法的时候,我们需要给它传递第一个参数来传递当前的方法
我们使用冒号来调用时,里面定义的self会自动传递它的值
41.Lua中面向对象我们是如何创建新对象并且继承原来的属性
Person={name=”wenxue”,age=”23”}
FunctionPerson:eat
Print(self.name+”在吃饭”
End
这里我们创建一个新表,可以对原有的方法基础上进行修改,并且还不会影响原有表的值
FunctionPerson:new
T={}
Setmeattable(T,__index) --这里当我们查找的属性在t中不存在,会自动寻找__index所指定的表
Return t
End
Person1=Person:new
Person1.name=”wenxueshaonian”
Person:eat()—这里我们调用也是通过冒号调用
42.lua中的继承比较好实现
Stduent=Person:new;
这样就可以继承new这个方法了
然后我们也可以对这个方法自行扩展,比如
Student.grade=1
这样就行