佳木斯湛栽影视文化发展公司

主頁 > 知識庫 > Lua中的全局變量、非全局變量總結(jié)

Lua中的全局變量、非全局變量總結(jié)

熱門標簽:服務(wù)外包 地方門戶網(wǎng)站 Linux服務(wù)器 網(wǎng)站排名優(yōu)化 百度競價排名 鐵路電話系統(tǒng) AI電銷 呼叫中心市場需求

前言

Lua將其所有的全局變量保存在一個常規(guī)的table中,這個table稱為“環(huán)境”。這種組織結(jié)構(gòu)的優(yōu)點在于,其一,不需要再為全局變量創(chuàng)造一種新的數(shù)據(jù)結(jié)構(gòu),因此簡化了Lua的內(nèi)部實現(xiàn);另一個優(yōu)點是,可以像其他table一樣操作這個table。為了便于實施這種操作,Lua將環(huán)境table自身保存在一個全局變量_G中。例如,我們可以使用以下代碼打印當(dāng)前環(huán)境中所有全局變量的名稱。

復(fù)制代碼 代碼如下:

for n in pairs(_G) do print(n) end

在你的電腦上運行一下以上代碼,看看結(jié)果。

全局變量聲明

在Lua中,全局變量不需要聲明就可以直接使用,但是這樣違反了編程的大忌,隨便使用全局變量,將導(dǎo)致程序的性能,當(dāng)出現(xiàn)bug時,也很難去發(fā)現(xiàn),同時也污染了程序中的命名??紤]到全局變量也是存放在一個table中,我們則可以通過元表來改變其它代碼訪問全局變量時的行為,看到了么?又是元表。代碼如下:

復(fù)制代碼 代碼如下:

setmetatable(_G, {
     __newindex = function (_, k)
          error("Attempt to write to undeclared variable " .. k)
     end,
     __index = function (_, k)
          error("Attempt to read undeclared variable " .. k)
     end
})
 
print(a) -- 這里a就是一個全局變量

而有的時候,我們的確需要定義一個全局變量,那怎么辦?還記得我在《Lua中的元表與元方法》這篇文章中寫的嗎?使用rawset就可以完成,它是不同過元表的,直接設(shè)置table的值;同時,為了測試一個變量是否存在,就不能簡單的將它與nil比較。因為如果它為nil,訪問就會拋出一個錯誤,同樣,我們可以使用rawget來繞過元方法。

非全局的變量

由于“環(huán)境”這個概念是全局的,任何對他的修改都會影響程序的所有部分。例如:若安裝一個元表用于控制全局變量的訪問,那么整個程序都必須遵循這個規(guī)范。但使用某個庫時,沒有先聲明就使用了全局變量,那么這個程序就無法運行了。

可以通過函數(shù)setfenv來改變一個函數(shù)的環(huán)境。該函數(shù)的參數(shù)是一個函數(shù)和一個新的環(huán)境table。第一個參數(shù)除了可以指定為函數(shù)本身,還可以指定為一個數(shù)字,以表示當(dāng)前函數(shù)調(diào)用棧中的層數(shù)。數(shù)字1表示當(dāng)前函數(shù),數(shù)字2表示調(diào)用當(dāng)前函數(shù)的函數(shù),以此類推。首先來一小段代碼:

復(fù)制代碼 代碼如下:

a = 1 -- 這里創(chuàng)建了一個全局變量
 
-- 將當(dāng)前環(huán)境變量改為一個新的空table
setfenv(1, {})
print(a)

運行代碼會彈出這樣的錯誤:attempt to call global ‘print' (a nil value)

print是存放在_G中的,由于我們將當(dāng)前的環(huán)境變量重置為了一個空的table,導(dǎo)致找不到print了,所以就出現(xiàn)了錯誤。為了防止這樣的錯誤的放生,在我們改變當(dāng)前的環(huán)境變量之前,我們需要保存當(dāng)前的環(huán)境變量。看下面的代碼:

復(fù)制代碼 代碼如下:

a = 1 -- 這里創(chuàng)建了一個全局變量
 
-- 將當(dāng)前環(huán)境變量改為一個新的空table
setfenv(1, {g = _G})
g.print(a)          -- 輸出nil
g.print(g.a)     -- 輸出1

這個時候訪問g就會得到原來的環(huán)境,這個環(huán)境中包含了字段print。我們可以使用名字_G來代替g,如下述代碼:
復(fù)制代碼 代碼如下:

a = 1 -- 這里創(chuàng)建了一個全局變量
 
-- 將當(dāng)前環(huán)境變量改為一個新的空table
setfenv(1, {_G = _G})
_G.print(a)          -- 輸出nil
_G.print(_G.a)     -- 輸出1

不要忘了我們之前總結(jié)的__index元方法,我們可以設(shè)置新的環(huán)境變量的__index為_G,這樣,當(dāng)在新的環(huán)境中找不到對應(yīng)的變量時,就會去_G中找,這樣,就相當(dāng)于新的環(huán)境變量繼承了全局的環(huán)境變量_G,看以下代碼:

復(fù)制代碼 代碼如下:

a = 1 -- 這里創(chuàng)建了一個全局變量
 
local newEnv = {}
setmetatable(newEnv, {__index = _G})
 
-- 將當(dāng)前環(huán)境變量改為一個新的空table
setfenv(1, newEnv)
print(a)

在Lua中,函數(shù)會繼承創(chuàng)建其的環(huán)境,所以一個程序塊若改變了它自己的環(huán)境,那么后續(xù)由它創(chuàng)建的函數(shù)都將共享這個新環(huán)境。這項機制對于創(chuàng)建名稱空間是很有用的。之后的總結(jié)中還會繼續(xù)講解的。

您可能感興趣的文章:
  • Lua中的變量類型與語句學(xué)習(xí)總結(jié)
  • Lua中的變量和流控制入門學(xué)習(xí)
  • 詳解Lua中的變量相關(guān)知識點
  • Lua教程(十): 全局變量和非全局的環(huán)境
  • Lua判斷變量是否為數(shù)字、字符串是否可以轉(zhuǎn)換為數(shù)字等
  • Lua中創(chuàng)建全局變量的小技巧(禁止未預(yù)期的全局變量)
  • C語言中通過LUA API訪問LUA腳本變量的簡單例子
  • Lua變量類型簡明總結(jié)
  • Lua中全局變量與非全局環(huán)境介紹
  • Lua中的變量與賦值方法

標簽:衡水 湖南 湘潭 黃山 蘭州 崇左 銅川 仙桃

巨人網(wǎng)絡(luò)通訊聲明:本文標題《Lua中的全局變量、非全局變量總結(jié)》,本文關(guān)鍵詞  ;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問題,煩請?zhí)峁┫嚓P(guān)信息告之我們,我們將及時溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無關(guān)。
  • 相關(guān)文章
  • 收縮
    • 微信客服
    • 微信二維碼
    • 電話咨詢

    • 400-1100-266
    东莞市| 宜春市| 哈密市| 巫山县| 南郑县| 仁怀市| 通山县| 章丘市| 庄河市| 南宫市| 二连浩特市| 宁晋县| 扎赉特旗| 赤峰市| 图木舒克市| 长海县| 武陟县| 河间市| 乐山市| 张家港市| 阆中市| 哈尔滨市| 汝城县| 旌德县| 大庆市| 湘乡市| 汉寿县| 津市市| 宽城| 商洛市| 昭平县| 辉县市| 阜康市| 玛沁县| 平谷区| 拉孜县| 赫章县| 安新县| 仪陇县| 磴口县| 竹溪县|