Lua中的环境,模块和包的知识点简单记录

来源:互联网 发布:淘宝提现手续费是多少 编辑:程序博客网 时间:2024/05/18 01:54

1.环境

lua把所有的全局变量存储在一个名为_G的table中,这样做一来不用为全局变量设置新的数据结构,二来可以像操作table元素一样操作全局变量,可以打印一下_G的所有元素,就能看到我们熟悉的一些函数(例如print等等)
我们可以通过元表来改变访问全局变量时的行为(例如不能访问没有定义的全局变量),这种情况下我们可以通过rawset,rawget函数来绕过元表访问存储全局变量的table.我们还可以通过setfenv函数设置局部环境,局部环境避免了局部行为对全局环境产生的破坏,被创建的函数会继承创建它的函数的环境,当其改变其新环境后,所有后续由它创建的函数也会继承该新环境.

2.模块

模块为lua中的代码共享提供了条件,学习模块前,先了解一下require函数.require是一个模块加载的高层函数,对于它而言,模块就是一段定义了一些值的代码.当调用require时,系统会先在package.loaded 中检查模块是否已经加载,如果是的话就返回该值,并且后续用到时会重复使用该值,不会重新加载,如果没有加载的话,系统就会现在package.preload中传入模块名试着为该模块找一个加载器(系统模块一般都是预加载好的),如果找不到,require就会从Lua文件或者C程序库中加载模块.如果找到Lua文件就会用loadfile来加载文件,如果找到C库就会用loadlib来加载C库,这两个函数都只是加载了代码,并没有运行他们,require会以模块名作为参数来运行代码.如果加载器有返回值,require会把返回值存在package.loaded字段中,如果没有返回值就会package.loaded中的值.这样我们就可以通过将package.loaded["KEY"]的值设置为nil来再次重新加载Key模块.require使用的路径使用的是一种模式匹配的方式,搜索Lua的路径存放在package.path变量下,该变量的值通过环境变量LUA_PATH来设置,搜索C库的路径存放在变量package.cpath中,该变量的值通过环境变量LUA_CPATH来设置.
编写模块的方法,最简单的是创建一个table,将所有需要导出的函数放入其中,最后返回这个table.
mModule ={}mModule.add = function () print("this is a module") endreturn mModule
这样有很多缺点,首先必须显示将模块名加在每个函数前面,其次一个函数调用模块内的另一个函数也必须显示限定名称,因此改为下面的方式:
local M ={}mModule=MM.add = function () print("this is a module") endreturn mModule
这样虽然仍然需要一个前缀M但至少不再依赖于模块名,其实完全不需写模块名,因为require加载时会把模块名当参数传进去,而且可以直接将模块名赋值给package.loaded["模块名"],所以去掉return语句,再改为下面方式:
local M ={}local mModule= ..._G[mModule] = Mpackage.loaded[mModule]=MM.add = function () print("this is a module") end
这样虽然已经具有了通用性,但是需要程序员编写代码的时候特别注意,如果一个函数改变了访问属性那么其他的调用它的函数都要改,于是引入环境来解决这个问题:
local M ={}local mModule= ..._G[mModule] = Mpackage.loaded[mModule]=Msetmetatable(M,{__index=_G})setfenv(1,M)add = function () print("this is a module") end
这样我们在写add函数时就不要加模块名前缀了,当调用模块内的其它函数时也不用加模块名前缀了,因为每个模块编写都有类似的开头,lua为了简化帮我们定义了一个函数module,它帮我们做了上述的大部分工作,这样我们前面定义的模块可以这样写moduke(...),默认情况下module不提供外部访问,可以在定义模块时加一个package.seeall来完成该项工作.于是上面的例子改为module(...,package.seeall)
当我们以require(“a.b”)的方式去加载一个模块时,lua会以a.b去package.loaded和packagepreloaded中去查找,但是去搜索一个该模块的文件时会将.转换为目录分隔符去查找相应的文件.这样就可以将一些包的模块组织到一个目录中.



原创粉丝点击