Lua學習筆記
阿新 • • 發佈:2018-12-19
最近準備把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() --更加完善與常用的方法的呼叫方式