Lua中的函数环境、_G及_ENV
lua5.1中的全局環境變量
Lua將環境table保存在一個全局變量_G中,可以對其訪問和設置。一般我們把需要被訪問的對象和函數等放到這里,
然后我們可以在需要時通過它來訪問和使用。
可以通過value = _G["varname"]或者value = _G.varname來獲得動態名字的全局變量。
“環境”是全局的,任何對它的修改都會影響程序的所有部分。對簡單的使用不會有什么問題,但較復雜的應用,這個會是一大潛在的問題
Lua5.1中改變環境 - setfenv
Lua5.1允許每個函數擁有一個子集的環境來查找全局變量,可以通過setfenv來改變一個函數的環境,
第一個參數若是1則表示當前函數,2則表示調用當前函數的函數(依次類推),第二個參數是一個新的環境table。
比如下面,修改了函數的環境, print不存在了,再訪問就會出錯。
va = 1 setfenv(1, {}) print(va) -- 會報錯,print是一個nil。這是因為一旦改變環境,所有的全局訪問都會使用新的table為了避免上述問題,可以使用
setfenv(1, {_G = _G})將原來的環境保存起來,然后用_G.print來引用。
另一種組裝新環境的方法是使用繼承,下面的代碼新環境從源環境中繼承了print和a,任何賦值都發生在新的table中。
a = 1 local newgt = {} setmetatable(newgt, {__index = _G}) setfenv(1, newgt) print(a)或者
a = 1 local newgt = {} setmetatable(newgt, {__index = _G})示例:
a = "1" -- create a global variable print(a, getmetatable(a)) local t ={} setmetatable(t, {__index = _G}) setfenv(1, t) -- 設置當前的func-env為t print(a)---- _G.print("_G:", a) -- _G: 1 t.print("t: ", a) -- t: 1setfenv(a, {}) -- change current environment to a new empty table print(a) -- attempt to call global 'print' (a nil value)Lua5.1之后的環境
在5.2之后, 引入了_ENV叫做環境,與_G全局變量表產生了一些混淆。
在5.2中, 操作a = 1相當于_ENV['a'] = 1
這是一個最基礎的認知改變,其次要格外注意_ENV不是全局變量,而是一個upvalue(非局部變量)。
其次,_ENV[‘_G’]指向了_ENV自身,這一目的是為了兼容5.1之前的版本,因為之前你也許會用到:
_G['a'] = 2, 在5.2中, 這相當于_ENV[‘_G’][‘a’],為了避免5.1之前的老代碼在5.2中運行錯誤,所以5.2設置了_ENV[‘_G’]=_ENV來兼容這個問題。然而你不要忘記_ENV[‘_G’]=_ENV,所以一切都順理成章了。
在5.1中,我們可以為一段代碼塊(或者函數)設置環境,使用函數setfenv,這樣會導致那一段代碼/數訪問全局變量的時候使用了setfuncs指定的table,而不是全局的_G。
在5.2中,setfenv遭到了廢棄,因為引入了_ENV。 通過在函數定義前覆蓋_ENV變量即可為函數定義設置一個全新的環境,比如:
a = 3 function echo()local _ENV={print=print, a = 2}function _echo()_ENV.print(a)endreturn _echo; endprint(a) -- 3---- local newEcho = echo() print(newEcho) -- function: 0x7fd1b94065c0 newEcho() -- 2總結
以上是生活随笔為你收集整理的Lua中的函数环境、_G及_ENV的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 雷军狂喜!小米在印度节假日期间销售超10
- 下一篇: MSP430F149的ADC12应用