日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Lua中的函数环境、_G及_ENV

發布時間:2023/12/15 编程问答 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Lua中的函数环境、_G及_ENV 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

lua5.1中的全局環境變量

Lua將環境table保存在一個全局變量_G中,可以對其訪問和設置。一般我們把需要被訪問的對象和函數等放到這里,
然后我們可以在需要時通過它來訪問和使用。
可以通過value = _G["varname"]或者value = _G.varname來獲得動態名字的全局變量。

> a=1 > b= "b" > print(_G[a]) nil > print(_G["a"]) 1 > print(_G["b"]) b > print(_G.a) 1 > print(_G.b) b

“環境”是全局的,任何對它的修改都會影響程序的所有部分。對簡單的使用不會有什么問題,但較復雜的應用,這個會是一大潛在的問題

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,所以一切都順理成章了。

> a = 1 > _ENV[a] nil > _ENV["a"] 1 > _ENV["_G"] table: 0x7fab5c5002e0 > print(_ENV) table: 0x7fab5c5002e0 > > _G["a"] 1 > _ENV._G.a 1 > _ENV["_G"].a 1 > _ENV["_G"]["a"] 1 >

在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的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。