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

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

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

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

1. 全局變量聲明:

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

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

--該table用于存儲所有已經(jīng)聲明過的全局變量名
local declaredNames = {}
local mt = {
    __newindex = function(table,name,value)
        --先檢查新的名字是否已經(jīng)聲明過,如果存在,這直接通過rawset函數(shù)設(shè)置即可。
        if not declaredNames[name] then
            --再檢查本次操作是否是在主程序或者C代碼中完成的,如果是,就繼續(xù)設(shè)置,否則報錯。
            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è)置時就無需檢查了。
            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)境存在一個剛性的問題,即它的修改將影響到程序的所有部分。Lua 5為此做了一些改進(jìn),新的特征可以支持每個函數(shù)擁有自己獨(dú)立的全局環(huán)境,而由該函數(shù)創(chuàng)建的closure函數(shù)將繼承該函數(shù)的全局變量表。這里我們可以通過setfenv函數(shù)來改變一個函數(shù)的環(huán)境,該函數(shù)接受兩個參數(shù),一個是函數(shù)名,另一個是新的環(huán)境table。第一個參數(shù)除了函數(shù)名本身,還可以指定為一個數(shù)字,以表示當(dāng)前函數(shù)調(diào)用棧中的層數(shù)。數(shù)字1表示當(dāng)前函數(shù),2表示它的調(diào)用函數(shù),以此類推。見如下代碼:

復(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)用將會報錯。

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

復(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)境變量的繼承性。見如下代碼:

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

標(biāo)簽:蘭州 仙桃 崇左 黃山 衡水 湖南 湘潭 銅川

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《Lua教程(十): 全局變量和非全局的環(huán)境》,本文關(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