深度學習Lua--環境表

Lua語言將全局環境自身保存在全局變量_G中,如下輸出全局環境中所有全局變量的名稱:

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

  • 具有動態名稱的全局變量

全局變量在另一個變量中的獲取,

value = load("return"..varname)() 和

value = _G[varname] 相同效果,後者效率高出一個數量級。

  • 全局變量聲明

全局變量不需聲明就可以使用,檢測所有全局表不存在的訪問,如下:

setmetatable(_G,{
    __newindex = function (_,n)
        error("attempt to write to undeclared varibale "..n,2)
    end,
    __index = function (_,n)
        error("attempt to read to undeclared varibale "..n,2)
    end,
})

當然可以使用rawset,rawget繞過元方法。

  • 非全局變量

自由名稱(free name)如:x 等價於 _ENV.x,_ENV本身是一個局部變量,是任意表,稱爲一個環境。

Lua處理全局變量的方式:

編譯所有代碼前,在外層創建局部變量_ENV;

所有自由名稱var變換爲_ENV.var;

函數load使用全局環境初始化代碼段的第一個上值,即lua語法內部維護的一個表。

  • 使用_ENV

代碼段(一個文件)都有一個_ENV變量。_ENV = nil 會使後續代碼不能直接訪問全局變量。_ENV主要用途是改變代碼段使用的環境。使用繼承把舊環境裝入如下:

local newgt = {}
setmetatable(newgt, {__index = _G})
_ENV = newget

任何賦值都發生在新表中。只能通過_G來修改全局變量中的變量。

  • 環境和模塊

_ENV解決污染全局變量。

  • _EVN和load

load通常把加載代碼段上值_ENV初始化爲全局環境,還有一個可選參數爲_ENV指定不同初始值。

env = {}
loadfile("config.lua","t",env)()

類似運行在沙盒中。

重複運行一段代碼數次,每次不同環境,兩種選擇如下:

第一種使用debug.setupvalue(f,1,env)

第一個參數是指定函數,第二參數是上值索引(永遠是1),第三參數是新上值。【依賴調試庫,打破可見性規則】

另一種,每次加載代碼段對其修改,如下:

lua把所有代碼段當做可變長參數函數進行編譯,多出來這一行會把傳給代碼段的第一個參數賦值給_ENV,從而改變環境。

prefix = "_ENV = ...;"
f = loadwithprefix(prefix,io.lines(filename,"*L"))
...
env1 = {}
f(env1)
env2 = {}
f(env2)

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章