欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Lua学习笔记

程序员文章站 2022-03-14 11:00:01
...

最近准备把lua应用到之前写过的Unity项目中,所以先学一下Lua,在这里做点笔记,自己没事翻翻看就好。

lua学习记录

lua的变量类型 nil string number boolean  table(“表”,lua的面向对象由表实现) function userdata thread(表示执行的独立线程,本质是伪“多线程”,是协程的概念,用于执行协同程序)

判断语句短路规则

真&&假   假
假&&真   假
num1&&num2  num2

真||假   真
假||真   真
num1||num2  num1

多重赋值  num1,num2,num3 = 10,20,30

在语句块中添加local才是局部变量
eg.
 do
   local num = 1 (局部变量)
 end

ipairs与pairs迭代器

ipairs迭代数组、遍历顺序集合,遇到nil就会中断
pairs迭代表、遍历集合中的所有数据
使用pairs关键字,循环输出数据、字符串类型时,for中必须使用k、v,循环中的k、v可以是任何字母或者合法的标识符代替

lua标准库提供的迭代器
A.迭代文件每行的io.lines
B.迭代table的pairs
C.迭代数组元素得的ipairs
D.迭代字符串中单词的string.gmatch


lua函数function
函数格式
function function_name( ... )
	-- body
end

lua函数的性质
1.函数无需定义返回类型,可以返回任意类型与任意数量的数值
2.函数的参数,无需定义参数类型
3.函数无需大括号
4.可以定义变量,把函数直接赋值给它,从而获得相同功能(类似与C#的委托)

eg.
1.不带返回值 
function func1(a)

end
2.带返回值
function func2( a,b)
	return a+b
end
3.函数赋值给变量 
func3 = func2
--因为func2有返回值
result1 = func3(20,30)
print(""..result1)

warning:定义函数  函数中由于函数没有参数类型,所以在没有(编译)运行前,计算机是无法发现错误的,这对比其他编译语言是一个明显的弱点


local关键字,全局与局部变量
lua规定,默认变量都是全局变量(无论是否定义在语句块中),局部变量需要在代码块中用local修饰
eg.
function func4(  )
	gNum1 = 10         --全局变量num1
	local num2 = 20   --使用local定义局部变量num2   
end

fun4()
print(gNum1)    --输出10
print(num2)     --报错无法输出,num2是nil值

在函数中定义全局变量,在函数外照样可以访问
函数可以声明为全局的与局部的,默认是全局的
eg.
local function locFunc( ... )
	-- body
end	
local函数不能被别的lua文件调用,类似于类中的private方法

函数的多返回值
可以返回多个任意不同类型的数值
eg.
function GetNumb( ... )
	return 10,20,30,(40)
end
res1,res2,res3,(res4)  = GetNumb()
函数的多返回值性质:
1.如果一个函数调用在最后,或者仅有一个表达式,lua回保留尽可能多的返回数值用于匹配
2.如果一个函数没有返回值,或者没有足够多的返回值,那么lua会用nul来补充缺失数值

函数可以作为数据进行赋值,也可以作为参数进行传递(类似于C#的委托)
函数作为参数进行传递
eg.
function PrintInfo( res )
	print("")
	print(res)
end
function AddNum(num1,num2,printFunc)
	local result = num1+num2
    printFunc(result)
end

匿名函数
定义:没有函数名称的函数
一个没有名称的函数,只有通过赋值给一个变量(相当于C#的委托注册方法),通过调用这个函数变量来间接调用这个匿名函数
定义的时候,无需定义函数名称,但是一定要把匿名函数赋值给变量
eg.
hideFunc = function (num1,num2)
	--匿名函数
	print(num1+num2)
end

hideFunc(66,88) --调用匿名函数,本质是调用的是匿名函数赋值给的变量

Lua字符串

字符串的下标从1开始

字符串的三种表示方式
str1= "   "
str2= '   '
str3=[[   ]]   --适合大量字符串
str4="   '  '  "  --可以在双引号里面带单引号
str5='  "   "   '--单引号里面可以带双引号

string.len(str1)  --使用字符串函数,输出字符串长度
#str2      --使用#符号,输出字符串长度

转义字符串
常用的,回车 \r   换行 \n    反斜杠 \\     双引号 ""

字符串常用函数
A:字符串长度len()、大小写函数upper()、lower()
string.len(str)
string.upper(str)
string.lower(str)

B:查找函数find()
string.find(s,pattern,init,plain)
findPos = string.find(str,"a")   --str是搜索的源字符串,"a"表示搜索关键字
findPos = string.find(str,"a",5) --"5"参数表示从下标5的位置开始搜索

C:截取函数 sub()
string.sub(s,i,j) --s是源字符串,i是选择截取字符串的位置,j是截取j个字符
strSubResult = string.sub("HelloWorld",1,3)
strSubResult = string.sub("朋友们好,Hello!",1,4)  --汉字是两个占位符

D:字符串替换函数 gsub()
strGSubResult = string.gsub(s,pattern,repl,n) --s源字符串,pattern关键字,repl替换后的关键字,n

E:字符串反转 reverse()
strReverseResult = string.reverse(s)  --s源字符串
--> abcd  ==> dcba

F:格式化字符串 format()

传统输出多个变量的长字符串,使用“拼接”的方式
eg.
num1,num2,num3 = 10,20,30
--输出三个变量相加的结果
print("加法:num1:"..num1.." +num2"..num2.." +num3:"..num3.." result="..num1+num2+num3)

访问数据库的开发
print("select 列名? from 表明? where id = ?查询条件? and ...")  --查询数据库的语句

--简化以上长字符串中添加多个变量问题的写法,lua提供了“字符串格式化”函数
eg.
--%d 表示一个数值型变量
--%s 表示一个字符串变量
string.format()
strFormatResult = string.format(formatstring:"使用字符串格式化:num1: %d+num2: %d+num3: %d = result: %d",num1,num2,num3,num1+num2+num3)   --formatstring需要格式化的字符串

表
 Table是lua的一种数据结构,用来帮助我们创建不同的数据类型,如数组、键值对集合等。。

表的特征与定义
lua(数组)的下标可以是负数,lua的长度可以动态改变(与C#的固定长度数组不同),可以把lua数组认为是C#的List、dictionary等集合类型
把Table当成一个"字典"集合来对待,也可以当成一个"数组"来对待,这要看如何初始化表

Table集合,可以有“空表”,“直接声明且定义表内容”,“声明表然后逐一赋值”三种方式
Table集合,也可以定义成类似“数组”的定义方式,其访问可以使用下标进行访问(但是lua没有数组概念,用表来表示)
访问table中的数据(键值对集合),可以直接用“.”访问,也可以用中括号访问,但一定要加字符串,否则会报错
Table中的索引都是由1开始的

tabMyArray = {}    --定义表
print(tabMyArray)   --输出表的地址
--定义数组类型的表
tabMyArray1 = {11,111,333}   --相当于数组
print(tabMyArray1[1])  --使用下标,进行表的内容输出 
print(tabMyArray1[2])
print(tabMyArray1[3])
--下标是从1开始的   要是tabMyArray1[0] 则会输出nil

--定义键值对类型的表
tabMyArray3 = {str1="aaa",str2="bbb",str3="ccc"}
--输出键值对类型的表
--两种不同的输出方式
1.使用中括号输出
print(tabMyArray3["str1"]) --输出信息
2.使用“.”输出,类似于C#中输出属性
print(tabMyArray3.str2)
print(tabMyArray3.str3)

表的赋值与迭代输出
1.空表的赋值与迭代输出 --空表要赋值才能输出
2.字典类型表的赋值与迭代输出
3.关于表变量的相互赋值的技术(引用传递)

lua中的table相当于c#中的字典类集合(具备key/value键值对的数据结构)
lua表的遍历方式
[table.getn();表示集合中的数量,即集合中最大索引]
for i =1,table.getn(mytable) do 
	...
end

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

tabMyArray4 = {10,20,30,54,40}
--使用for输出  
for i =1 ,4 do
	print(tabMyArray4[i])
end
--使用table函数或者符号输出
for i =1 ,#tabMyArray4 do    --使用“#”符号,来得到表中的数量
	print(tabMyArray4[i])
end

for i=1 , table.getn(tabMyArray4) do    --使用表函数table.getn(tableName),得到表中的数量
	print(tabMyArray4[i])
end

--使用迭代输出(键值对类型)
tabMyArray5= {str1="aaa",str2="bbb",str3="ccc"}
tabMyArray5.str4 = "ddd"
tabMyArray5["str5"] = "eee"
--输出
for i =1,5 do --需要注意,getn和 # 只能用于数组,键值对还是需要给定长度   
	print(tabMyArray5["str"..i])   --不常用也不实用
end

使用迭代器函数 pairs / ipairs 输出连续与非连序(键值对)数值
 --输出顺序不能保证
 tabMyArray6 = {str1="aaa",str2="bbb",str3="ccc"}   
 for k,v in pairs(tabMyArray6) do
 	print(k,v)   --k键   v值   --key value
 end

 一般数组类型的集合可以只输出v,即只输出数据,但是 k,v还是必须的。
 tabMyArray7={"aa","bbb","c"}
 for k,v in ipairs(tabMyArray7) do
 	print(v)
 end

 表的函数

 table.getn():得到表(数组型)的长度
tab1= {"aa","bbb","c"}
得到表的长度   # 和table.getn都可以都可以得到数组型表的长度
eg.
print(#tab1)
print(table.getn(tab1))


 table.concat():高效率的对于字符串链接的一种方式
 eg.
 tab2 = {"aa","bbb","c"}
 str2 = table.concat(tab2)
 print("str2="..str2)   --print : str2=aabbbc
 str3 = table.concat(tab2,"|")   --添加分隔符
 print("str3="..str3)   --print : str2=aa|bbb|c
 str4 = table.concat(tab2,"|",2,3)   --指定序号内容字符串 2到3
 print("str4="..str4)   --print : str2=bbb|c

 table.insert(t,pos,value)  --t表,pos位置,value值
eg.
tab3 = {"Hell","Every"}
table.insert(tab3,2,"o ")
print(table.concat( tab3))   --print : Hello Every

tab4 = {"同学","大家好"}
table.insert(tab4,2,"们,")
print(table.concat( tab4))   --print : 同学们,大家好


 table.remove()
 tab5 = {"Hello ","Everyone","OK"}
 table.remove(tab5)    --函数默认移除最后的字符串序号
  print(table.concat( tab5))   --print :Hello Everyone
  table.remove(tab5,2)   --这样就把Everyone删除了
 print(table.concat( tab5))    --print :Hello OK

table.sort() 表的排序方法
needSortTable = {10,32,21,54,97,84,32,45,8}
table.sort( needSortTable )   --升序排列
--输出查看
for i =1,table.getn(needSortTable) do
	print(needSortTable[i])
end
--字符串排序
needSortStrTable = {"river","sky","Cave","好","World"}
table.sort(needSortStrTable)
for i=1,table.getn(needSortStrTable) do 
	print(needSortStrTable[i])  --print :Cave World river sky 好   顺序是大写 小写 中文
end

得到表中最大数值 lua 5.1好像有bug
table.maxn() 得到表中的最大正数索引值,返回的是key值
 tabMaxAarry = {10,32,21,54,97,84,32,45,8}
nMaxNum = table.maxn(tabMaxAarry)
print("表中最大数值 = "..nMaxNum)

寻找最大值函数
---输入:tableName,表类型变量 (如果不合法则输出nil)
---输出:表中的最大值key值,以及对应的value
function GetTableMaxNumb(tableName)
	--建议在函数块内使用局部变量
	local returnMaxNumber = nil   --返回最大数值

	--参数检查
	if(type(tableName)~="table") then    --type()返回值是个字符串
		print("error table")
		return nil
	end

	for k,v in pairs(table) do		
	--给returnMaxNumber变量赋予初始数值
		if(returenMaxNumber ==nil) then
			returnMaxNumber = v
		end
		--取得表中得最大数值
		if(v>returnMaxNumber) then
			returnMaxNumber = v
		end
	end

	return returnMaxNumber
end

resultMaxNum = GetTableMaxNumb(tabMaxAarry)

if(resultMaxNum~=nil) then
	print(resultMaxNum)
else
	print("nil")
end

表资源的释放
使用nil对表(字符串、基本其他数据类型)资源作释放
给整个table赋值nil,则表示销毁整个表,清空内存

tabMaxAarry = nil --释放变量资源
resultMaxNum = nil 

lua模拟面向对象编程
OOP三大特性,封装,继承,多态
封装:指能够把一个实体的信息、功能、响应都装入一个单独的对象中的特性
继承:继承的方法允许在不改动源程序的基础上对其进行扩充,这样使得原功能得以保存,而新功能也得以扩展。有利于减少重复编码,提高软件的开发效率
多态:同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果

lua的语法没有面向对象机制
lua中使用Table实现面向对象机制。把table模拟成一个“类”来使用。

其实lua的string(math、random)等就可以看成面向对象的特殊表

定义表的字段与方法
tableName.field 定义表的字段与方法使用
tableName.methodName()定义表的字段与方法
定义表的第二种方式,匿名方法赋值给表字段

eg.  --定义一个空表,相当于一个OOP编程中得“类”
Person = {}

--定义字段  
Person.Name = "陈治翰"
Person.Gender = "男"
Person.Weight = 51
Person.Height = 173
--定义方法   
Person.Speak = function ( ) ---第一种定义方式  匿名函数
	print("人在说话")
end

function Person.Walking()   --第二种定义方式  常用的定义方法
	print("人在走路")
end

--在方法中调用信息 传统定义方式
Person.ShowInfo = function (  )   
	print("调用个人信息")
	print("身高"..Person.Height)   --记得要加Person
	print("体重"..Person.Weight)
	Person.Speak()
	person.Walking()
end
--在方法中调用信息 改进函数定义方式使用局部变量
--引入this变量
local this = Person
Person.ShowInfo = function (  )   
	print("调用个人信息")
	print("身高"..this.Height)   --记得要加Person
	print("体重"..this.Weight)
	this.Speak()
	this.Walking()
end



调用表中"字段"与"方法"
--调用字段
print(Person.Name)   --print :陈治翰
print(Person.Gender) --print :男
print(Person.Weight) --print :51
print(Person.Height) --print :173

--调用方法
Person.Speak()
Person.Walking()

--提高函数的灵活性
a=Person   --把Person表复制给a 变量
a.ShowInfo()  --也可以执行的

Person=nil   --把Person销毁了
a.ShowInfo()  --会报错,Person是空对象
--要是定义了local this = Person
a.ShowInfo()  --正常执行了

表字段的缺陷
定义局部表引用变量,降低方法引用表字段的耦合性  --使用self关键字 就可以不使用局部变量了

在lua中,可以认为定义的Person表,Person是一个指针,那么定义的Person表的内容在内存的其他区域。当Person赋值给a,就相当于又定义了一个a指针,就相当于有a、Person两个指针指向Person的内容,
当Person = nil 只是把Person这个指针销毁了,但是Person中的内容还在。在销毁之前,使用a获取Person的内容,则需要定义一个其他局部变量,相当于第三个指针,该指针指向Person的内容。但是在Person表中,
需要用第三个指针调用Person的字段和函数

使用self关键字完善方法定义和调用方式
使用self关键字,直接在方法中引用表自身的字段与方法
--在方法中调用信息 继续改进函数定义方式使用局部变量(配合函数使用“冒号”定义函数)
--使用自带的self关键字
function Person:Show( )
	print("调用个人信息")
	print("身高"..self.Height)   --记得要加Person
	print("体重"..self.Weight)
	self.Speak()
	self.Walking()
end
--调用
Person:Show()  --更加完善与常用的方法的调用方式



相关标签: Lua