L02. 变量及作用域

一. 什么是变量

  

 

二. Lua变量的命令规则

  1. 命名规则:数字字母下划线构成 但是不能数字开头

  2. 注意 :变量命名必须要包含一定涵义 比如我们要用变量存储一个年龄数值 比如我们用 x=18 别人看我们的源码 看到这里 她不明白 X这个变量为18代表什么意思 如果我们用age=18 那么他一看就明白了 方便我们自己 也方便他人 这个是一个良好的习惯 值得培养

  3. 注意:  变量名区分大小写

  4. 注意:变量名有一些系统关键字 不要占用这些关键字 比如Lua本身的一些语句 if else end function

  5. 注意:如果规范一点 我们可以针对 全局变量和局部变量 我们最好区分写法 比如全局变量 p_x=14 p就是public 的缩写 局部变量 l_y l就是local的缩写

 

三 . Lua变量的定义

  1. Lua语言中的变量包含三种类型:全局变量、局部变量、表中的域。

  2. Lua中的所有变量全部是全局变量,哪怕是在函数体中也是全局变量,除非用Local关键字显式声明为局部变量

--初始化全局变量,全局变量不需要定义直接可以拿来使用
g_a = 123; g_b = 456 print(a,b) --输出结果: 123 456 --定义并初始化局部变量,使用local声明 local l_a = 123; l_b = 456 print(a,b) --输出结果: 123 456 local k = 5 --局部变量 k = 6 --局部变量 do m = 6 --全局变量 local n = 5 --局部变量 end local function func() b = 8 --全局变量 local b --局部变量 end if true then local c = 5 --局部变量 d = 6 --全局变量 end

  4. 初始化变量与定义变量是两个不同的概念

--只要在赋值之前变量为nil, 都为初始化变量

--
这叫定义局部变量 local a --这叫初始化局部变量(a在赋值之前为nil,然后被赋予有效值叫初始化) a = 6 --这叫定义并初始化局部变量 local b = 8 --这叫初始化全局变量 c = 5

  5. 全局变量都保存在_G表中

--初始化全局变量
k = 5 
--输出全局变量k
print(k)        --输出结果: 5
--也可以这样输出全局变量
print(_G.k)     --输出结果: 5

  6. 注意: 变量先在最小的作用域下寻找定义,然后再扩大作用域寻找,之后在去找全局_G里面寻找定义(如果不明白作用域,下方有讲解)

local val1 = 5     --定义并初始化局部变量
val1 = 6           --局部变量赋值(此变量与上面的变量是一个)

do 
   val1 = 8        --局部变量赋值(此变量与上面的变量是一个)
   
   function fun()  --定义全局函数
       val1 = 8    --局部变量赋值(此变量与上面的变量是一个)
   end
   fun()           --调用执行函数
end
--[[
    讲解一下函数内变量是如何寻找自己属于哪个作用域的
    1. 先在函数内寻找val1,如果没有找到
    2. 然后在定义函数的上方的do end语句块内,开始寻找,如果没有找到
    3. 然后再整个.lua(模块)文件中查找,如果没有找到(这里是找到了val1属于这个作用域)
    4. 最后在_G里面寻找
--]]

 

四. Lua变量的赋值与删除

  1. 变量的默认值为nil。

--变量的默认值为nil示例: 
--输出一个全局并没有赋值的变量
print(a)  --输出结果: nil
  
--输出一个局部并没有赋值的变量
local a
print(a)  --输出结果: nil

  2. 赋值是将"="右边的内容计算完成后并保存起来然后再赋值给左边(Lua特性,利用此特性可以使用多变量赋值方式直接进行变量交换)

  3. 多个变量同时赋值,变量列表和值列表的各个元素用逗号分开,赋值语句右边的值会依次赋给左边的变量。

  4. 多个变量同时赋值时,变量列表与值列表的元素个数不一致时,采取方式:当变量个数 > 值的个数,按变量个数补足nil     当变量个数 < 值的个数,多余的值会被忽略

local a = 5            --将5赋值给a变量
local b = a            --将a变量内的值赋值给b

--多变量赋值
local a,b,c = {123},20,"在吗?"
--赋值语句右边的值会依次赋给左边的变量。
print(a,b,b)           --输出结果:表地址    20    在吗

--交换变量
local a,b = 10,20
a,b = b,a        --交换变量
print(a,b)        --输出结果: 20  10

--变量列表与值列表的元素个数不一致
--
案例1 local a,b,c = 1,2 --变量列表多于值列表,则将变量列表中的c赋值为nil,因为赋值语句右边的值会依次赋给左边的变量。 print(a,b,c) --输出结果:1 2 nil --案例2 local x,y = 10,20,30 --变量列表少于值列表,则将值列表中30进行省略 print(x,y) --输出结果:10 20

  5. 尽可能的使用局部变量:  ①.避免了命名的冲突 ②访问速度更快 ③占用内存更小

    6. 删除变量

   如果你想删除一个变量,只需要将变量赋值为nil

             当一个变量不等于nil时,这个变量才存在

 

四. Lua变量的作用域

  1. 全局变量整个项目都有效或者说整个lua虚拟机都有效

  2. 局部变量

    ①局部变量的作用域仅限于代码块中,可以是一个'控制结构的主体'、或是一个'函数的主体'、或是一个'代码段'-->'变量被声明时的.lua文件'

    ②: 局部变量会随着'作用域的结束而消失',从而使'垃圾回收器-->gc'能够将其'释放'

    ③: 访问局部变量的速度比全局变量更快,原因: local的变量是存放在lua的堆栈内,是Array操作,而全局变量是存放在_G的table中,效率不及堆栈

   3. 变量的作用域从小到大排序:

       1)'全局环境'变量-->(_ENV|'_G')列表

       2)'文件'作用范围的local变量 --> "包"或"模块"

       3)'函数内'定义的local变量

       4)函数内部'程序块'或'复杂语句中'定义的local变量

a = 5            --全局变量a
a = 6            --将全局变量a重新赋值
local b = 10    --对于本文件.lua的局部变量,作用域在本文件.lua(模块)中有效
b = 20          --对局部变量b重新赋值


--语句块
do 
    a = 1            --全局变量
    local b = 2      --局部变量,仅针对这个语句块有效
    b = 3            --对局部变量重新赋值
end 
print(a,b)           --输出结果: 1  20

--函数
function abc()
   x = 1            --全局变量
   local y = 2      --局部变量,仅针对function这个语句块有效
   y = 2            --对局部变量重新赋值
end
abc()               --调用abc函数
--如果不调用abc则输出: nil  nil
print(x,y)          --输出结果: 1   nim


--If判断
if true then 
    k = 1            --全局变量
    local v = 2        --局部变量,仅针对if这个语句块有效
    v = 3            --对局部变量重新赋值
else 
    --上面if中的局部变量在这里是无效的
end


--while循环
local i = 100       --局部变量,针对本文件.lua(模块)有效
while i > 10 do     --[[这个i是获取的外面i的值,因为: 
    i这个变量首先在while语句块中往上查找,上面没有,则会道上一层作用域中查找
    --]]
   print(i)            --输出结果: 100         --这个为什么输出100与while表达式中i原理一样
   local i = 5      --局部变量对外面无效
   print(i)            --输出结果: 5
end
print(i)            --输出结果: nil


--repeat循环
local j = 1
repeat
    print(j)          --输出结果: 1      
    local j = 100     --创建局部变量
    print(j)          --输出结果: 100
until j == 100         --[[里面的局部变量j对此表达式有效因为:
    j这个变量首先查找 repeat这个语句块中的定义如果没有查找到则查找上一层作用域
--]]

   4. 将函数赋值给变量,那么这个变量就指向了这个函数的地址,那么就具有了函数的一切功能

--局部变量print就具有了全局函数print功能,可以将全部的全局变量函数修改成模块内的局部函数
--1. 这样写的好处是让脚本执行效率更快,因为局部变量的访问要比全局的快
--2. 并且还节省空间,因为当局部变量的语句块结束后,lua虚拟机会释放内存
local print = print

--下面的代码不能需要单独复制出来运行,测试全局函数与局部函数的执行速度 do   local abs = math.abs   local t1 = os.clock ()   for i = 1,100000000 do     abs(1)   end   print("使用局部函数耗时: ",os.clock ()-t1) --耗时: 3.251 end do   local t1 = os.clock ()   for i = 1,100000000 do     math.abs(-123)   end   print("使用全局函数耗时: ",os.clock ()-t1) --耗时: 5.392 end

五. 变量的作用域习题

--变量的作用域实战习题1
local l_var = "第一个模块变量"
local a = "第二个模块变量"
do    
    print(l_bl)                 --输出结果: nil
    local l_bl = "do end的局部变量"
    print(l_bl)                 --输出结果: do end的局部变量
    function g_func(a)
        print(string.format("%s, %s",l_var, a) )
    end
    local a = "do end的局部变量"
    g_func(a)                   --输出结果: 第一个模块变量, do end的局部变量
end

local l_var = "重复定义的第一个模块变量"
g_func(a)                     --输出结果: 第一个模块变量, 第二个模块变量
这张图可以清晰明了的看清lua代码中语句应该获取哪个作用域的值(重要)
 

 

 

posted @ 2022-09-08 10:34  小书臣  阅读(144)  评论(0编辑  收藏  举报