多变量同时赋值
Lua可以对多个变量同时赋值,变量列表和值列表的各个元素用逗号分开,赋值语句右边的值会依次赋给左边的变量。当变量个数和值的个数不一致时:
- 左侧变量列表如果多出,多出的部分被置为nil;
- 右侧值列表如果多出,最末多出的部分被抛弃。
a, b, c, d = 1, 2, 3
print(a, b, c, d) --1 2 3 nil
a, b, c = 4, 3, 2, 1
print(a, b, c, d) --4 3 2 nil
执行赋值语句时Lua会先计算右边所有的值,然后再执行赋值操作,所以我们可以这样交换变量的值
a, b = 1, 2
a, b = b, a --等价于执行 a, b = 2, 1
拷贝赋值、引用赋值问题
这两个词是来自其他语言,Lua也需要注意这个问题。在Lua中可以用C语言的指针来理解,即把Lua变量看作是C语言的指针,下面来用不同类型的数据看Lua变量赋值的情况。
示例1,数字类型:
a = 3 -- a变量类似C语言的一个指针,指向一块内存区域,这块内存的内容是3
b = a -- 把a指针的指向的地址,赋值给b,此时a,b指向同一块内存,都是3
print(a, b) -- 3 3
a = 4 -- 修改a指针的地址,指向一个新的内存,存储的值是4,此时b指针还是指向原来的内存,没有改变
print(a, b) -- 4 3
b = a
a = nil -- 把a指针清空,只是清除了a指针保存的地址,没有清除指向地址所存储的内容
print(a, b) -- nil 3
示例2,字符串类型:
-- 字符串变量的赋值,和数值原理相同
a = "A"
b = a
a = "a"
print(b) --A
a = nil
print(b) --A
示例3,表类型:
a = { key = 'value1' }
b = a -- 把a赋值给b,此时a,b指向同一块内存地址
for key, value in pairs(b) do
print(key, value) --key value1
end
a['key'] = 'value2' -- 修改a指向内存存储的值,因为此时a,b指向同一块内存,b也会被影响
for key, value in pairs(b) do
print(key, value) --key value2
end
a = nil -- 把a指针设置为nil,原来指向的内存没被改变,b指向还是指向原来的内存,不受影响
for key, value in pairs(b) do
print(key, value) --key value2
end
示例4,还是表类型:
a = { key = 'value1' }
b = a
a = { key = 'value2' } -- 把a指针指向一块新的内存地址,此时a,b指针指向不再相同,b的指向和对应的内存没变
for key, value in pairs(b) do
print(key, value) --key value1
end
a = { key = 'value1' }
b = a
a = nil -- 把a指针设置为nil,原来指向的内存没被改变,b指向还是指向原来的内存,不受影响
for key, value in pairs(b) do
print(key, value) --key value1
end
上面的几种示例,都是进行了这几步操作
- 对a赋一个初始值
- 把a赋值给b
- 修改a
- 看b是否也被修改
然后步骤4的结果表现出不一致的情况,数字类型(示例1)和字符串类型(示例2)的b不会被修改,而表类型却有的被修改(示例3),有的没被修改(示例4)。最根本的原因在于第3步修改a时,是否在修改了a的指向。
如果没有修改a的指向,而是修改a指向地址所存储的值,则b也会被影响,如:
a['key'] = 'value2'
如果修改a是修改了a指向的地址,则b不被影响,如:
a = 4
a = 'a'
a = { key = 'value3' }
其他赋值形式
赋值除了用等号之外,还有其他的赋值形式,如参数的传递、函数的返回等也是赋值操作,如:
a = { key = 'value1' }
local function change_table_value(b)
-- 把实参a传入此函数,相当于执行了 b = a;
-- 此时a,b指向同一块内存,下面的改动没有改变a,b指针的指向,但是改变了他们指向地址所存储的内容
b.key = 'value2'
end
change_table_value(a)
for key, value in pairs(a) do
print(key, value) --key value2
end
a = { key = 'value1' }
local function change_to_new_table(b)
-- 此时a,b指向同一块内存,下面的改动把b指向一块新的内存,没有改变a指针的指向,更没有改变a指向内存存储的内容
b = { key = 'value2' }
end
change_to_new_table(a)
for key, value in pairs(a) do
print(key, value) --key value1
end
上例可以看出其他形式的赋值,原理和上面的等号形式赋值相同,要点在于看清是改变了a的指向还是a指向内存所存储的值。