lua變數、資料型別、if判斷條件和資料結構table以及【lua 函數】

2023-04-19 06:00:36

一、lua變數【 全域性變數和區域性變數和表中的域】

Lua 變數有三種型別:全域性變數區域性變數表中的域

▪ 全域性變數:預設情況下,Lua中所有的變數都是全域性變數。

▪ 區域性變數:使用local 顯式宣告在函數內的變數,以及函數的引數,都是區域性變數。在函數外即使用local去宣告,它的作用域也是當前的整個檔案,這相當於一個全域性變數。

▪ 表中的域:變數的預設值均為 nil

☺ Lua語言不區分未初始化變數和被賦值為nil的變數,因此全域性變數無須宣告即可使用。


1、全域性變數

全域性變數,不需要宣告,只需要將一個值賦予一個全域性變數即可建立了

b=10 	-- 這個b就是一個全域性變數了
print(b)
  • 通常沒必要刪除一個全域性變數,如果一個變數生存週期較為短,使用區域性變數即可。不過,如果真的想刪除全域性變數的話,只需將它賦值為nil。
b=nil 	-- 這個全域性變數b就被刪除了
print(b)

2、區域性變數-使用local 宣告

  • Lua 中的變數全是全域性變數,哪怕是語句塊或是函數裡,除非用 local 顯式宣告為區域性變數

  • 區域性變數的作用域為從宣告位置開始到所在語句塊結束。

建議:在Lua中,應儘可能使用區域性變數,好處:

  1. 避免命名衝突
  2. 存取區域性變數的速度比全域性變數更快

3、lua表中的域

a = {}
a[10] = 1
for i=1,15,1 do
	print(a[i])
end
  • 結果:


二、lua資料型別、if判斷條件

Lua 是動態型別語言,變數不要型別定義,只需要為變數賦值。 值可以儲存在變數中,作為引數傳遞或結果返回。

1、Lua 中有 8 個基本型別分別為:nil、boolean、number、string、userdata、function、thread 和 table。

資料型別 描述
nil 空值,只有值nil屬於該類,表示一個無效值在條件表示式中相當於false)。
boolean 布林型別
number 數值型別,相當於C語言的double
string 字串型別,由一對雙引號或單引號來表示
function 函數型別,由 C 或 Lua 編寫的函數
table Lua 中的表(table)其實是一個"關聯陣列"(associative arrays),陣列的索引可以是數位、字串或表型別。在 Lua 裡,table 的字面量是用{} 表示。 {},表示建立一個空表。
thread 執行緒型別,表示執行的獨立線路,用於執行協同程式
userdata 表示任意儲存在變數中的C資料結構

2、type(變數名)

  • 作用:獲取該變數的型別

3、lua 的if 判斷條件是理解為是否有效

▷什麼時候會【無效】錯誤失敗---為nil和false的時候

  • nil 表示空值、無效值

▷其他情況為數位、字串、true、表(甚至是空表也是正確的),判斷條件都是【有效】正確成功的!



三、lua資料結構-table

0、table的字面量:{},建立的空表,內部的域預設值是nil。

  • 表用大括號{}來構造,可以是多維的 {{}}。

1、lua中的表,其實是一個"關聯陣列",關聯陣列是一種具有特殊索引的陣列,陣列的索引可以是陣列、字串、表等[除了nil]。

  • 表中的元素是鍵值對形式。key 也就是陣列的索引。表的key是唯一的。表是可以自定義鍵名。

2、table 是沒有固定大小的,可以新增任意數量的元素到陣列中。

3、table 是lua中最主要的資料結構機制,也是唯一的資料結構。用它可以實現陣列,雜湊表、集合、字典等等。還可以通過table 表示物件、包、模組。

其實lua 中的table 概念,相當於java中的物件的概念。萬物皆是物件。

4、表中元素的刪除,有兩種方式:直接設定為nil或呼叫remove方法刪除

  • 兩種刪除方式的區別:直接把元素賦值為nil,會留下空位,不影響其他元素。而用remove函數去刪除,會把後面的元素往前移,補位。

5、表中元素有多少個,可以使用#獲取

6、表中的索引是從1開始的

tb={'乾飯', '吃飯', '恰飯'}
  • 實際上,tb如下:
-- tb的情況如下:
-- 地址table(c917ad2)
{
 [1] = '乾飯',
 [2] = '吃飯',
 [3] = '恰飯',
}

7、表有自定義鍵的時候:

-- 表中只寫了值value作為元素
tb={'乾飯', '吃飯', '恰飯', s='溜達'}
  • 實際上,表是有預設分配鍵key的,預設分配的鍵是從數位1開始的,tb表中的分配如下:
-- tb的情況如下:
-- 地址table(c917ad3)
{
 [1] = '乾飯',
 [2] = '吃飯',
 [3] = '恰飯',
 ['s'] = '溜達',--細節:s會被帶上引號
}

細節:要通過自定義的s鍵獲取到值,s是要加上引號的。


對於自定義的鍵有一個語法糖,中括號可以使用點代替


表中預設分配的鍵和自定義鍵的執行順序是:預設的先執行,然後再是自定義的鍵

-- 表中只寫了值value作為元素
tb={'乾飯',a='溜達',b='哈哈哈', _='餓了麼','吃飯', '恰飯'}
  • 實際上,tb表中的分配如下:程式分配鍵的時候,會先跳過自定義鍵,再接著分配。
-- tb的情況如下:
-- 地址table(c917ad3)
{
 [1] = '乾飯',
 [2] = '吃飯',
 [3] = '恰飯',
 ['a'] = '溜達',
 ['b'] = '哈哈哈',
 ['_'] = '餓了麼',
}
  • 結果:

8、table 提供的增刪元素的方法 table.insert 和 table.remove

  • table.insert(表名,要增加的鍵位,要增加的值) 直接再最後的位置增加元素:table.insert(表名,要增加的值)

  • table.remove(表名,要刪除的鍵位)



四、lua 函數(形參-實引數數量不匹配、多重返回值、不定長引數、方法的冒號和點-self隱式引數)

0、lua 程式是嚴格從上到下的順序執行程式碼的, 函數的宣告必須在寫函數呼叫前面。


在lua中,函數是作為第一型別,函數是可以存在在變數中,也可以通過引數傳遞給其他函數,還可以作為其他函數的返回值,還可以作為table表中的鍵

1、函數定義的方式

-- 方式1:
function 函數名(參數列)
	函數內容
end


-- 方式2:
函數名=function(參數列)
	函數內容
end

2、lua 函數

① 函數是可以存在在變數中【匿名函數

a = function(x, y)
	return x * y
end
b = a
print(b(2,3))
  • 結果:

    6

▪ 在table中也可以存在function函數

tab = {
	test=function()
		print("Hello World!")
	end
}
tab.test()
  • 結果:

Hello World!

3、形參-實引數數量不匹配

  • 傳入的實引數量 > 定義的形引數量:多傳入的引數,直接被忽略了
  • 傳入的實引數量 < 定義的形引數量:缺少的引數,使用nil替補

4、多重返回值

  • 舉例1:


  • 舉例2:

  • 小細節:多個具有多重返回值的函數連續呼叫[使用,間隔],只有最後一個函數被展開,即最後一個函數才有資格返回多個值,其他函數都預設返回第一個值


5、不定長引數

  • 和java 一樣,不定長引數使用...表示,並且作為函數的最後一個引數。
  • select 函數來存取變長引數了
    • select('#', …) 返回可變引數的長度。
    • select(n, …) 用於返回從起點 n 開始到結束位置的所有參數列。


6、方法的冒號和點-self隱式引數

▷ Lua 定義或呼叫方法時的語法糖-冒號,表示引數self

這個語法糖是用冒號,表示self,相當於java中的this

■ 舉例1:

--定義
Account = { balance = 0 }
--withdraw 方法有兩個引數,一個self【相當於java中的this】是指向當前table的Account 
function Account.withdraw(self, v)
         self.balance = self.balance - v
end
--等價寫法:
function Account:withdraw(v) --通過冒號,表示定義了第一個引數是self
         self.balance = self.balance - v
end

--呼叫
Account.withdraw(self, 100)
--等價寫法
Account:withdraw(100)        

■ 舉例2:

-- 在table的鍵值對的value---是function的時候,方法的引數是self,並且還將self 引數傳遞給function方法體的另外一個方法
-- {} 在lua中表示table
tbWnd.tbOnClick = {
    btnOk = function(self)
        self:onClickOK() -- 相當於onClickOK(self)
    end,
}

7、函數巢狀呼叫,並且作為引數的那個函數,它是需要有引數傳入

① 通過將引數儲存到table中,table又繫結上的函數,該函數就可以通過self.key 拿到引數

② 然後外層的函數(func,table)

local tbTable = {}
tbTable.key1  = 1
function tbTable:func1()--這樣寫,隱式引數是self
    print(self.key1)
end


-- 函數巢狀呼叫
function func2(func,tbSelf)
    func(tbself)
end

-- 執行
func(tbTable.func1)



☺ 五、lua 函數常見寫法

1、直接構建

function func(...)
    print(...)
end

-- 呼叫函數
func(123)

2、表構建,key儲存函數(1)

local tbTable = {}
function tbTable.func1(...)
    print(...)
end

function tbTable.func2(...)
    print(...)
end

-- 呼叫函數
tbTable.func1(123)
tbTable.func1(4,5,6)

3、表構建,key儲存函數(2)

local tbTable = {}

tbTable.func1 = function(...)
    print(...)
end

tbTable.func2 = function(...)
    print(...)
end

-- 呼叫函數
tbTable.func1(123)
tbTable.func1(4,5,6)

4、表構建,key儲存函數(3)

local tbTable = {
    func1 = function(...)
    	print(...)
	end,
    func2 = function(...)
    	print(...)
	end
}

-- 呼叫函數
tbTable.func1(123)
tbTable.func1(4,5,6)



六、函數巢狀|閉包

1、local 特點:

區域性變數:使用local 顯式宣告在函數內的變數,以及函數的引數,都是區域性變數。

在函數外即使用local去宣告,它的作用域也是當前的整個檔案,這相當於一個全域性變數。


2、函數巢狀|閉包

(1) 特點:函數的呼叫是用() 表示,有多少層,函數真正呼叫就需要多少個()

(2) 舉例子:

  • 舉例子1:
local f = function(n)
	return function(x)
		return x+n
	end
end

print(f(1)(2)) -- 函數巢狀,每一層都相當於()

a = f(1)
print(a(10))
  • 結果:

    3
    11


  • 舉例子2:local 在函數外相當於java的全域性變數【獨立的作用域強調的就是這個在函數外面的local 變數】
local p = 1
local f = function()
	local v = 0 -- local 在[下面的]函數外面相當於java的全域性變數
	return function()
		v = v + p
		print(v)
	end
end	

a,b = f(), f()
a(); b();
p = 2
a(); b();
  • 結果:

    1

    1

    3

    3

  • local 在函數外相當於java的全域性變數【獨立的作用域

class A{
   private int v; -- 全域性變數
   public void add(){}
}

  • 舉例子3:
local f = function()
	return {
        add = function(a,b)
			return a + b
	   end,
        sub = function(a,b)
			return a - b
	   end,
    }
end	

v = f()
print(v.add(1,2))
print(v.sub(2,1))
  • 結果:

    3
    1




如果本文對你有幫助的話記得給一樂點個贊哦,感謝!