濮阳杆衣贸易有限公司

主頁(yè) > 知識(shí)庫(kù) > Lua教程(十): 全局變量和非全局的環(huán)境

Lua教程(十): 全局變量和非全局的環(huán)境

熱門(mén)標(biāo)簽:新岸線(xiàn)智能電銷(xiāo)機(jī)器人 怎么去除地圖標(biāo)注 地圖標(biāo)注大廈 清朝地圖標(biāo)注哈爾濱 冀州市地圖標(biāo)注 百度地圖標(biāo)注早餐區(qū)域 個(gè)人怎么在地圖標(biāo)注需要的店鋪 武漢外呼防封系統(tǒng)多少錢(qián) 漳州智云呼電話(huà)機(jī)器人

Lua將其所有的全局變量保存在一個(gè)常規(guī)的table中,這個(gè)table被稱(chēng)為“環(huán)境”。它被保存在全局變量_G中。

1. 全局變量聲明:

Lua中的全局變量不需要聲明就可以使用。盡管很方便,但是一旦出現(xiàn)筆誤就會(huì)造成難以發(fā)現(xiàn)的錯(cuò)誤。我們可以通過(guò)給_G表加元表的方式來(lái)保護(hù)全局變量的讀取和設(shè)置,這樣就能降低這種筆誤問(wèn)題的發(fā)生幾率了。見(jiàn)如下示例代碼:

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

--該table用于存儲(chǔ)所有已經(jīng)聲明過(guò)的全局變量名
local declaredNames = {}
local mt = {
    __newindex = function(table,name,value)
        --先檢查新的名字是否已經(jīng)聲明過(guò),如果存在,這直接通過(guò)rawset函數(shù)設(shè)置即可。
        if not declaredNames[name] then
            --再檢查本次操作是否是在主程序或者C代碼中完成的,如果是,就繼續(xù)設(shè)置,否則報(bào)錯(cuò)。
            local w = debug.getinfo(2,"S").what
            if w ~= "main" and w ~= "C" then
                error("attempt to write to undeclared variable " .. name)
            end
            --在實(shí)際設(shè)置之前,更新一下declaredNames表,下次再設(shè)置時(shí)就無(wú)需檢查了。
            declaredNames[name] = true
        end
        print("Setting " .. name .. " to " .. value)
        rawset(table,name,value)
    end,
   
    __index = function(_,name)
        if not declaredNames[name] then
            error("attempt to read undeclared variable " .. name)
        else
            return rawget(_,name)
        end
    end
}   
setmetatable(_G,mt)

a = 11
local kk = aa

--輸出結(jié)果為:
--[[
Setting a to 11
lua: d:/test.lua:21: attempt to read undeclared variable aa
stack traceback:
        [C]: in function 'error'
        d:/test.lua:21: in function d:/test.lua:19>
        d:/test.lua:30: in main chunk
        [C]: ?
--]]

 2. 非全局的環(huán)境:

全局環(huán)境存在一個(gè)剛性的問(wèn)題,即它的修改將影響到程序的所有部分。Lua 5為此做了一些改進(jìn),新的特征可以支持每個(gè)函數(shù)擁有自己獨(dú)立的全局環(huán)境,而由該函數(shù)創(chuàng)建的closure函數(shù)將繼承該函數(shù)的全局變量表。這里我們可以通過(guò)setfenv函數(shù)來(lái)改變一個(gè)函數(shù)的環(huán)境,該函數(shù)接受兩個(gè)參數(shù),一個(gè)是函數(shù)名,另一個(gè)是新的環(huán)境table。第一個(gè)參數(shù)除了函數(shù)名本身,還可以指定為一個(gè)數(shù)字,以表示當(dāng)前函數(shù)調(diào)用棧中的層數(shù)。數(shù)字1表示當(dāng)前函數(shù),2表示它的調(diào)用函數(shù),以此類(lèi)推。見(jiàn)如下代碼:

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

a = 1
setfenv(1,{})
print(a)

--輸出結(jié)果為:
--[[
lua: d:/test.lua:3: attempt to call global 'print' (a nil value)
stack traceback:
        d:/test.lua:3: in main chunk
        [C]: ?
--]]

為什么得到這樣的結(jié)果呢?因?yàn)閜rint和變量a一樣,都是全局表中的字段,而新的全局表是空的,所以print調(diào)用將會(huì)報(bào)錯(cuò)。

為了應(yīng)對(duì)這一副作用,我們可以讓原有的全局表_G作為新全局表的內(nèi)部表,在訪(fǎng)問(wèn)已有全局變量時(shí),可以直接轉(zhuǎn)到_G中的字段,而對(duì)于新的全局字段,則保留在新的全局表中。這樣即便是函數(shù)中的誤修改,也不會(huì)影響到其他用到全局變量(_G)的地方。見(jiàn)如下代碼:

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

a = 1
local newgt = {}  --新環(huán)境表
setmetatable(newgt,{__index = _G})
setfenv(1,newgt)
print(a)  --輸出1

a = 10
print(a)  --輸出10
print(_G.a) --輸出1
_G.a = 20
print(a)  --輸出10

最后給出的示例是函數(shù)環(huán)境變量的繼承性。見(jiàn)如下代碼:

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

function factory()
    return function() return a end
end
a = 3
f1 = factory()
f2 = factory()
print(f1())  --輸出3
print(f2())  --輸出3

setfenv(f1,{a = 10})
print(f1())  --輸出10
print(f2())  --輸出3

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

標(biāo)簽:臺(tái)灣 宣城 金昌 德宏 天門(mén) 濰坊 儋州 天門(mén)

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《Lua教程(十): 全局變量和非全局的環(huán)境》,本文關(guān)鍵詞  Lua,教程,十,全局,變量,和,;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問(wèn)題,煩請(qǐng)?zhí)峁┫嚓P(guān)信息告之我們,我們將及時(shí)溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無(wú)關(guān)。
  • 相關(guān)文章
  • 下面列出與本文章《Lua教程(十): 全局變量和非全局的環(huán)境》相關(guān)的同類(lèi)信息!
  • 本頁(yè)收集關(guān)于Lua教程(十): 全局變量和非全局的環(huán)境的相關(guān)信息資訊供網(wǎng)民參考!
  • 推薦文章
    玉山县| 民勤县| 巴楚县| 老河口市| 连云港市| 远安县| 北安市| 登封市| 太原市| 沁源县| 吉林省| 永靖县| 阳朔县| 甘洛县| 博客| 青浦区| 楚雄市| 通河县| 九龙坡区| 朝阳区| 江源县| 夏邑县| 万盛区| 阿图什市| 东丽区| 大石桥市| 甘南县| 徐汇区| 镇赉县| 兖州市| 隆子县| 晋中市| 时尚| 上栗县| 栾城县| 普定县| 根河市| 融水| 分宜县| 宜春市| 双桥区|