设置函数环境——setfenv
當(dāng)我們在全局環(huán)境中定義變量時(shí)經(jīng)常會(huì)有命名沖突,尤其是在使用一些庫的時(shí)候,變量聲明可能會(huì)發(fā)生覆蓋,這時(shí)候就需要一個(gè)非全局的環(huán)境來解決這問題。setfenv函數(shù)可以滿足我們的需求。
setfenv(f, table):設(shè)置一個(gè)函數(shù)的環(huán)境
(1)當(dāng)?shù)谝粋€(gè)參數(shù)為一個(gè)函數(shù)時(shí),表示設(shè)置該函數(shù)的環(huán)境
(2)當(dāng)?shù)谝粋€(gè)參數(shù)為一個(gè)數(shù)字時(shí),為1代表當(dāng)前函數(shù),2代表調(diào)用自己的函數(shù),3代表調(diào)用自己的函數(shù)的函數(shù),以此類推
所謂函數(shù)的環(huán)境,其實(shí)一個(gè)環(huán)境就是一個(gè)表,該函數(shù)被限定為只能訪問該表中的域,或在函數(shù)體內(nèi)自己定義的變量。下面這個(gè)例子,設(shè)定當(dāng)前函數(shù)的環(huán)境為一個(gè)空表,那么在設(shè)定執(zhí)行以后,來自全局的print函數(shù)將不可見,所以調(diào)用會(huì)失敗。
-- 一個(gè)環(huán)境就是一個(gè)表,該表記錄了新環(huán)境能夠訪問的全部域 newfenv = {} setfenv(1, newfenv) print(1) -- attempt to call global `print' (a nil value)我們可以這樣繼承已有的域:
a = 10 newfenv = {_G = _G} setfenv(1, newfenv) _G.print(1) -- 1 _G.print(_G.a) -- 10 _G.print(a) -- nil 注意此處是nil,新環(huán)境沒有a域,但可以通過_G.a訪問_G的a域可以看到,新環(huán)境中可以訪問_G,但有一點(diǎn)就是_G中的所有函數(shù)必須手動(dòng)調(diào)用,這樣其實(shí)很不方便。我們可以使用metatable來對上述代碼進(jìn)行改進(jìn):
-- 任何賦值操作都對新表進(jìn)行,不用擔(dān)心誤操作修改了全局變量表。另外,你仍然可以通過_G修改全局變量: newfenv = {} setmetatable(newfenv, {__index = _G}) setfenv(1, newfenv) print(1) -- 1 新環(huán)境直接繼承了全局環(huán)境的所有域,好處:可以不需要通過_G來手動(dòng)調(diào)用這樣,當(dāng)訪問到函數(shù)中不存在的變量時(shí),會(huì)自動(dòng)在_G中查找。對于當(dāng)前函數(shù)和_G都存在的變量,可以通過是否用_G顯示調(diào)用來區(qū)分,比如如果有兩個(gè)a,那么_G.a表示繼承來的,a就是當(dāng)前函數(shù)環(huán)境的。
另外,可以通過getfenv(f)函數(shù)查看函數(shù)所處的環(huán)境,默認(rèn)會(huì)返回全局環(huán)境_G。
?
?
總結(jié)
以上是生活随笔為你收集整理的设置函数环境——setfenv的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: zabbix监控之二----Zabbix
- 下一篇: 10个迷惑新手的CocoaObjecti