lua語言學(xué)習(xí)總結(jié)

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 中有三種方式表示字符串:

  1. 使用一對單引號 'hello'
  2. 使用一對雙引號"hello"
  3. 字符串還可以用一種長括號( 即[[ ]]) 括起來的方式定義辫封。

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))
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末吓揪,一起剝皮案震驚了整個濱河市亲怠,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌柠辞,老刑警劉巖团秽,帶你破解...
    沈念sama閱讀 211,194評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異叭首,居然都是意外死亡习勤,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評論 2 385
  • 文/潘曉璐 我一進(jìn)店門焙格,熙熙樓的掌柜王于貴愁眉苦臉地迎上來图毕,“玉大人,你說我怎么就攤上這事眷唉∮璨” “怎么了?”我有些...
    開封第一講書人閱讀 156,780評論 0 346
  • 文/不壞的土叔 我叫張陵冬阳,是天一觀的道長蛤虐。 經(jīng)常有香客問我,道長肝陪,這世上最難降的妖魔是什么驳庭? 我笑而不...
    開封第一講書人閱讀 56,388評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮氯窍,結(jié)果婚禮上饲常,老公的妹妹穿的比我還像新娘。我一直安慰自己狼讨,他們只是感情好不皆,可當(dāng)我...
    茶點故事閱讀 65,430評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著熊楼,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上鲫骗,一...
    開封第一講書人閱讀 49,764評論 1 290
  • 那天犬耻,我揣著相機(jī)與錄音,去河邊找鬼执泰。 笑死枕磁,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的术吝。 我是一名探鬼主播计济,決...
    沈念sama閱讀 38,907評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼排苍!你這毒婦竟也來了沦寂?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,679評論 0 266
  • 序言:老撾萬榮一對情侶失蹤淘衙,失蹤者是張志新(化名)和其女友劉穎传藏,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體彤守,經(jīng)...
    沈念sama閱讀 44,122評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡毯侦,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,459評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了具垫。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片侈离。...
    茶點故事閱讀 38,605評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖筝蚕,靈堂內(nèi)的尸體忽然破棺而出卦碾,到底是詐尸還是另有隱情,我是刑警寧澤饰及,帶...
    沈念sama閱讀 34,270評論 4 329
  • 正文 年R本政府宣布蔗坯,位于F島的核電站,受9級特大地震影響燎含,放射性物質(zhì)發(fā)生泄漏宾濒。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,867評論 3 312
  • 文/蒙蒙 一屏箍、第九天 我趴在偏房一處隱蔽的房頂上張望绘梦。 院中可真熱鬧,春花似錦赴魁、人聲如沸卸奉。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,734評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽榄棵。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間疹鳄,已是汗流浹背拧略。 一陣腳步聲響...
    開封第一講書人閱讀 31,961評論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留瘪弓,地道東北人垫蛆。 一個月前我還...
    沈念sama閱讀 46,297評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像腺怯,于是被迫代替她去往敵國和親袱饭。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,472評論 2 348

推薦閱讀更多精彩內(nèi)容

  • Lua 5.1 參考手冊 by Roberto Ierusalimschy, Luiz Henrique de F...
    蘇黎九歌閱讀 13,763評論 0 38
  • ¥開啟¥ 【iAPP實現(xiàn)進(jìn)入界面執(zhí)行逐一顯】 〖2017-08-25 15:22:14〗 《//首先開一個線程呛占,因...
    小菜c閱讀 6,365評論 0 17
  • 在蒙臺梭利吸收性心智的理論中虑乖,我們可以獲得從三歲開始孩子的心智狀態(tài)是進(jìn)入了有意識的吸收性心智,換句話說栓票,在3...
    谷曉玉閱讀 2,895評論 0 1
  • 簡悅直播教練恬源閱讀 114評論 0 4
  • 我醉在自釀的憂愁里 抱著月亮的影子 我問自己 今夕是何夕 沒有你的日子 生命中只剩下白天和黑夜 雪下的那么密 你的...
    妮妮雅閱讀 284評論 0 1