lua的起源
lua是Roberto Ierusalimschy、Luiz Henrique de Figueiredo 和 Waldemar Celes在1993年創建的一門輕量的可嵌入的快速的腳本語言,其功能非常強大,是以C語言編寫的開源語言。lua本身的目的是爲嵌入應用程序爲應用程序提供靈活的擴展和定製功能。
Lua特性
- 腳本語言------解釋型語言
- 嵌入程序開發
- 易與其他語言相互調用
- 輕量
- 面向過程
- 函數式編程
- 熱更新
安裝Lua
下載地址:http://luabinaries.sourceforge.net/download.html
推薦的編寫工具:sublime、VSCode、babelua等等
安裝完成後不要忘記配置環境變量
在系統環境變量中的Path中加入
要把路徑換成你自己lua所安裝的路徑。
執行lua腳本方法:打開CMD,進入lua腳本所在文件夾,使用命令:lua xxxxx.lua即可運行腳本。
lua語法
一、註釋
單行註釋:–註釋內容
多行註釋:–[[ 註釋內容 ]]
二、變量聲明
Lua 變量有三種類型:全局變量、局部變量、表中的域。
Lua 中的變量全是全局變量,那怕是語句塊或是函數裏,除非用 local 顯式聲明爲局部變量。
局部變量的作用域爲從聲明位置開始到所在語句塊結束。
變量的默認值均爲 nil(即相當於C#等語言中的null)。
例:全局變量聲明
- 單變量:name = “xiaowang”
- 多變量:name,age = “xiaowang”,18
局部變量聲明 - 單變量:local age = 23
- 多變量:local name,age = “xiaowang”,20
注:聲明變量時,不需要指定數據類型;語句結束也不需要分號;
三、運算符
1.算數運算符:加(+)、減(-)、乘(*)、除(/)、冪(^)、取餘(%)(不多說)
2.比較運算符:⼩於(<)、⼤於(>)、⼩於等於(<=)、⼤於等於(>=)、等於等於(==)、不等於(~=)(不多說)
3.邏輯運算符:
- 與(and)、或(or)、⾮(not)
- 注意邏輯運算結果:
- a and b - - 如果a爲false,則返回a,否則返回b
a or b - - 如果a爲true,則返回a,否則返回b
not a - -如果a爲true,則返回false,否則返回true
注:邏輯運算中只有nil和false視爲假,其它都爲真,0也爲真
4.連接運算符:…兩個點
例:print("hello " … “world”) ------》 hello world
四、數據類型
- nil:表示空值,所有沒有使⽤過的變量都是nil;nil既是值,⼜是數據類型
- boolean:布爾類型,只有兩個有效的值:true和false
- number:數值類型,在Lua⾥,相當於C語⾔⾥的double
- string:字符串,如果願意的話,字符串是可以包含"\0"字符的
- table:關係類型,這個類型的功能⽐較強⼤
- function:函數類型,可以由函數類型來聲明變量
五、關係類型詳解
- table = {}------初始化表
- table[0] =4------指定值
- table[“name”] = “⽼王”
- table[“son”] = {name=“北京”,gender=“男”}
- table = nil------移除應用,lua垃圾回收釋放內存
table 是 Lua 的一種數據結構用來幫助我們創建不同的數據類型,如:數組、字典等。Lua table 使用關聯型數組,你可以用任意類型的值來作數組的索引,但這個值不能是 nil。Lua table 是不固定大小的,你可以根據自己需要進行擴容。Lua也是通過table來解決模塊(module)、包(package)和對象(Object)的。 例如string.format表示使用"format"來索引table string。
- Table嵌套:table =
{
10,–相當於[1] = 10
[100] = 110,
person = {
name = “Albert”,
age = 80,
},
20–相當於[2] = 20
}
六、賦值語句
- 變量個數>值的個數 —> 按變量個數補⾜nil
- 變量個數<值的個數 —> 多餘的值會被忽略
如下例:
• a , b = 10 , 2x <—> a = 10 ; b = 2x ;
• a , b , c = 0 , 1 —> 0 1 nil
• a , b = a + 1 , b + 1 , b + 2 —> 1 2
• a , b , c = 0 —> 0 nil nil
• a , b = f() —> f()返回兩個值,第⼀個賦給a,第⼆個賦給b
還有個特殊的賦值操作
• a , b = b , a <—> swap(x,y);
• a[i] , a[j] = a[j] , a[i] <—> swap(a[i],a[j]);
是的,Lua可以直接通過以上方式交換兩個變量的值
七、if語句
-
語法:
1.第⼀種形式:
if conditions then
then-part
end2.第⼆種形式:
if conditions then
then-part
else else -part
end;3.第三種形式:
if conditions then
then-part
elseif conditions then
elseif-part
…
else
else-part
end;
例:
a = io.read()
if a==“m” then
print(“man”)
elseif a==“w” then
print(“women”)
else
end
if語句常見練習:
•輸⼊⼀個年份,判斷該年份是否
是閏年?如果是閏年,則輸出該年是
閏年,否則輸出該年不是閏年。
•提示:
•閏年:能被400整除,或者能被
4整除但是不能被100整除。
實現:
year = io.read()
if tonumber(year)%400 == 0 or (tonumber(year)%4 == 0 and tonumber(year)%100 ~=0) then
print("yes")
else
print("no")
end
八、for語句
- 語法:
for var=exp1,exp2,exp3 do
loop-part
end
exp1是起點(包含),exp2是終點(包含),exp3 增量(可省略,省略時表示每次自增1) - 例:
for i=1,10,2 do
print(i)
end
練習:
求1到100內的質數之和。
實現:
sum = 0
for i=2,100,1 do
flag = true
for j=2,i/2,1 do
if i%j ==0 then
flag = false
end
end
if flag then
print(i)
sum = sum + i
end
end
print(sum)
九、while循環語句
- 語法:
while condition do
statements
end
例:
while i < 100 do
print(i)
i = i + 2
end
練習:
編寫程序實現功能,計算100⾄10000之間有多少個數其各位數字之和是7.(例如241:2+4+1=7) 。
實現:
i = 100
count = 0
while i < 10000 do
quyu = 1000
sum = 0
temp = i
while temp > 9 do
dange = (temp - temp%quyu)/quyu
temp = temp%quyu
if temp < 10 then
sum = sum + temp
end
sum = sum + dange
quyu = quyu/10
end
i = i + 1
if sum == 7 then
count = count + 1
print(i-1)
end
end
print(count
十、repeat語句
- 語法:
repeat
statements;
until conditions;
例:
i = 0
repeat
print(i)
i = i +1
until i > 10
十一、範型for語句
- 語法:
- – print all values of array ‘a’
for i,v in ipairs(a) do print(v) end
– print all keys of table ‘t’
for k in pairs(t) do print(k) end
區別:ipairs遇到第⼀個nil跳出循環
十二、break語句
emmm…這個沒什麼好說的,就是用來跳出循環的嘛
例:
ocal i = 1
while a[i] do
if a[i] == v then break end
i=i+1
end
十三、函數
在Lua中,函數是對語句和表達式進行抽象的主要方法。既可以用來處理一些特殊的工作,也可以用來計算一些值。
Lua 提供了許多的內建函數,你可以很方便的在程序中調用它們,如print()函數可以將傳入的參數打印在控制檯上。
Lua 函數主要有兩種用途:
1.完成指定的任務,這種情況下函數作爲調用語句使用;
2.計算並返回值,這種情況下函數作爲賦值語句的表達式使用。
- 語法:
function func_name (argumentslist)
statements-list;
end; - 調用:
括號可省略
print(“HelloWorld”) <—>print “HelloWorld” - 形參實參匹配
function f(a, b) return a or b end
CALL PARAMETERS
f(3) ------a=3, b=nil
f(3, 4) – a=3, b=4
f(3,4,5) -a=3,b=4 (5 is discarded)
注意:Lua不支持重載!
Lua支持多返回值:
function maximum (a)
local mi = 1 -- maximum index
local m = a[mi] -- maximum value
for i,val in ipairs(a) do
if val > m then
mi = i
m = val
end
end
return m, mi
end
print(maximum({8,10,23,12,5})) --> 23 3
十四、Lua模擬面向對象
模塊
模塊類似於一個封裝庫,從 Lua 5.1 開始,Lua 加入了標準的模塊管理機制,可以把一些公用的代碼放在一個文件裏,以 API
接口的形式在其他地方調用,有利於代碼的重用和降低代碼耦合度。Lua 的模塊是由變量、函數等已知元素組成的 table,因此創建一個模塊很簡單,就是創建一個
table,然後把需要導出的常量、函數放入其中,最後返回這個 table 就行。
-
創建模塊
1.xxx.lua
2.aaa={}
2.1.aaa.name=“A”
2.2.function aaa.show(){return “I am A”}
3.bbb={}
3.1.bbb.name=“b”
3.2.function bbb.show(){return “I am B”} -
使用模塊
-
Lua提供了一個名爲require的函數用來加載模塊。要加載一個模塊,只需要簡單地調用就可以了。
require(“模塊名”) ---------require(“xxx”)
元表(metatable)
在 Lua table 中我們可以訪問對應的key來得到value值,但是卻無法對兩個 table 進行操作。
因此 Lua 提供了元表(Metatable),允許我們改變table的行爲,每個行爲關聯了對應的元方法。
例如,使用元表我們可以定義Lua如何計算兩個table的相加操作a+b。
當Lua試圖對兩個表進行相加時,先檢查兩者之一是否有元表,之後檢查是否有一個叫"__add"的字段,若找到,則調用對應的值。"__add"等即時字段,其對應的值(往往是一個函數或是table)就是"元方法"。
有兩個很重要的函數來處理元表:
- 設置元表:setmetatable(table,metatable) 返回值爲tabl,對table設置元表metatable
- 獲取元表:getmetatable(table) 返回值爲metatable,獲取table的元表
元⽅法
__index (讀)
- 如果__index是個表格:⼦表沒有的字段,搜索元表;若搜不到,遞歸搜索元表的元表…
這是 metatable 最常用的鍵。
當你通過鍵來訪問 table 的時候,如果這個鍵沒有值,那麼Lua就會尋找該table的metatable(假定有metatable)中的__index 鍵。如果__index包含一個表格,Lua會在表格中查找相應的鍵。
例:
son = {}
parent = {
__index = {
name = "laowang",
func = function ()
print("show")
end
}
}
setmetatable(son, parent)
print(son.name)
son.func()
-如果 __index是個⽅法:⼦表沒有的字段,調⽤元表__index⽅法,並以表格和字段爲參數
__index 元方法查看錶中元素是否存在,如果不存在,返回結果爲 nil;如果存在則由 __index 返回結果。
__index總結
Lua 查找一個表元素時的規則,其實就是如下 3 個步驟:
1.在表中查找,如果找到,返回該元素,找不到則繼續
2.判斷該表是否有元表,如果沒有元表,返回 nil,有元表則繼續。
3.判斷元表有沒有 __index 方法,如果 __index 方法爲 nil,則返回 nil;如果 __index 方法是一個表,則重複 1、2、3; 如果 __index 方法是一個函數,則返回該函數的返回值。
該部分內容來自作者寰子:https://blog.csdn.net/xocoder/article/details/9028347
例:
son={}
parent={__index = function
(tb,key)
-- body
if key == "name" then
-- body
return "laowang"
else
return "null variable"
end
end
}
setmetatable(son,parent)
print(son.name)
__newindex(寫)
- 如果__newindex是⼀個表格:在設置值時,⼦表沒有的新字段,會在元表的__newindex表格中添加該新字段
例:
tb = {}
newtb = {}
setmetatable(tb,{__newindex =
newtb})
tb.name = "xiaozhang"
print(tb.name)
print(newtb.name)
以上實例中表設置了元方法 __newindex,在對新索引鍵(tb.name)賦值時(tb.name = “xiaozhang”),會調用元方法,而不進行賦值。而如果對已存在的索引鍵,則會進行賦值,而不調用元方法 __newindex。
- 如果__newindex是⼀個⽅法:在設置值時,⼦表沒有的新字段,會調⽤元表的__newindex⽅法,並會以表格、字段、值作爲參數
例:
son = {name = "xiaowang"}
parent = { __newindex =
function (tb,key,value)
if key == "age" then
print(key,value)
end
end
}
setmetatable(son,parent)
son.name = "xiaozhang"
son.age = "18"
還有兩個方法__call、__tostring就不細說了,讀者可以自行查閱API,大差不差。
十五、LUA面向對象編程
我們知道,對象由屬性和方法組成。LUA中最基本的結構是table,所以需要用table來描述對象的屬性。
lua 中的 function 可以用來表示方法。那麼LUA中的類可以通過 table + function 模擬出來。
至於繼承,可以通過 metetable 模擬出來(不推薦用,只模擬最基本的對象大部分時間夠用了)。
Lua
中的表不僅在某種意義上是一種對象。像對象一樣,表也有狀態(成員變量);也有與對象的值獨立的本性,特別是擁有兩個不同值的對象(table)代表兩個不同的對象;一個對象在不同的時候也可以有不同的值,但他始終是一個對象;與對象類似,表的生命週期與其由什麼創建、在哪創建沒有關係。
創建⼀個類
Person = {name = "xiaoming",age = 19,sex = "M"}
設置類的構造函數
function
Person:new(name,age,sex)
o = {}
setmetatable(o,self)
self.__index = self
self.name = name
self.age = age
self.sex = sex
return o
end
設置類的成員函數
function Person:getsex()
return self.sex
end
對象的實例化
xiaoming = Person:new("xiaoming",10,"M")
設置對象的成員字段
xiaoming.age = 11
調⽤對象的成員⽅法
print(xiaoming:getsex())
靜態
Person.maxPerson = 100000
print(Person.maxPerson)
function Person.getMax()
return Person.maxPerson
end