用户工具

站点工具


侧边栏

06mod教程区:新手入门:lua语法

2.1 表

  • test = { a="1", [4]="2", "3", d=nil, e="5", "6", nil, "7", i={"1"}}

    需要注意是,如果手动给一个值设置数字作为其键,若没有键的单值的索引(从1开始)大于等于前面这个被设置的数字键,则输出的时候会覆盖掉前面的值

    如上,设置test[4]=2, 但是单值的数量为4(3,6,nil,7),所以test[4]被后面的7覆盖掉,变成了 test[4]=7

  • 元表(metaclass)
    • setmetatable(tableA, tableB):将tableB设置为tableA的元表,返回值为设置元表后的tableA
    • getmetatable(tableA):返回tableA的元表,若其没有元表,返回nil
    • __index:用来对表访问
      • __index的值是一个表

        当你通过键来访问 table 的时候,如果这个键没有值,那么Lua就会寻找该table的metatable(假定有metatable)中的__index

snippet.lua
      local a = {}
      local b = {}
      b.__index = {key="value"}
      setmetatable(a, b)
      print(a["key"])  --- value
 
      -----等价------
      setmetatable(a, {__index={key="value"}})
      print(a["key"])  --- value
    
  - `__index`是一个函数
    当你通过键访问table的时候,如果这个键没有值,那么Lua会把table和键分别作为`__index`对应函数的两个参数传递过去
    ```lua
    tableA = nil
    local fn = function(mytable, key)
        tableA = mytable
        if key == "key2" then
            return "查找的键为key2"
        else
            return nil
        end
    end
    
    local a = {key1 = "value1"}
    local b = {__index = fn}
    setmetatable(a, b)
    
    print(a.key1, a.key2)  --- value1  查找的键为key2
    print(tableA==a)  --- true     (说明函数接受的table是原来的table(a),不是table的metatable(b))
    print(tableA==b)  --- false
    
    ----另一种写法----
    a = setmetatable({key1 = "value1"}, { __index = {key2 = "查找的键为key2"}})
    print(a.key1, a.key2)  --- value1  查找的键为key2
    print(tableA==a)  --- true (说明函数接受的table是主表,不是元表)
    print(tableA==b)  --- false
    ```
  1. rawget(table, "key"):让元表的__index方法无效
    ```lua
    ----当__index是一个表时,rawget(table, "key")让其无效---
    local a = {}
    local b = {}
    b.__index = {key="value"}
    setmetatable(a, b)
    print(a.key)  --- value
    print(rawget(a, "key"))  --- nil
    
    ---当__index是一个函数时,rawget(table, "key")让其无效---
    local fn = function(mytable, key)
        return key
    end
    
    local a = {key1 = "value1"}
    local b = {__index = fn}
    setmetatable(a, b)
    
    print(a.key1, a.key2)  --- value1  key2
    print(rawget(a, "key1")) --- value1
    print(rawget(a, "key2"))  --- nil
    ```
  1. __newindex:用来对表更新
  当你**给表缺少的索引进行赋值时**,解释器就会查找`__newindex` 元方法
  1. __newindex是一个表
    会直接把值赋给`__newindex`对应的表,而不会对主表进行赋值
    ```lua
    ---对主表不存在的键进行赋值,会触发元表的__newindex方法---
    local a = {test="已有的值"}
    local b = {}
    b.__newindex = {}
    setmetatable(a, b)
    
    a["key"] = "没有的key进行赋值"
    print(a["key"])  --- nil
    print(b["key"])  --- nil
    print(b.__newindex["key"])  --- "没有的key进行赋值"
    
    ---对主表已有的键进行赋值,不会触发元表的__newindex方法---
    local a = {test="已有的值"}
    local b = {}
    b.__newindex = {}
    setmetatable(a, b)
    
    a["test"] = "改变test的值"
    print(a["test"])  --- "改变test的值"
    print(b["test"])  --- nil
    print(b.__newindex["test"])  --- nil
    ```
  1. __newindex是一个函数
    在`__newindex`中如果对主表中的键进行赋值,要用`rawset`(直接赋值会导致递归)
    ```lua
    local fn = function(mytable, k, v)
      print("k: " .. k)
      print("v: " .. v)
    end
    
    local a = {test="已有的值"}
    local b = {}
    b.__newindex = fn
    setmetatable(a, b)
    
    a["key"] = "没有的key进行赋值"
    --- k: key
    --- v: 没有的key进行赋值
    print(a["key"])  --- nil
    print(b["key"])  --- nil
    print(b["__newindex"]["key"]) -- Error,因为__newindex是个函数,不是表
    
    ---在__newindex中对主表进行修改---
    local fn = function(mytable, k, v)
      local modi_v = "【" ..v.. "】"
      rawset(mytable, k, modi_v)  -- 要用rawset,直接mytable[k]=v会引起递归
    end
    
    local a = {test="已有的值"}
    local b = {}
    b.__newindex = fn
    setmetatable(a, b)
    
    a["key"] = "没有的key进行赋值"
    --- k: key
    --- v: 没有的key进行赋值
    print(a["key"])  --- 【没有的key进行赋值】
    print(b["key"])  --- nil
    ```
  1. __call:在 Lua 以函数方式调用主表时,调用元表__call对应的函数
  1. 第一个参数为主表
  2. 后续接可变参数
  ```lua
  local a = {}
  local b = {}
  b.__call = function (mytable, ...)
    local t = {...}
    for i, v in pairs(t) do 
      print(v)
    end
    return "__call方法"
  end
  
  local c = {10, 20, 30}
  setmetatable(a, b)
  
  print(a(1)) --- 1
  print(a(1, 2, 3)) --- 1 2 3
  ```
  1. __tostring:元方法用于修改表的输出行为。以下实例我们自定义了表的输出内容
  ```lua
  local a = {}
  local b = {}
b.__tostring = function (mytable) 
    return "toString方法"
  end
  local c = setmetatable(a, b)
  print(a)  --- toString 方法
  ```
  

2.2 三元表达式

snippet.lua
local thing = condition and if_true or if_false
---------------等价于---------------
local thing = nil
if condition then
    thing = if_true
else
    thing = if_false
end

2.3 循环表达式

  • pairs:输出所有非nil对象
    1. 键值对、单值,pairs都可以遍历到,pairs首先给所有非键值对,按顺序赋一个索引作为key值,如下文的“3”、“6”,nil, “7”被分别赋为“1”, “2”, “3”, “4”,然后输出所有键值对(随机顺序,同时跳过nil)


    lua local test = { a="1", [4]="2", "3", d=nil, e="5", "6", nil, "7"} for k, v in pairs(test) do print(k..v) end --[[输出 13 26 47 -- 这里是7不是2,详见Lua中关于表的定义 e5 a1 ]]

  • ipairs :输出所有非键值对,遇到nil停止

    lua local test = { a="1", [4]="2", "3", d=nil, e="5", "6", nil, "7"} for i, v in ipairs(test) do print(i..v) end --[[输出 13 26 ]] --因为d=nil, 是键值对,本身就不会被考虑进去,所以在剩下的 3,6,nil,7中,会输出到6,然后遇到nil终止

2.4 断言

assert(a, b):a是要检查是否有错误的一个参数,b是a错误时抛出的信息(参数b是可选的)(assert只在debugger模式下有用)

snippet.lua
print("enter a number:")
n = io.read("*number")
if not n then
    error("invalid input")
end
 
---↓等价于↓---
print("enter a number:")
n = assert(io.read("*number"), "invalid input")
06mod教程区/新手入门/lua语法.txt · 最后更改: 2021/07/14 10:42 (外部编辑)