一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

腳本之家,腳本語(yǔ)言編程技術(shù)及教程分享平臺(tái)!
分類導(dǎo)航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服務(wù)器之家 - 腳本之家 - Lua - 深入談?wù)刲ua中神奇的table

深入談?wù)刲ua中神奇的table

2020-05-08 10:49暗無(wú)天日 Lua

table 在lua中是一個(gè)非常常用的數(shù)據(jù)結(jié)構(gòu),可以用來(lái)存放各種類型的元素,下面這篇文章就來(lái)給大家介紹了關(guān)于lua中神奇的table的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面來(lái)一起看看吧

前言

最近在嘗試配置 awesome WM,因此粗略地學(xué)習(xí)了一下 lua 。 在學(xué)習(xí)過(guò)程中,我完全被 table 在 lua 中的應(yīng)用所鎮(zhèn)住了。

table 在 lua 中真的是無(wú)處不在:首先,它可以作為字典和數(shù)組來(lái)用; 此外,它還可以被用于設(shè)置閉包環(huán)境、module; 甚至可以用來(lái)模擬對(duì)象和類

字典

table 最基礎(chǔ)的作用就是當(dāng)成字典來(lái)用。 它的 key 值可以是除了 nil 之外的任何類型的值。

?
1
2
3
4
5
6
7
8
9
t={}
t[{}] = "table"  -- key 可以是 table
t[1] = "int"  -- key 可以是整數(shù)
t[1.1] = "double" -- key 可以是小數(shù)
t[function () end] = "function" -- key 可以是函數(shù)
t[true] = "Boolean" -- key 可以是布爾值
t["abc"] = "String" -- key 可以是字符串
t[io.stdout] = "userdata" -- key 可以是userdata
t[coroutine.create(function () end)] = "Thread" -- key可以是thread

當(dāng)把 table 當(dāng)成字典來(lái)用時(shí),可以使用 pairs 函數(shù)來(lái)進(jìn)行遍歷。

?
1
2
3
for k,v in pairs(t) do
 print(k,"->",v)
end

運(yùn)行結(jié)果為:

1 ->  int
1.1 ->  double
thread: 0x220bb08 ->  Thread
table: 0x220b670  ->  table
abc ->  String
file (0x7f34a81ef5c0) ->  userdata
function: 0x220b340 ->  function
true  ->  Boolean

從結(jié)果中你還可以發(fā)現(xiàn),使用 pairs 進(jìn)行遍歷時(shí)的順序是隨機(jī)的,事實(shí)上相同的語(yǔ)句執(zhí)行多次得到的結(jié)果是不一樣的。

table 中的key最常見(jiàn)的兩種類型就是整數(shù)型和字符串類型。 當(dāng) key 為字符串時(shí),table可以當(dāng)成結(jié)構(gòu)體來(lái)用。同時(shí)形如 t["field"] 這種形式的寫法可以簡(jiǎn)寫成 t.field 這種形式。

數(shù)組

當(dāng) key 為整數(shù)時(shí),table 就可以當(dāng)成數(shù)組來(lái)用。而且這個(gè)數(shù)組是一個(gè) 索引從1開(kāi)始 ,沒(méi)有固定長(zhǎng)度,可以根據(jù)需要自動(dòng)增長(zhǎng)的數(shù)組。

?
1
2
3
4
a = {}
for i=0,5 do  -- 注意,這里故意寫成了i從0開(kāi)始
 a[i] = 0
end

當(dāng)將 table 當(dāng)成數(shù)組來(lái)用時(shí),可以通過(guò) 長(zhǎng)度操作符 # 來(lái)獲取數(shù)組的長(zhǎng)度

?
1
print(#a)

結(jié)果為

5

你會(huì)發(fā)現(xiàn), lua 認(rèn)為 數(shù)組 a 中只有5個(gè)元素,到底是哪5個(gè)元素呢?我們可以使用使用 ipairs 對(duì)數(shù)組進(jìn)行遍歷:

?
1
2
3
for i,v in ipairs(a) do
 print(i,v)
end

結(jié)果為

1 0
2 0
3 0
4 0
5 0

從結(jié)果中你會(huì)發(fā)現(xiàn) a 的0號(hào)索引并不認(rèn)為是數(shù)組中的一個(gè)元素,從而也驗(yàn)證了 lua 中的數(shù)組是從 1開(kāi)始索引的

另外,將table當(dāng)成數(shù)組來(lái)用時(shí),一定要注意索引不連貫的情況,這種情況下 # 計(jì)算長(zhǎng)度時(shí)會(huì)變得很詭異

?
1
2
3
4
5
6
7
8
a = {}
for i=1,5 do
 a[i] = 0
end
a[8] = 0   -- 雖然索引不連貫,但長(zhǎng)度是以最大索引為準(zhǔn)
print(#a)
a[100] = 0   -- 索引不連貫,而且長(zhǎng)度不再以最大索引為準(zhǔn)了
print(#a)

結(jié)果為:

8
8

而使用 ipairs 對(duì)數(shù)組進(jìn)行遍歷時(shí),只會(huì)從1遍歷到索引中斷處

?
1
2
3
for i,v in ipairs(a) do
 print(i,v)
end

結(jié)果為:

1 0
2 0
3 0
4 0
5 0

環(huán)境(命名空間)

lua將所有的全局變量/局部變量保存在一個(gè)常規(guī)table中,這個(gè)table一般被稱為全局或者某個(gè)函數(shù)(閉包)的環(huán)境。

為了方便,lua在創(chuàng)建最初的全局環(huán)境時(shí),使用全局變量 _G 來(lái)引用這個(gè)全局環(huán)境。因此,在未手工設(shè)置環(huán)境的情況下,可以使用 _G[varname] 來(lái)存取全局變量的值.

?
1
2
3
for k,v in pairs(_G) do
 print(k,"->",v)
end

rawequal  ->  function: 0x41c2a0
require ->  function: 0x1ea4e70
_VERSION  ->  Lua 5.3
debug ->  table: 0x1ea8ad0
string  ->  table: 0x1ea74b0
xpcall  ->  function: 0x41c720
select  ->  function: 0x41bea0
package ->  table: 0x1ea4820
assert  ->  function: 0x41cc50
pcall ->  function: 0x41cd10
next  ->  function: 0x41c450
tostring  ->  function: 0x41be70
_G  ->  table: 0x1ea2b80
coroutine ->  table: 0x1ea4ee0
unpack  ->  function: 0x424fa0
loadstring  ->  function: 0x41ca00
setmetatable  ->  function: 0x41c7e0
rawlen  ->  function: 0x41c250
bit32 ->  table: 0x1ea8fc0
utf8  ->  table: 0x1ea8650
math  ->  table: 0x1ea7770
collectgarbage  ->  function: 0x41c650
rawset  ->  function: 0x41c1b0
os  ->  table: 0x1ea6840
pairs ->  function: 0x41c950
arg ->  table: 0x1ea9450
table ->  table: 0x1ea5130
tonumber  ->  function: 0x41bf40
io  ->  table: 0x1ea5430
loadfile  ->  function: 0x41cb10
error ->  function: 0x41c5c0
load  ->  function: 0x41ca00
print ->  function: 0x41c2e0
dofile  ->  function: 0x41cbd0
rawget  ->  function: 0x41c200
type  ->  function: 0x41be10
getmetatable  ->  function: 0x41cb80
module  ->  function: 0x1ea4e00
ipairs  ->  function: 0x41c970

從lua 5.2開(kāi)始,可以通過(guò)修改 _ENV 這個(gè)值(lua5.1中的setfenv從5.2開(kāi)始被廢除)來(lái)設(shè)置某個(gè)函數(shù)的環(huán)境,從而讓這個(gè)函數(shù)中的執(zhí)行語(yǔ)句在一個(gè)新的環(huán)境中查找全局變量的值。

?
1
2
3
4
5
6
7
8
9
10
11
a=1    -- 全局變量中a=1
local env={a=10,print=_G.print} -- 新環(huán)境中a=10,并且確保能訪問(wèn)到全局的print函數(shù)
function f1()
 local _ENV=env
 print("in f1:a=",a)
 a=a*10   -- 修改的是新環(huán)境中的a值
end
 
f1()
print("globally:a=",a)
print("env.a=",env.a)
?
1
2
3
in f1:a= 10
globally:a= 1
env.a= 100

另外,新創(chuàng)建的閉包都繼承了創(chuàng)建它的函數(shù)的環(huán)境

module

lua 中的模塊也是通過(guò)返回一個(gè)table來(lái)供模塊使用者來(lái)使用的。 這個(gè) table中包含的是模塊中所導(dǎo)出的所有東西,包括函數(shù)和常量。

定義module的一般模板為

module(模塊名, package.seeall)

其中 module(模塊名) 的作用類似于

local modname = 模塊名
local M = {}                    -- M即為存放模塊所有函數(shù)及常數(shù)的table
_G[modname] = M
package.loaded[modname] = M
setmetatable(M,{__index=_G})    -- package.seeall可以使全局環(huán)境_G對(duì)當(dāng)前環(huán)境可見(jiàn)
local _ENV = M                  -- 設(shè)置當(dāng)前的運(yùn)行環(huán)境為 M,這樣后續(xù)所有代碼都不需要限定模塊名了,所定義的所有函數(shù)自動(dòng)變成M的成員
<函數(shù)定義以及常量定義>

return M                        -- module函數(shù)會(huì)幫你返回module table,而無(wú)需手工返回

對(duì)象

lua 中之所以可以把table當(dāng)成對(duì)象來(lái)用是因?yàn)?

函數(shù)在 lua 中是一類值,你可以直接存取table中的函數(shù)值。 這使得一個(gè)table既可以有自己的狀態(tài),也可以有自己的行為:

?
1
2
3
4
Account = {balance = 0}
function Account.withdraw(v)
 Account.balance = Account.balance - v
end

lua 支持閉包,這個(gè)特性可以用來(lái)模擬對(duì)象的私有成員變量

?
1
2
3
4
5
6
7
8
9
10
function new_account(b)
 local balance = b
 return {withdraw = function (v) balance = balance -v end,
  get_balance = function () return balance end
 }
end
 
a1 = new_account(1000)
a1.withdraw(10)
print(a1.get_balance())

990

不過(guò),上面第一種定義對(duì)象的方法有一個(gè)缺陷,那就是方法與 Account 這個(gè)名稱綁定死了。 也就是說(shuō),這個(gè)對(duì)象的名稱必須為 Accout 否則就會(huì)出錯(cuò)

?
1
2
3
a = Account
Account = nil
a.withdraw(10)     -- 會(huì)報(bào)錯(cuò),因?yàn)锳ccout.balance不再存在

為了解決這個(gè)問(wèn)題,我們可以給 withdraw 方法多一個(gè)參數(shù)用于指向?qū)ο蟊旧?/p>

?
1
2
3
4
5
6
7
8
Account = {balance=100}
function Account.withdraw(self,v)
 self.balance = self.balance - v
end
a = Account
Account = nil
a.withdraw(a,10)     -- 沒(méi)問(wèn)題,這個(gè)時(shí)候 self 指向的是a,因此會(huì)去尋找 a.balance
print(a.balance)

90

不過(guò)由于第一個(gè)參數(shù) self 幾乎總是指向調(diào)用方法的對(duì)象本身,因此 lua 提供了一種語(yǔ)法糖形式 object:method(...) 用于隱藏 self 參數(shù)的定義及傳遞. 這里冒號(hào)的作用有兩個(gè),其在定義函數(shù)時(shí)往函數(shù)中地一個(gè)參數(shù)的位置添加一個(gè)額外的隱藏參數(shù) sef, 而在調(diào)用時(shí)傳遞一個(gè)額外的隱藏參數(shù) self 到地一個(gè)參數(shù)位置。 即 function object:method(v) end 等價(jià)于 function object.method(self,v) end, object:method(v) 等價(jià)于 object.method(object,v)

當(dāng)涉及到類和繼承時(shí),就要用到元表和元方法了。事實(shí)上,對(duì)于 lua 來(lái)說(shuō),對(duì)象和類并不存在一個(gè)嚴(yán)格的劃分。

當(dāng)一個(gè)對(duì)象被另一個(gè)table的 __index 元方法所引用時(shí),table就能引用該對(duì)象中所定義的方法,因此也就可以理解為對(duì)象變成了table的類。

類定義的一般模板為:

?
1
2
3
4
5
function 類名:new(o)
 o = o or {}
 setmetatable(o,{__index = self})
 return o
end

或者

?
1
2
3
4
5
6
function 類名:new(o)
 o = o or {}
 setmetatable(o,self)
 self.__index = self
 return o
end

相比之下,第二種寫法可以多省略一個(gè)table

另外有一點(diǎn)我覺(jué)得有必要說(shuō)明的就是 lua 中的元方法是在元表中定義的,而不是對(duì)象本身定義的,這一點(diǎn)跟其他面向?qū)ο蟮恼Z(yǔ)言比較不同。

總結(jié)

以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)服務(wù)器之家的支持。

原文鏈接:https://lujun9972.github.io/blog/2018/06/17/lua中神奇的table/

延伸 · 閱讀

精彩推薦
  • LuaLua中的元方法__newindex詳解

    Lua中的元方法__newindex詳解

    這篇文章主要介紹了Lua中的元方法__newindex詳解,本文講解了查詢與更新、監(jiān)控賦值、通過(guò)table給另一個(gè)table賦值等內(nèi)容,需要的朋友可以參考下 ...

    笨木頭8872020-04-09
  • LuaLua中table庫(kù)函數(shù)方法介紹

    Lua中table庫(kù)函數(shù)方法介紹

    這篇文章主要介紹了Lua中table庫(kù)函數(shù)方法介紹,本文講解了concat、insert、maxn、remove、sort、foreachi等方法,需要的朋友可以參考下 ...

    腳本之家2502020-04-17
  • LuaLua實(shí)現(xiàn)__add方法重載示例

    Lua實(shí)現(xiàn)__add方法重載示例

    這篇文章主要介紹了Lua實(shí)現(xiàn)__add方法重載示例,本文直接給出實(shí)現(xiàn)代碼,需要的朋友可以參考下 ...

    腳本之家7452020-04-24
  • LuaLua中計(jì)算、執(zhí)行字符串中Lua代碼的方法

    Lua中計(jì)算、執(zhí)行字符串中Lua代碼的方法

    這篇文章主要介紹了Lua中計(jì)算、執(zhí)行字符串中Lua代碼的方法,類似JavaScript中eval函數(shù)的功能,在Lua中也可以實(shí)現(xiàn),需要的朋友可以參考下 ...

    腳本之家6322020-04-30
  • LuaLua教程(二):基礎(chǔ)知識(shí)、類型與值介紹

    Lua教程(二):基礎(chǔ)知識(shí)、類型與值介紹

    這篇文章主要介紹了Lua教程(二):基礎(chǔ)知識(shí)、類型與值介紹,本文講解了Hello World程序、代碼規(guī)范、全局變量、類型與值等內(nèi)容,需要的朋友可以參考下 ...

    腳本之家5922020-04-28
  • LuaLua和C語(yǔ)言的交互詳解

    Lua和C語(yǔ)言的交互詳解

    這篇文章主要介紹了Lua和C語(yǔ)言的交互詳解,Lua和C語(yǔ)言通過(guò)棧完成交互,本文結(jié)合代碼實(shí)例詳細(xì)講解了交互的方法,需要的朋友可以參考下 ...

    果凍想3702020-04-14
  • LuaLua簡(jiǎn)介、編譯安裝教程及變量等語(yǔ)法介紹

    Lua簡(jiǎn)介、編譯安裝教程及變量等語(yǔ)法介紹

    這篇文章主要介紹了Lua簡(jiǎn)介、編譯安裝教程及變量等語(yǔ)法介紹,本文同時(shí)講解了lua注釋語(yǔ)法、Lua命令行方式等內(nèi)容,需要的朋友可以參考下 ...

    junjie3632020-04-14
  • Lua深入探究Lua中的解析表達(dá)式

    深入探究Lua中的解析表達(dá)式

    這篇文章主要介紹了深入探究Lua中的解析表達(dá)式,對(duì)于其語(yǔ)法部分的說(shuō)明和示例都超詳細(xì),極力推薦此文!需要的朋友可以參考下 ...

    腳本之家3542020-05-05
主站蜘蛛池模板: 视频大全在线观看网址 | caoporn人人| 国色天香社区在线视频免费观看 | 国产私拍精品88福利视频 | 国产在线欧美日韩精品一区二区 | 天天舔天天干天天操 | 精品国语对白精品自拍视 | 999导航| 超级乱淫伦小说1女多男 | 日本高清色视频www 日本高清免费观看 | 日韩综合一区 | 日本性生活免费看 | 亚洲色图第一页 | 精品在线一区 | 教师系列 大桥未久在线 | 91香蕉依人综合久久 | 肉文np高h | 欧美久久久久久 | 91精品久久一区二区三区 | 免看一级一片一在线看 | 99久久中文字幕伊人 | 波多野结衣中文字幕在线 | 欧美又硬又粗又长又大 | 日韩成人在线影院 | 久久大胆视频 | 小黄鸭YELLOWDUCK7596 | 国产三级精品三级男人的天堂 | 男女被爆动漫羞羞动漫 | 国产精品福利 | 天堂中文在线观看 | 精品久久久久久亚洲精品 | 欧美xxxxx九色视频免费观看 | 69福利区 | 狠狠插入| 欧美日韩中文国产一区 | 女主被男主为催奶药h | 高清视频在线观看+免费 | 国产色在线观看 | 黄网久久| 肉浦团在线观看 | 精品国语对白精品自拍视 |