全局变量和局部变量(local variable)
Posted 森明帮大于黑虎帮
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了全局变量和局部变量(local variable)相关的知识,希望对你有一定的参考价值。
全局变量(global variable)
在Lua中定义全局变量非常简单,就是定义变量的时候,前面不要加上local。
这个神秘的全局变量,其实本质上也是一个table,它把我们创建的全局变量都保存到一个table里。
这个table的名字是:_G。
gName = "globalVar"
print(gName)
print(_G.gName)
print(_G["gName"])
-- result:
--> globalVar
--> globalVar
--> globalVar
我们定义了一个全局变量gName,于是这个gName成为了_G的一个字段。
使用全局变量会有命名冲突和效率问题,因此我们在适用情况下往往使用局部变量。
局部变量(local variable)
局部变量只在被声明的哪个代码块内有效。
代码块:控制结构、函数、chunk(变量被声明的那个文件或者文本串)。
local fLocal = function(n)
if (n == 1) then
return n;
else
return n + fLocal(n-1)
end
end
print("result:", fLocal(2))
会报错:attempt to call global ‘fLocal’ (a nil value)。
同样的道理,也是有两种修改方式:
-
提前声明fLocal
分析一下,函数fLocal中是不能识别自己的,那么编译器在到这里的时候还不能认识fLocal。这让我想起来某个语言的定义(具体是什么忘记了):只有匹配到””,才算定义完毕,编译器才会识别这个定义。那是什么意思呢?拿这里的local fLocal来说只有编译器解释到“end”的时候才表示fLocal定义完毕,才会有这个变量,不然都是非法的,所以解决办法就是把fLocal单独拿出来,这样编译器扫描一遍的时候就认识了,不会报错。local fLocal fLocal = function(n) if (n == 1) then return n; else return n + fLocal(n-1) end end print("result:", fLocal(2))
特例
Lua local function和function
- 使用function声明的函数(全局函数)时,引用时不会因为声明的顺序找不到。
- 使用local function声明的函数(局部函数)时,引用必须在函数声明后。
function test()
test1()
test2()
end
function test1()
print("test1")
end
local function test2()
print("test2")
end
test()
会报错:attempt to call global ‘test2’ (a nil value)
有两种修改方法:
- 将local function test2的声明放到function test前面。
- 将local function test2修改为function test2。
Lua local table和table
为什么local table比较特殊呢?首先,我们知道table的赋值与其他基本类型变量不同,是引用赋值
v1 = 1
v2 = v1 --创建了一个新的变量v2,v2的值与v1相同
v1 = nil
t1 = v=100
t2 = t1 --只是为t1起了一个别名t2
t1.v = nil
print(v1,v2,t1.v,t2.v)
因此要注意:避免local表引用global表
a = 1
do
local a = a --创建了一个局部变量a,赋值为全局变量a的值1
a = 2
print(a) --2
end
print(a) --1
t =
t.a = 1
do
local t = t --这种写法是错误的,因为这里创建了一个局部表t,引用了全局表t,实际上是同一张全局表,失去了local的作用
t.a = 2
print(t.a) --2
end
print(t.a) --2
Note:
1.Lua 中的变量全是全局变量,无论语句块或是函数里,除非用 local 显式声明为局部变量,变量默认值均为nil。
2.使用local创建一个局部变量,与全局变量不同,局部变量只在被声明的那个代码块内有效。(代码块:指的是一个控制结构内,一个函数体,或者一个chunk(变量被声明的那个文件或者文本串))。
x = 10
local i = 1 --local to the chunk
while i <= x do
local x = i * 2 --local to the while body
print(x)
i = i + 1
end
if i > 20 then
local x -- local to the "then" body
x = 20
print(x + 2)
else
print(x)
end
print(x)
运行结果:
2
4
6
8
10
12
14
18
20
10
10
注意:如果在交互模式下上面的例子可能不能输出如期结果,因为第二句的local i=1是一个完整的chunk,在交互模式下执行完这一句后,Lua 将开始一个新的chunk,这样第二句的i 已经超出他的有效范围。可将这段代码放在do…end中(相当于C的…)。
3.尽可能使用局部变量,有两个好处:
-
避免命名冲突。
-
访问速度更快(原因是local变量是存放在lua的堆栈里面的是array操作,而全局变量是存放在_G中的table中,效率不及堆栈)。
Lua中的函数可以作为全局变量也可作为局部变量,当我们将函数保存在一个局部变量里时,我们将得到一个局部函数。局部函数和局部变量一样在一定范围内有效。
- 使用function声明的函数为全局函数,在被引用时可以不会因为声明的顺序而找不到 。
- 使用local function声明的函数为局部函数,在引用的时候必须要在声明的函数后面。
function test()
test2()
test1()
end
local function test1()
print("hello test1")
end
function test2()
print("hello test2")
end
test()
会报错:attempt to call global ‘test2’ (a nil value)
有两种修改方法:
- 将local function test1的声明放到function test前面。
- 将local function test1修改为function test1。
5.其他补充:
- local变量过多也会有堆栈溢出的问题,一段过程下最多拥有200个local变量,且
do end
不算。类似这样:
local Class =
local test1 = 1
local test2 = 2
... --to 199
return Class
如果超过199,则会报出main function has more than 200 local variables的错误。当然这里说的是一段过程,所以函数是另算的,同样一个函数的过程最多也不能超过200个local变量(调用函数则算转入下一个过程了)。
- 模块级local变量暂无限制,但是也要考虑到热更新方面的问题:若是选择使用模块级local变量去存储模块的数据,那么在热更新方面的处理将会变得十分麻烦。从这点考虑的话,模块级local变量最好只是用于引用别的模块为妙。
以上是关于全局变量和局部变量(local variable)的主要内容,如果未能解决你的问题,请参考以下文章
全局变量报错:UnboundLocalError: local variable 'l' referenced before assignment
python中的本地变量(local variable)和全局变量(global variable)分别是啥?
全局变量报错:UnboundLocalError: local variable 'l' referenced before assignment
The difference between a local variable and a member variable