欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

<u id="dhgyw"></u>
    <menuitem id="dhgyw"></menuitem>
  • <blockquote id="dhgyw"></blockquote>

    深入談?wù)刲ua中神奇的table

     更新時間:2018年07月10日 11:55:59   作者:暗無天日  
    table 在lua中是一個非常常用的數(shù)據(jù)結(jié)構(gòu),可以用來存放各種類型的元素,下面這篇文章就來給大家介紹了關(guān)于lua中神奇的table的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面來一起看看吧

    前言

    最近在嘗試配置 awesome WM,因此粗略地學(xué)習(xí)了一下 lua 。 在學(xué)習(xí)過程中,我完全被 table 在 lua 中的應(yīng)用所鎮(zhèn)住了。

    table 在 lua 中真的是無處不在:首先,它可以作為字典和數(shù)組來用; 此外,它還可以被用于設(shè)置閉包環(huán)境、module; 甚至可以用來模擬對象和類

    字典

    table 最基礎(chǔ)的作用就是當(dāng)成字典來用。 它的 key 值可以是除了 nil 之外的任何類型的值。

    t={}
    t[{}] = "table"  -- key 可以是 table
    t[1] = "int"  -- key 可以是整數(shù)
    t[1.1] = "double" -- key 可以是小數(shù)
    t[function () end] = "function" -- key 可以是函數(shù)
    t[true] = "Boolean" -- key 可以是布爾值
    t["abc"] = "String" -- key 可以是字符串
    t[io.stdout] = "userdata" -- key 可以是userdata
    t[coroutine.create(function () end)] = "Thread" -- key可以是thread

    當(dāng)把 table 當(dāng)成字典來用時,可以使用 pairs 函數(shù)來進行遍歷。

    for k,v in pairs(t) do
     print(k,"->",v)
    end

    運行結(jié)果為:

    1 ->  int
    1.1 ->  double
    thread: 0x220bb08 ->  Thread
    table: 0x220b670  ->  table
    abc ->  String
    file (0x7f34a81ef5c0) ->  userdata
    function: 0x220b340 ->  function
    true  ->  Boolean

    從結(jié)果中你還可以發(fā)現(xiàn),使用 pairs 進行遍歷時的順序是隨機的,事實上相同的語句執(zhí)行多次得到的結(jié)果是不一樣的。

    table 中的key最常見的兩種類型就是整數(shù)型和字符串類型。 當(dāng) key 為字符串時,table可以當(dāng)成結(jié)構(gòu)體來用。同時形如 t["field"] 這種形式的寫法可以簡寫成 t.field 這種形式。

    數(shù)組

    當(dāng) key 為整數(shù)時,table 就可以當(dāng)成數(shù)組來用。而且這個數(shù)組是一個 索引從1開始 ,沒有固定長度,可以根據(jù)需要自動增長的數(shù)組。

    a = {}
    for i=0,5 do  -- 注意,這里故意寫成了i從0開始
     a[i] = 0
    end

    當(dāng)將 table 當(dāng)成數(shù)組來用時,可以通過 長度操作符 # 來獲取數(shù)組的長度

    print(#a)

    結(jié)果為

    5

    你會發(fā)現(xiàn), lua 認(rèn)為 數(shù)組 a 中只有5個元素,到底是哪5個元素呢?我們可以使用使用 ipairs 對數(shù)組進行遍歷:

    for i,v in ipairs(a) do
     print(i,v)
    end

    結(jié)果為

    1 0
    2 0
    3 0
    4 0
    5 0

    從結(jié)果中你會發(fā)現(xiàn) a 的0號索引并不認(rèn)為是數(shù)組中的一個元素,從而也驗證了 lua 中的數(shù)組是從 1開始索引的

    另外,將table當(dāng)成數(shù)組來用時,一定要注意索引不連貫的情況,這種情況下 # 計算長度時會變得很詭異

    a = {}
    for i=1,5 do
     a[i] = 0
    end
    a[8] = 0   -- 雖然索引不連貫,但長度是以最大索引為準(zhǔn)
    print(#a)
    a[100] = 0   -- 索引不連貫,而且長度不再以最大索引為準(zhǔn)了
    print(#a)

    結(jié)果為:

    8
    8

    而使用 ipairs 對數(shù)組進行遍歷時,只會從1遍歷到索引中斷處

    for i,v in ipairs(a) do
     print(i,v)
    end

    結(jié)果為:

    1 0
    2 0
    3 0
    4 0
    5 0

    環(huán)境(命名空間)

    lua將所有的全局變量/局部變量保存在一個常規(guī)table中,這個table一般被稱為全局或者某個函數(shù)(閉包)的環(huán)境。

    為了方便,lua在創(chuàng)建最初的全局環(huán)境時,使用全局變量 _G 來引用這個全局環(huán)境。因此,在未手工設(shè)置環(huán)境的情況下,可以使用 _G[varname] 來存取全局變量的值.

    for k,v in pairs(_G) do
     print(k,"->",v)
    end

    rawequal  ->  function: 0x41c2a0
    require ->  function: 0x1ea4e70
    _VERSION  ->  Lua 5.3
    debug ->  table: 0x1ea8ad0
    string  ->  table: 0x1ea74b0
    xpcall  ->  function: 0x41c720
    select  ->  function: 0x41bea0
    package ->  table: 0x1ea4820
    assert  ->  function: 0x41cc50
    pcall ->  function: 0x41cd10
    next  ->  function: 0x41c450
    tostring  ->  function: 0x41be70
    _G  ->  table: 0x1ea2b80
    coroutine ->  table: 0x1ea4ee0
    unpack  ->  function: 0x424fa0
    loadstring  ->  function: 0x41ca00
    setmetatable  ->  function: 0x41c7e0
    rawlen  ->  function: 0x41c250
    bit32 ->  table: 0x1ea8fc0
    utf8  ->  table: 0x1ea8650
    math  ->  table: 0x1ea7770
    collectgarbage  ->  function: 0x41c650
    rawset  ->  function: 0x41c1b0
    os  ->  table: 0x1ea6840
    pairs ->  function: 0x41c950
    arg ->  table: 0x1ea9450
    table ->  table: 0x1ea5130
    tonumber  ->  function: 0x41bf40
    io  ->  table: 0x1ea5430
    loadfile  ->  function: 0x41cb10
    error ->  function: 0x41c5c0
    load  ->  function: 0x41ca00
    print ->  function: 0x41c2e0
    dofile  ->  function: 0x41cbd0
    rawget  ->  function: 0x41c200
    type  ->  function: 0x41be10
    getmetatable  ->  function: 0x41cb80
    module  ->  function: 0x1ea4e00
    ipairs  ->  function: 0x41c970

    從lua 5.2開始,可以通過修改 _ENV 這個值(lua5.1中的setfenv從5.2開始被廢除)來設(shè)置某個函數(shù)的環(huán)境,從而讓這個函數(shù)中的執(zhí)行語句在一個新的環(huán)境中查找全局變量的值。

    a=1    -- 全局變量中a=1
    local env={a=10,print=_G.print} -- 新環(huán)境中a=10,并且確保能訪問到全局的print函數(shù)
    function f1()
     local _ENV=env
     print("in f1:a=",a)
     a=a*10   -- 修改的是新環(huán)境中的a值
    end
    
    f1()
    print("globally:a=",a)
    print("env.a=",env.a)
    in f1:a= 10
    globally:a= 1
    env.a= 100

    另外,新創(chuàng)建的閉包都繼承了創(chuàng)建它的函數(shù)的環(huán)境

    module

    lua 中的模塊也是通過返回一個table來供模塊使用者來使用的。 這個 table中包含的是模塊中所導(dǎo)出的所有東西,包括函數(shù)和常量。

    定義module的一般模板為

    module(模塊名, package.seeall)

    其中 module(模塊名) 的作用類似于

    local modname = 模塊名
    local M = {}                    -- M即為存放模塊所有函數(shù)及常數(shù)的table
    _G[modname] = M
    package.loaded[modname] = M
    setmetatable(M,{__index=_G})    -- package.seeall可以使全局環(huán)境_G對當(dāng)前環(huán)境可見
    local _ENV = M                  -- 設(shè)置當(dāng)前的運行環(huán)境為 M,這樣后續(xù)所有代碼都不需要限定模塊名了,所定義的所有函數(shù)自動變成M的成員
    <函數(shù)定義以及常量定義>

    return M                        -- module函數(shù)會幫你返回module table,而無需手工返回

    對象

    lua 中之所以可以把table當(dāng)成對象來用是因為:

    函數(shù)在 lua 中是一類值,你可以直接存取table中的函數(shù)值。 這使得一個table既可以有自己的狀態(tài),也可以有自己的行為:

    Account = {balance = 0}
    function Account.withdraw(v)
     Account.balance = Account.balance - v
    end

    lua 支持閉包,這個特性可以用來模擬對象的私有成員變量

    function new_account(b)
     local balance = b
     return {withdraw = function (v) balance = balance -v end,
      get_balance = function () return balance end
     }
    end
    
    a1 = new_account(1000)
    a1.withdraw(10)
    print(a1.get_balance())

    990

    不過,上面第一種定義對象的方法有一個缺陷,那就是方法與 Account 這個名稱綁定死了。 也就是說,這個對象的名稱必須為 Accout 否則就會出錯

    a = Account
    Account = nil
    a.withdraw(10)     -- 會報錯,因為Accout.balance不再存在

    為了解決這個問題,我們可以給 withdraw 方法多一個參數(shù)用于指向?qū)ο蟊旧?/p>

    Account = {balance=100}
    function Account.withdraw(self,v)
     self.balance = self.balance - v
    end
    a = Account
    Account = nil
    a.withdraw(a,10)     -- 沒問題,這個時候 self 指向的是a,因此會去尋找 a.balance
    print(a.balance)

    90

    不過由于第一個參數(shù) self 幾乎總是指向調(diào)用方法的對象本身,因此 lua 提供了一種語法糖形式 object:method(...) 用于隱藏 self 參數(shù)的定義及傳遞. 這里冒號的作用有兩個,其在定義函數(shù)時往函數(shù)中地一個參數(shù)的位置添加一個額外的隱藏參數(shù) sef, 而在調(diào)用時傳遞一個額外的隱藏參數(shù) self 到地一個參數(shù)位置。 即 function object:method(v) end 等價于 function object.method(self,v) end, object:method(v) 等價于 object.method(object,v)

    當(dāng)涉及到類和繼承時,就要用到元表和元方法了。事實上,對于 lua 來說,對象和類并不存在一個嚴(yán)格的劃分。

    當(dāng)一個對象被另一個table的 __index 元方法所引用時,table就能引用該對象中所定義的方法,因此也就可以理解為對象變成了table的類。

    類定義的一般模板為:

    function 類名:new(o)
     o = o or {}
     setmetatable(o,{__index = self})
     return o
    end

    或者

    function 類名:new(o)
     o = o or {}
     setmetatable(o,self)
     self.__index = self
     return o
    end

    相比之下,第二種寫法可以多省略一個table

    另外有一點我覺得有必要說明的就是 lua 中的元方法是在元表中定義的,而不是對象本身定義的,這一點跟其他面向?qū)ο蟮恼Z言比較不同。

    總結(jié)

    以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。

    相關(guān)文章

    • Lua中的函數(shù)淺析

      Lua中的函數(shù)淺析

      這篇文章主要介紹了Lua中的函數(shù),包括函數(shù)聲明、函數(shù)參數(shù)、多重返回值、變長參數(shù)、具名實參、閉包函數(shù)等內(nèi)容,需要的朋友可以參考下
      2014-09-09
    • Lua的堆棧淺析

      Lua的堆棧淺析

      這篇文章主要介紹了Lua的堆棧淺析,本文參考游戲人工智能編程案例精粹中的Lua堆棧索引圖,畫出了自己的一張理解圖,需要的朋友可以參考下
      2014-09-09
    • lua日志文件處理代碼

      lua日志文件處理代碼

      本文給大家分享的是使用lua編寫的日志文件的處理代碼,非常的簡單實用,有需要的小伙伴可以參考下。
      2015-09-09
    • Lua面向?qū)ο笾惡屠^承淺析

      Lua面向?qū)ο笾惡屠^承淺析

      這篇文章主要介紹了Lua面向?qū)ο笾惡屠^承淺析,本文講解了一些Lua面向?qū)ο蟮囊恍┲R,需要的朋友可以參考下
      2014-09-09
    • Lua中執(zhí)行系統(tǒng)命令方法介紹

      Lua中執(zhí)行系統(tǒng)命令方法介紹

      這篇文章主要介紹了Lua中執(zhí)行系統(tǒng)命令方法介紹,Lua中有兩種方法可以執(zhí)行操作系統(tǒng)內(nèi)置命令,需要的朋友可以參考下
      2015-04-04
    • Lua在windows下的安裝及環(huán)境配置

      Lua在windows下的安裝及環(huán)境配置

      這篇文章主要介紹了Lua在windows下的安裝及環(huán)境配置,本文使用lua for windows整體環(huán)境,lua for windows其實是一整套Lua的開發(fā)環(huán)境,需要的朋友可以參考下
      2015-07-07
    • Lua調(diào)用自定義C模塊

      Lua調(diào)用自定義C模塊

      Lua可以調(diào)用C函數(shù)的能力將極大的提高Lua的可擴展性和可用性。對于有些和操作系統(tǒng)相關(guān)的功能,或者是對效率要求較高的模塊,我們完全可以通過C函數(shù)來實現(xiàn),之后再通過Lua調(diào)用指定的C函數(shù)。對于那些可被Lua調(diào)用的C函數(shù)而言,其接口必須遵循Lua要求的形式
      2015-09-09
    • Lua極簡入門指南:全局變量

      Lua極簡入門指南:全局變量

      這篇文章主要介紹了Lua極簡入門指南:全局變量,本文講解了全局變量、_ENV等內(nèi)容,需要的朋友可以參考下
      2014-10-10
    • Lua中的邏輯運算符使用詳解

      Lua中的邏輯運算符使用詳解

      這篇文章主要介紹了Lua中的邏輯運算符使用詳解,是Lua入門學(xué)習(xí)中的基礎(chǔ)知識,需要的朋友可以參考下
      2015-05-05
    • Lua協(xié)程(coroutine)程序運行分析

      Lua協(xié)程(coroutine)程序運行分析

      這篇文章主要介紹了Lua協(xié)程(coroutine)程序運行分析,本文講解分析了一段lua 協(xié)程代碼是如何運行的,需要的朋友可以參考下
      2015-05-05

    最新評論