设置函数环境——setfenv(转)

  当我们在全局环境中定义变量时经常会有命名冲突,尤其是在使用一些库的时候,变量声明可能会发生覆盖,这时候就需要一个非全局的环境来解决这问题。setfenv函数可以满足我们的需求。

  setfenv(f, table):设置一个函数的环境

  (1)当第一个参数为一个函数时,表示设置该函数的环境

  (2)当第一个参数为一个数字时,为1代表当前函数,2代表调用自己的函数,3代表调用自己的函数的函数,以此类推

  所谓函数的环境,其实一个环境就是一个表,该函数被限定为只能访问该表中的域,或在函数体内自己定义的变量。下面这个例子,设定当前函数的环境为一个空表,那么在设定执行以后,来自全局的print函数将不可见,所以调用会失败。

-- 一个环境就是一个表,该表记录了新环境能够访问的全部域
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,新环境没有a域,但可以通过_G.a访问_G的a域

  可以看到,新环境中可以访问_G,但有一点就是_G中的所有函数必须手动调用,这样其实很不方便。我们可以使用metatable来对上述代码进行改进:

-- 任何赋值操作都对新表进行,不用担心误操作修改了全局变量表。另外,你仍然可以通过_G修改全局变量:
newfenv = {}
setmetatable(newfenv, {__index = _G})
setfenv(1, newfenv)
print(1)        -- 1 新环境直接继承了全局环境的所有域,好处:可以不需要通过_G来手动调用

  这样,当访问到函数中不存在的变量时,会自动在_G中查找。对于当前函数和_G都存在的变量,可以通过是否用_G显示调用来区分,比如如果有两个a,那么_G.a表示继承来的,a就是当前函数环境的。

  另外,可以通过getfenv(f)函数查看函数所处的环境,默认会返回全局环境_G。

http://www.cnblogs.com/sifenkesi/p/3843348.html

时间: 2024-11-02 03:58:38

设置函数环境——setfenv(转)的相关文章

Lua的函数环境、包实例讲解_Lua

复制代码 代码如下: function foo()    print(g or "No g defined!") end foo() setfenv(foo, { g = 100, print = print }) --设置foo的环境为表{ g=100, ...} foo() print(g or "No g defined!") --No g defined! --100 --No g defined! 定义:函数环境就是函数在执行时所见的全局变量的集合,以一个

lua设置非全局变量,设置当前环境变量相关问题

问题描述 lua设置非全局变量,设置当前环境变量相关问题 a="world" local newtable={} setmetatable(newtable, {_index=_G}) setfenv(1,newtable) b="hello" print(b) print(a) ................ 以上这段代码,为啥会报错呢?错误如下: lua: noglobal.lua:6: attempt to call global 'print' (a ni

Linux(Ubuntu)下设置golang环境变量

1).源代码安装go语言 Go的工具链采用C语言编写,要构建它,你需要安装一个C编译器,本例采用gcc工具; 进入linux 终端,输入命令行 sudo apt-get install build-essential Go使用Mercurial进行版本管理,首先你必须安装了Mercurial,对于 Ubuntu/Debian 系统先安装easy_install; sudo apt-get install mercurial 出现Processing triggers for python-sup

设置Ubuntu环境变量 PATH 的方法 及配置备份

在Ubuntu中有如下几个文件可以设置环境变量  /etc/profile:在登录时,操作系统定制用户环境时使用的第一个文件,此文件为系统的每个用户设置环境信息,当用户第一次登录时,该文件被执行.  /etc/environment:在登录时操作系统使用的第二个文件,系统在读取你自己的profile前,设置环境文件的环境变量  ~/.profile:在登录时用到的第三个文件是.profile文件,每个用户都可使用该文件输入专用于自己使用的shell信息,当用户登录时,该文件仅仅执行一次!默认情况

ide-Android如何设置开发环境?

问题描述 Android如何设置开发环境? 不知道Google是全国范围内的禁用,还是个别地区的禁用.大家在设置自己的开发环境的时候,有没有遇到IDE不能升级,SDK不能安装或升级的情况?大家如何绕过的... 是通过修改hosts文件吗?我现在的情况是修改hosts后,SDK可以升级或安装.但是IDE就无法访问升级服务器了.反之亦然. 现在SDK Manager无法运行,点击直接没反应,而不是网上普遍反应的一闪即逝,我的连闪都不闪. SDK Manager 的可执行文件在哪里?AndroidSt

教你设置Java环境变量

JDK安装成功之后,测试是否真的已成功安装,在命令提示符里面输入"java -version"并按回车键,若出现如下版本信息: java version "1.6.0_26" Java(TM) SE Runtime Environment (build 1.6.0_26-b03) Java HotSpot(TM) Client VM (build 20.1-b02, mixed mode, sharing) 则表明JDK已安装成功. 下面是说明怎么设置Java环境变

Windows 7下node.js设置npm环境变量

前面日志中的例子需运行"npm install formidable"指令安装模块支持文件上传. 如果浏览器有代理服务器,或者办公环境封杀了https,则需要设置npm环境变量. 我看到的错误提示信息是这样: npm ERR! Error: failed to fetch from registry: formidable 首先查看环境变量默认值(没准将来想设回去): >npm config get proxy null >npm config get registry h

Ubuntu设置shell环境变量

Ubuntu设置shell环境变量 打开配置文件: vim ~/.bashrc 在文件的末尾,添加如下 export 变量名=变量 如:export JAVA_HOME=/usr/lib/jvm/java-6-sunexport PATH=$PATH:~/mybin 注销并重新登录,新的环境变量就生效了. 在http://www.aliyun.com/zixun/aggregation/13835.html">Ubuntu中有如下几个文件可以设置环境变量 /etc/profile:在登录时

《AutoCAD 2013中文版从入门到精通》——1.2 设置绘图环境

1.2 设置绘图环境 AutoCAD 2013中文版从入门到精通 在AutoCAD中,可以利用相关命令对图形单位和图形边界进行具体设置. 1.2.1 图形单位设置 执行方式 命令行:DDUNITS(或UNITS) 菜单栏:"格式"→"单位 操作步骤 执行上述命令后,系统打开"图形单位"对话框,如图1-21所示.该对话框用于定义单位和角度格式. 选项说明 1."长度"与"角度"选项组 指定测量的长度与角度当前单位及当前