lua基礎(chǔ)數(shù)據(jù)類型
nil
一個變量在第一次賦值前的默認(rèn)值是 nil, 將nil 賦予給一個全局變量就等同于刪除它船逮。
boolean
布爾類型, 可選值 true/false窑邦; Lua 中 nil 和 false 為“假”拜英, 其它所有值均為“真”。比如 0 和空
字符串就是“真”盆驹;
local a = true
if a then
print("a") -->output:a
else
print("not a") --這個沒有執(zhí)行
end
number
Number 類型用于表示實數(shù)圆丹。可以使用數(shù)學(xué)函數(shù) math.floor( 向下取整) 和 math.ceil( 向上取整) 進(jìn)行取整操作躯喇。
local order = 3.99
local score = 98.01
print(math.floor(order)) -->output:3
print(math.ceil(score)) -->output:99
string
Lua 中有三種方式表示字符串:
- 使用一對單引號
'hello'
- 使用一對雙引號
"hello"
- 字符串還可以用一種長括號( 即[[ ]]) 括起來的方式定義辫封。
Lua 的字符串是不可改變的值,也不能通過下標(biāo)來訪問字符串的某個字符
local str1 = 'hello world'
local str2 = "hello lua"
local str3 = [["add\name",'hello']]
local str4 = [=[string have a [[]].]=]
print(str1) -->output:hello world
print(str2) -->output:hello lua
print(str3) -->output:"add\name",'hello'
print(str4) -->output:string have a [[]].
table
Table 類型實現(xiàn)了一種抽象的“關(guān)聯(lián)數(shù)組”廉丽。 “關(guān)聯(lián)數(shù)組”是一種具有特殊索引方式的數(shù)組倦微, 索引通常是字符串( string) 或者 number 類型, 但也可以是除 nil 以外的任意類型的值正压。
local corp = {
web = "www.google.com", --索引為字符串欣福, key = "web",
-- value = "www.google.com"
telephone = "12345678", --索引為字符串
staff = {"Jack", "Scott", "Gary"}, --索引為字符串, 值也是一個表
100876, --相當(dāng)于 [1] = 100876焦履, 此時索引為數(shù)字
-- key = 1, value = 100876
100191, --相當(dāng)于 [2] = 100191拓劝, 此時索引為數(shù)字
[10] = 360, --直接把數(shù)字索引給出
["city"] = "Beijing" --索引為字符串
}
print(corp.web) -->output:www.google.com
print(corp["telephone"]) -->output:12345678
print(corp[2]) -->output:100191
print(corp["city"]) -->output:"Beijing"
print(corp.staff[1]) -->output:Jack
print(corp[10]) -->output:360
function
在 Lua 中, 函數(shù) 也是一種數(shù)據(jù)類型裁良, 函數(shù)可以存儲在變量中凿将, 可以通過參數(shù)傳遞給其他函數(shù), 還可以作為其他函數(shù)的返回值价脾。
local function foo()
print("in the function")
--dosomething()
local x = 10
local y = 20
return x + y
end
local a = foo --把函數(shù)賦給變量
print(a())
--output:
in the function
30
表達(dá)式
邏輯運算符
邏輯運算符 | 說明 |
---|---|
and | 邏輯與 |
or | 邏輯或 |
not | 邏輯非 |
字符串連接
使用操作符“..”( 兩個點)連接兩個字符串牧抵,也可以使用 string 庫函數(shù) string.format 連接字符串。
print("Hello " .. "World") -->打印 Hello World
print(0 .. 1) -->打印 01
str1 = string.format("%s-%s","hello","world")
print(str1) -->打印 hello-world
str2 = string.format("%d-%s-%.2f",123,"world",1.21)
print(str2) -->打印 123-world-1.21
使用table 和 table.concat() 來進(jìn)行很多字符串的拼接:
local pieces = {}
for i, elem in ipairs(my_list) do
pieces[i] = my_process(elem)
end
local res = table.concat(pieces)
控制結(jié)構(gòu)
if-else
單個if分支
x = 10
if x > 0 then
print("x is a positive number")
end
兩個分支if-else
x = 10
if x > 0 then
print("x is a positive number")
else
print("x is a non-positive number")
end
多個分支if-elseif-else
score = 90
if score == 100 then
print("Very good!Your score is 100")
elseif score >= 60 then
print("Congratulations, you have passed it,your score greater or equal to 60")
--此處可以添加多個elseif
else
print("Sorry, you do not pass the exam! ")
end
while
while 表達(dá)式 do
--body
end
Lua 并沒有像許多其他語言那樣提供類似 continue 這樣的控制語句用來立即進(jìn)入下一個循環(huán)迭代( 如果有的話) 侨把。 因此犀变, 我們需要仔細(xì)地安排循環(huán)體里的分支, 以避免這樣的需求秋柄。
lua提供了break語句获枝,可以跳出當(dāng)前循環(huán)。
repeat
repeat 控制結(jié)構(gòu)類似于其他語言中的 do-while骇笔,執(zhí)行 repeat 循環(huán)體后省店, 直到 until 的條件為真時才結(jié)束
x = 10
repeat
print(x)
until false
for
for數(shù)字型
for var = begin, finish, step do
--body
end
step參數(shù)是可選的屡律,默認(rèn)為1
for i = 1, 5 do
print(i)
end
for泛型
泛型 for 循環(huán)通過一個迭代器( iterator) 函數(shù)來遍歷所有值:
-- 打印數(shù)組a的所有值
local a = {"a", "b", "c", "d"}
for i, v in ipairs(a) do
print("index:", i, " value:", v)
end
-- output:
index: 1 value: a
index: 2 value: b
index: 3 value: c
index: 4 value: d
ipairs()是用于遍歷數(shù)組的迭代器函數(shù)是复。在每次循環(huán)中孝情, i 會被賦予一個索引值谢澈, 同時 v 被賦予一個對應(yīng)于該索引的數(shù)組元素值。
pairs()用于遍歷
break粗俱,return關(guān)鍵字
break
語句 break 用來終止 while 说榆、 repeat 和 for 三種循環(huán)的執(zhí)行, 并跳出當(dāng)前循環(huán)體寸认, 繼續(xù)執(zhí)行當(dāng)前循環(huán)之后的語句
return
return 主要用于從函數(shù)中返回結(jié)果签财, 或者用于簡單的結(jié)束一個函數(shù)的執(zhí)行
有時候, 為了調(diào)試方便偏塞, 我們可以想在某個函數(shù)的中間提前 return 唱蒸, 以進(jìn)行控制流的短路。此時我們可以將 return 放在一個 do ... end 代碼塊中
local function foo()
print("before")
do return end
print("after") -- 這一行語句永遠(yuǎn)不會執(zhí)行到
end
函數(shù)的參數(shù)
按值傳遞
Lua 函數(shù)的參數(shù)大部分是按值傳遞的烛愧。在調(diào)用函數(shù)的時候油宜,若形參個數(shù)和實參個數(shù)不同時, Lua會自動調(diào)整實參個數(shù)怜姿。 調(diào)整規(guī)則:
- 若實參個數(shù)大于形參個數(shù), 從左向右疼燥, 多余的實參被忽略沧卢;
- 若實參個數(shù)小于形參個數(shù), 從左向右醉者, 沒有被實參初始化的形參會被初始化為 nil但狭。
變長參數(shù)
若形參為 ... , 表示該函數(shù)可以接收不同長度的參數(shù)。 訪問參數(shù)的時候也要使用 ...
local function func( ... ) -- 形參為 ... ,表示函數(shù)采用變長參數(shù)
local temp = {...} -- 訪問的時候也要使用 ...
local ans = table.concat(temp, " ") -- 使用 table.concat 庫函數(shù)對數(shù)
-- 組內(nèi)容使用 " " 拼接成字符串撬即。
print(ans)
end
func(1, 2) -- 傳遞了兩個參數(shù)
func(1, 2, 3, 4) -- 傳遞了四個參數(shù)
-->output
1 2
1 2 3 4
具名參數(shù)
Lua 還支持通過名稱來指定實參立磁,這時候要把所有的實參組織到一個 table 中, 并將這個table 作為唯一的實參傳給函數(shù)
local function change(arg) -- change 函數(shù)剥槐, 改變長方形的長和寬唱歧, 使其各增長一倍
arg.width = arg.width * 2
arg.height = arg.height * 2
return arg
end
local rectangle = { width = 20, height = 15 }
print("before change:", "width =", rectangle.width,
"height =", rectangle.height)
rectangle = change(rectangle)
print("after change:", "width =", rectangle.width,
"height =", rectangle.height)
-->output
before change: width = 20 height = 15
after change: width = 40 height = 30
按引用傳遞
當(dāng)函數(shù)參數(shù)是 table 類型時, 傳遞進(jìn)來的是 實際參數(shù)的引用粒竖, 此時在函數(shù)內(nèi)部對該 table 所做的修改颅崩, 會直接對調(diào)用者所傳遞的實際參數(shù)生效
function change(arg) --change函數(shù), 改變長方形的長和寬蕊苗, 使其各增長一倍
arg.width = arg.width * 2 --表arg不是表rectangle的拷貝沿后, 他們是同一個表
arg.height = arg.height * 2
end -- 沒有return語句了
local rectangle = { width = 20, height = 15 }
print("before change:", "width = ", rectangle.width,
" height = ", rectangle.height)
change(rectangle)
print("after change:", "width = ", rectangle.width,
" height =", rectangle.height)
--> output
before change: width = 20 height = 15
after change: width = 40 height = 30
函數(shù)返回值
函數(shù)必須放在調(diào)用的代碼之前
lua允許函數(shù)返回多個值。返回多個值時朽砰, 值之間用“,”隔開尖滚。
local function swap(a, b) -- 定義函數(shù) swap喉刘, 實現(xiàn)兩個變量交換值
return b, a -- 按相反順序返回變量的值
end
模塊
一個 Lua 模塊的數(shù)據(jù)結(jié)構(gòu)是用一個 Lua 值( 通常是一個 Lua 表或者 Lua 函數(shù)) 。 一個 Lua 模塊代碼就是一個會返回這個 Lua 值的代碼塊漆弄∧郎眩可以使用內(nèi)建函數(shù) require() 來加載和緩存模塊。 模塊加載后的結(jié)果通過是一個 Lua table置逻,這個表就像是一個命名空間推沸,其內(nèi)容就是模塊中導(dǎo)出的所有東西, 比如函數(shù)和變量券坞。 require 函數(shù)會返回Lua 模塊加載后的結(jié)果鬓催, 即用于表示該 Lua 模塊的 Lua 值
require函數(shù)
要加載一個模塊, 只需要簡單地調(diào)用 require "file" 就可以了恨锚, file 指模塊所在的文件名宇驾。這個調(diào)用會返回一個由模塊函數(shù)組成的table, 并且還會定義一個包含該 table 的全局變量猴伶。
在 Lua 中創(chuàng)建一個模塊最簡單的方法是: 創(chuàng)建一個 table课舍, 并將所有需要導(dǎo)出的函數(shù)放入其中, 最后返回這個 table 就可以了他挎。 相當(dāng)于將導(dǎo)出的函數(shù)作為 table 的一個字段
#my.lua, 創(chuàng)建了my模塊
local foo={}
local function getname()
return "Lucy"
end
function foo.greeting()
print("hello " .. getname())
end
return foo
#在main.lua中加載my模塊
local fp = require("my")
fp.greeting() -->output: hello Lucy
注: 對于需要導(dǎo)出給外部使用的公共模塊筝尾, 處于安全考慮, 是要避免全局變量的出現(xiàn)办桨。
String庫
string.byte(s[,i[,j]])
返回字符 s[i]筹淫、 s[i + 1]、 s[i + 2]呢撞、 ······损姜、 s[j] 所對應(yīng)的 ASCII 碼
string.char (...)
接收 0 個或更多的整數(shù)( 整數(shù)范圍: 0~255) , 返回這些整數(shù)所對應(yīng)的 ASCII 碼字符組成的字符串
string.upper(s)
接收一個字符串 s殊霞, 返回一個把所有小寫字母變成大寫字母的字符串
string.lower(s)
接收一個字符串 s摧阅, 返回一個把所有大寫字母變成小寫字母的字符串。
string.len(s)
接收一個字符串绷蹲, 返回它的長度棒卷。
string.find(s, p [, init [, plain]])
在 s 字符串中第一次匹配 p 字符串。 若匹配成功瘸右, 則返回 p 字符串在 s 字符串中出現(xiàn)的開始位置和結(jié)束位置娇跟; 若匹配失敗, 則返回 nil太颤。
string.format(formatstring, ...)
按照格式化參數(shù) formatstring苞俘, 返回后面 ... 內(nèi)容的格式化版本
string.match(s, p [, init])
在字符串 s 中匹配( 模式) 字符串 p, 若匹配成功龄章, 則返回目標(biāo)字符串中與模式匹配的子串吃谣;否則返回 nil乞封。
string.gmatch(s, p)
返回一個迭代器函數(shù), 通過這個迭代器函數(shù)可以遍歷到在字符串 s 中出現(xiàn)模式串 p 的所有地方岗憋。
string.rep(s, n)
返回字符串 s 的 n 次拷貝肃晚。
string.sub(s, i [, j])
返回字符串 s 中, 索引 i 到索引 j 之間的子字符串
string.gsub(s, p, r [, n])
將目標(biāo)字符串 s 中所有的子串 p 替換成字符串 r
string.reverse (s)
接收一個字符串 s仔戈, 返回這個字符串的反轉(zhuǎn)
table庫
下標(biāo)從 1 開始关串。在 Lua 中, 數(shù)組下標(biāo)從 1 開始計數(shù)监徘。
table.getn 獲取長度
對于常規(guī)的數(shù)組晋修, 里面從 1 到 n 放著一些非空的值的時候, 它的長度就精確的為 n凰盔, 即最后一個值的下標(biāo)墓卦。 如果數(shù)組有一個“空洞”( 就是說, nil 值被夾在非空值之間) 户敬, 那么 #t 可能是指向任何一個是 nil 值的前一個位置的下標(biāo)落剪。
不要在 Lua 的 table 中使用 nil 值, 如果一個元素要刪除尿庐, 直接 remove忠怖, 不要用 nil 去代替。
table.concat (table [, sep [, i [, j ] ] ])
對于元素是 string 或者 number 類型的表 table抄瑟, 返回 table[i]..sep..table[i+1] ··· sep..table[j] 連接成的字符串
table.insert (table, [pos ,] value)
在( 數(shù)組型) 表 table 的 pos 索引位置插入 value脑又, 其它元素向后移動到空的地方
table.maxn (table)
返回( 數(shù)組型) 表 table 的最大索引編號; 如果此表沒有正的索引編號锐借, 返回 0
table.remove (table [, pos])
在表 table 中刪除索引為 pos( pos 只能是 number 型) 的元素, 并返回這個被刪除的元素往衷,它后面所有元素的索引值都會減一
table.sort (table [, comp])
按照給定的比較函數(shù) comp 給表 table 排序钞翔, 也就是從 table[1] 到 table[n], 這里 n 表示 table的長度
日期時間函數(shù)
os.time ([table])
如果不使用參數(shù) table 調(diào)用 time 函數(shù)席舍, 它會返回當(dāng)前的時間和日期( 它表示從某一時刻到現(xiàn)在的秒數(shù))
os.difftime (t2, t1)
返回 t1 到 t2 的時間差布轿, 單位為秒
os.date ([format [, time]])
把一個表示日期和時間的數(shù)值, 轉(zhuǎn)換成更高級的表現(xiàn)形式
格式字符 | 含義 |
---|---|
%a | 一星期中天數(shù)的簡寫( 例如: Wed) |
%A | 一星期中天數(shù)的全稱( 例如: Wednesday) |
%b | 月份的簡寫( 例如: Sep) |
%B | 月份的全稱( 例如: September) |
%c | 日期和時間( 例如: 07/30/15 16:57:24) |
%d | 一個月中的第幾天[01 ~ 31] |
%H | 24小時制中的小時數(shù)[00 ~ 23] |
%I | 12小時制中的小時數(shù)[01 ~ 12] |
%j | 一年中的第幾天[001 ~ 366] |
%M | 分鐘數(shù)[00 ~ 59] |
%m | 月份數(shù)[01 ~ 12] |
%p | “上午( am) ”或“下午( pm) ” |
%S | 秒數(shù)[00 ~ 59] |
%w | 一星期中的第幾天[1 ~ 7 = 星期天 ~ 星期六] |
%x | 日期( 例如: 07/30/15) |
%X | 時間( 例如: 16:57:24) |
%y | 兩位數(shù)的年份[00 ~ 99] |
%Y | 完整的年份( 例如: 2015) |
%% | 字符'%' |
數(shù)學(xué)庫
函數(shù)名 | 函數(shù)功能 |
---|---|
math.rad(x) | 角度x轉(zhuǎn)換成弧度 |
math.deg(x) | 弧度x轉(zhuǎn)換成角度 |
math.max(x, ...) | 返回參數(shù)中值最大的那個數(shù)来颤, 參數(shù)必須是number型 |
math.min(x, ...) | 返回參數(shù)中值最小的那個數(shù)汰扭, 參數(shù)必須是number型 |
math.random ([m[, n]]) | 不傳入?yún)?shù)時, 返回 一個在區(qū)間[0,1)內(nèi)均勻分布的偽隨機(jī)實數(shù)福铅; 只使用一個整數(shù)參數(shù)m時萝毛, 返回一個在區(qū)間[1, m]內(nèi)均勻分布的偽隨機(jī)整數(shù); 使用兩個整數(shù)參數(shù)時滑黔, 返回一個在區(qū)間[m, n]內(nèi)均勻分布的偽隨機(jī)整數(shù) |
math.randomseed(x) | 為偽隨機(jī)數(shù)生成器設(shè)置一個種子x笆包, 相同的種子將會生成相同的數(shù)字序列 |
math.abs(x) | 返回x的絕對值 |
math.fmod(x, y) | 返回 x對y取余數(shù) |
math.pow(x, y) | 返回x的y次方 |
math.sqrt(x) | 返回x的算術(shù)平方根 |
math.exp(x) | 返回自然數(shù)e的x次方 |
math.log(x) | 返回x的自然對數(shù) |
math.log10(x) | 返回以10為底环揽, x的對數(shù) |
math.floor(x) | 返回最大且不大于x的整數(shù) |
math.ceil(x) | 返回最小且不小于x的整數(shù) |
math.pi | 圓周率 |
math.sin(x) | 求弧度x的正弦值 |
math.cos(x) | 求弧度x的余弦值 |
math.tan(x) | 求弧度x的正切值 |
math.asin(x) | 求x的反正弦值 |
math.acos(x) | 求x的反余弦值 |
math.atan(x) | 求x的反正切值 |
文件操作
io.open (filename [, mode])
按指定的模式 mode, 打開一個文件名為 filename 的文件庵佣, 成功則返回文件句柄歉胶, 失敗則返回 nil 加錯誤信息
模式 | 含義 | 文件不存在時 |
---|---|---|
"r" | 讀模式 (默認(rèn)) | 返回nil加錯誤信息 |
"w" | 寫模式 | 創(chuàng)建文件 |
"a" | 添加模式 | 創(chuàng)建文件 |
"r+" | 更新模式, 保存之前的數(shù)據(jù) | 返回nil加錯誤信息 |
"w+" | 更新模式巴粪, 清除之前的數(shù)據(jù) | 創(chuàng)建文件 |
"a+" | 添加更新模式通今, 保存之前的數(shù)據(jù),在文件尾進(jìn)行添加 | 創(chuàng)建文件 |
file:close ()
關(guān)閉文件。 注意: 當(dāng)文件句柄被垃圾收集后肛根, 文件將自動關(guān)閉辫塌。 句柄將變?yōu)橐粋€不可預(yù)知的值。
io.close ([file])
關(guān)閉文件晶通, 和 file:close() 的作用相同璃氢。 沒有參數(shù) file 時, 關(guān)閉默認(rèn)輸出文件狮辽。
file:flush ()
把寫入緩沖區(qū)的所有數(shù)據(jù)寫入到文件 file 中一也。
io.flush ()
相當(dāng)于 file:flush(), 把寫入緩沖區(qū)的所有數(shù)據(jù)寫入到默認(rèn)輸出文件
io.input ([file])
當(dāng)使用一個文件名調(diào)用時喉脖, 打開這個文件( 以文本模式) 椰苟, 并設(shè)置文件句柄為默認(rèn)輸入文件; 當(dāng)使用一個文件句柄調(diào)用時树叽, 設(shè)置此文件句柄為默認(rèn)輸入文件舆蝴; 當(dāng)不使用參數(shù)調(diào)用時,返回默認(rèn)輸入文件句柄题诵。
file:lines ()
返回一個迭代函數(shù), 每次調(diào)用將獲得文件中的一行內(nèi)容, 當(dāng)?shù)轿募矔r洁仗, 將返回 nil, 但不關(guān)閉文件性锭。
io.lines ([filename])
打開指定的文件 filename 為讀模式并返回一個迭代函數(shù), 每次調(diào)用將獲得文件中的一行內(nèi)容,當(dāng)?shù)轿募矔r赠潦, 將返回 nil, 并自動關(guān)閉文件草冈。 若不帶參數(shù)時 io.lines() 等價于 io.input():lines()讀取默認(rèn)輸入設(shè)備的內(nèi)容她奥, 結(jié)束時不關(guān)閉文件。
io.output ([file])
類似于 io.input怎棱, 但操作在默認(rèn)輸出文件上哩俭。
file:read (...)
按指定的格式讀取一個文件。 按每個格式將返回一個字符串或數(shù)字, 如果不能正確讀取將返回nil拳恋, 若沒有指定格式將指默認(rèn)按行方式進(jìn)行讀取凡资。
格式 | 含義 |
---|---|
"*n" | 讀取一個數(shù)字 |
"*a" | 從當(dāng)前位置讀取整個文件。 若當(dāng)前位置為文件尾诅岩, 則返回空字符串 |
"*l" | 讀取下一行的內(nèi)容讳苦。 若為文件尾带膜, 則返回nil。 (默認(rèn)) |
number | 讀取指定字節(jié)數(shù)的字符鸳谜。 若為文件尾膝藕, 則返回nil。 如果number為0,則返回空字符串咐扭, 若為文件尾,則返回nil |
io.read (...)
相當(dāng)于 io.input():read
io.type (obj)
檢測 obj 是否一個可用的文件句柄芭挽。 如果 obj 是一個打開的文件句柄, 則返回 "file" 如果 obj是一個已關(guān)閉的文件句柄蝗肪, 則返回 "closed file" 如果 obj 不是一個文件句柄袜爪, 則返回 nil。
file:write (...)
把每一個參數(shù)的值寫入文件薛闪。 參數(shù)必須為字符串或數(shù)字辛馆, 若要輸出其它值, 則需通過 tostring 或 string.format 進(jìn)行轉(zhuǎn)換豁延。
io.write (...)
相當(dāng)于 io.output():write
file:seek ([whence] [, offset])
設(shè)置和獲取當(dāng)前文件位置昙篙, 成功則返回最終的文件位置(按字節(jié), 相對于文件開頭),失敗則返回 nil 加錯誤信息诱咏。
whence | 含義 |
---|---|
"set" | 文件開始 |
"cur" | 文件當(dāng)前位置(默認(rèn)) |
"end" | 文件結(jié)束 |
file:setvbuf (mode [, size])
設(shè)置輸出文件的緩沖模式
模式 | 含義 |
---|---|
"no" | 沒有緩沖苔可, 即直接輸出 |
"full" | 全緩沖, 即當(dāng)緩沖滿后才進(jìn)行輸出操作(也可調(diào)用flush馬上輸出) |
"line" | 以行為單位袋狞, 進(jìn)行輸出 |
元表
元表 (metatable) 的表現(xiàn)行為類似于 C++ 語言中的操作符重載
Lua 提供了兩個十分重要的用來處理元表的方法焚辅, 如下:
- setmetatable(table, metatable): 此方法用于為一個表設(shè)置元表。
- getmetatable(table): 此方法用于獲取表的元表對象苟鸯。
# 設(shè)置元表
local mytable = {}
local mymetatable = {}
setmetatable(mytable, mymetatable)
元方法 | 含義 |
---|---|
"__add" | + 操作 |
"__sub" | - 操作 其行為類似于 "add" 操作 |
"__mul" | * 操作 其行為類似于 "add" 操作 |
"__div" | / 操作 其行為類似于 "add" 操作 |
"__mod" | % 操作 其行為類似于 "add" 操作 |
"__pow" | ^ ( 冪) 操作 其行為類似于 "add" 操作 |
"__unm" | 一元 - 操作 |
"__concat" | .. ( 字符串連接) 操作 |
"__len" | # 操作 |
"__eq" | == 操作 函數(shù) getcomphandler 定義了 Lua 怎樣選擇一個處理器來作比較操作 僅在兩個對象類型相同且有對應(yīng)操作相同的元方法時才起效 |
"__lt" | < 操作 |
"__le" | <= 操作 |
"__index" | 取下標(biāo)操作用于訪問 table[key] |
"__newindex" | 賦值給指定下標(biāo) table[key] = value |
"__tostring" | 轉(zhuǎn)換成字符串 |
"__call" | 當(dāng) Lua 調(diào)用一個值時調(diào)用 |
"__mode" | 用于弱表(week table) |
"__metatable" | 用于保護(hù)metatable不被訪問 |
面向?qū)ο?/h2>
類
可以使用表和函數(shù)實現(xiàn)面向?qū)ο蟆?將函數(shù)和相關(guān)的數(shù)據(jù)放置于同一個表中就形成了一個對象同蜻。
下面的代碼,創(chuàng)建了account類: account.lua
local _M = {}
local mt = { __index = _M }
function _M.deposit (self, v)
self.balance = self.balance + v
end
function _M.withdraw (self, v)
if self.balance > v then
self.balance = self.balance - v
else
error("insufficient funds")
end
end
function _M.new (self, balance)
balance = balance or 0
return setmetatable({balance = balance}, mt)
end
return _M
下面代碼是使用account類示例:
local account = require("account")
local a = account:new()
a:deposit(100)
local b = account:new()
b:deposit(50)
print(a.balance) --> output: 100
print(b.balance) --> output: 50
繼承
繼承可以用元表實現(xiàn)早处, 它提供了在父類中查找存在的方法和變量的機(jī)制埃仪。 在 Lua 中是不推薦使用繼承方式完成構(gòu)造的, 這樣做引入的問題可能比解決的問題要多
---------- s_base.lua
local _M = {}
local mt = { __index = _M }
function _M.upper (s)
return string.upper(s)
end
return _M
---------- s_more.lua
local s_base = require("s_base")
local _M = {}
_M = setmetatable(_M, { __index = s_base })
function _M.lower (s)
return string.lower(s)
end
return _M
---------- test.lua
local s_more = require("s_more")
print(s_more.upper("Hello")) -- output: HELLO
print(s_more.lower("Hello")) -- output: hello
局部變量
在一個 block 中的變量陕赃, 如果之前沒有定義過, 那么認(rèn)為它是一個全局變量颁股, 而不是這個 block 的局部變量
Lua 中的局部變量要用 local 關(guān)鍵字來顯式定義么库, 不使用 local 顯式定義的變量就是全局變量
局部變量的生命周期是有限的, 它的作用域僅限于聲明它的塊( block) 甘有。 一個塊是一個控制結(jié)構(gòu)的執(zhí)行體诉儒、 或者是一個函數(shù)的執(zhí)行體再或者是一個程序塊( chunk)
“盡量使用局部變量”是一種良好的編程風(fēng)格
判斷數(shù)組大小
table.getn(t) 等價于 #t 但計算的是數(shù)組元素, 不包括 hash 鍵值亏掀。 而且數(shù)組是以第一個 nil 元素來判斷數(shù)組結(jié)束忱反。 # 只計算 array 的元素個數(shù)泛释, 它實際上調(diào)用了對象的 metatable 的__len 函數(shù)。 對于有 __len 方法的函數(shù)返回函數(shù)返回值温算, 不然就返回數(shù)組成員數(shù)目怜校。
注意: 一定不要使用 # 操作符或 table.getn 來計算包含 nil 的數(shù)組長度, 這是一個未定義的操作注竿, 不一定報錯茄茁, 但不能保證結(jié)果如你所想。 如果你要刪除一個數(shù)組中的元素巩割, 請使用remove 函數(shù)裙顽, 而不是用 nil 賦值。
非空判斷
對于table型變量宣谈,可以如下判斷非空:
local person = {name = "Bob", sex = "M"}
if person ~= nil and person.name ~= nil then
print(person.name)
end
對于簡單類型的變量愈犹, 我們可以用 if (var == nil) then 這樣的簡單句子來判斷。 但是對于 table型的 Lua 對象闻丑, 就不能這么簡單判斷它是否為空了漩怎。 一個 table 型變量的值可能是 {} , 這時它不等于 nil
正則表達(dá)式(openresty中的正則表達(dá)式規(guī)范 -- ngx.re.*)
下面是使用openresty中正則的例子:
location /test {
content_by_lua_block {
local regex = [[\d+]]
-- 參數(shù) "j" 啟用 JIT 編譯梆掸, 參數(shù) "o" 是開啟緩存必須的
local m = ngx.re.match("hello, 1234", regex, "jo")
if m then
ngx.say(m[0])
else
ngx.say("not matched!")
end
}
}
正則中使用了jo 兩個參數(shù):
- ngx.re.* 中的 o 選項扬卷, 指明該參數(shù), 被編譯的 Pattern 將會在工作進(jìn)程中緩存酸钦, 并且被當(dāng)前工作進(jìn)程的每次請求所共享
- ngx.re.* 中的 j 選項怪得, 指明該參數(shù), 如果使用的 PCRE 庫支持 JIT卑硫, OpenResty 會在編譯 Pattern 時啟用 JIT徒恋。即使運行在不支持 JIT 的 OpenResty 上, 加上 j 選項也不會帶來壞的影響
lua正則匯總:
符號 | 匹配次數(shù) | 匹配模式 |
---|---|---|
+ | 匹配前一字符 1 次或多次 | 非貪婪 |
* | 匹配前一字符 0 次或多次 | 貪婪 |
- | 匹配前一字符 0 次或多次 | 非貪婪 |
? | 匹配前一字符 0 次或1次 | 僅用于此欢伏, 不用于標(biāo)識是否貪婪 |
符號 | 匹配模式 |
---|---|
. | 任意字符 |
%a | 字母 |
%c | 控制字符 |
%d | 數(shù)字 |
%l | 小寫字母 |
%p | 標(biāo)點字符 |
%s | 空白符 |
%u | 大寫字母 |
%w | 字母和數(shù)字 |
%x | 十六進(jìn)制數(shù)字 |
%z | 代表 0 的字符 |
虛變量
當(dāng)一個方法返回多個值時入挣, 有些返回值有時候用不到, 要是聲明很多變量來一一接收硝拧, 顯然不太合適( 不是不能) 径筏。 Lua 提供了一個虛變量(dummy variable), 以單個下劃線( “_”) 來命名障陶, 用它來丟棄不需要的數(shù)值滋恬, 僅僅起到占位的作用。
-- string.find (s,p) 從string 變量s的開頭向后匹配 string
-- p抱究, 若匹配不成功恢氯, 返回nil, 若匹配成功, 返回第一次匹配成功的起止下標(biāo)勋拟。
local start, finish = string.find("hello", "he") --start 值為起始下標(biāo)勋磕, finish
--值為結(jié)束下標(biāo)
print ( start, finish ) --輸出 1 2
local start = string.find("hello", "he") -- start值為起始下標(biāo)
print ( start ) -- 輸出 1
local _,finish = string.find("hello", "he") --采用虛變量( 即下劃線) , 接收起
--始下標(biāo)值敢靡, 然后丟棄挂滓, finish接收
--結(jié)束下標(biāo)值
print ( finish ) --輸出 2
點號與冒號操作符的區(qū)別
冒號操作會帶入一個 self 參數(shù), 用來代表 自己 醋安。 而點號操作杂彭, 只是 內(nèi)容 的展開。
local str = "abcde"
print("case 1:", str:sub(1, 2))
print("case 2:", str.sub(str, 1, 2))