自学成菜-流水账学习法lua入门

Posted 呆呆熊的技术路

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了自学成菜-流水账学习法lua入门相关的知识,希望对你有一定的参考价值。

  • 学习背景: 一直想去体验下openrestry,可惜一直没动力去完成这件事,正好工作原因需要调研,就开启体验之旅吧。开始前需要对lua语法有简单了解和认识

  • 流水式计划:

    • 基础语法简单熟悉

    • openrestry模块知识点实践

    • 一个小项目

lua基础语法

print("hello lua")

获取数据类型 函数type

a = 123
print(type(a))     -->output:number
print(type(1.23))  -->output:number
print(type(nil))   -->output:nil
print(type('123')) -->output:string
print(type(true))  -->output:boolean

a = {}
print(type(a))     -->output:table

local b
print(b)        -->output:nil  默认nil
  以上出现了几个关键词简单描述下:
  1. local相当于声明变量b为局部变量
  2. --为单行注释 --[[ code ]]为多行注释
local a = 0

if a then
   print('pass')  --output:pass
end
local b
if b then
   print('pass')
else
   print('no pass'--output:no pass
end
local a=false

if a then
   print('pass')
else
   print('no pass'--output:no pass
end

在lua中,nil和false为假,其他所有值为真 比如0和空字符串都为真

local a = 5
local b = 3

function getNumber()
    if a>b then
        return a
    else
        return b
    end
end

value = getNumber()
print(value)

声明a,b两个全局变量,声明了一个函数返回最大值,其中需要注意的就是lua是没有函数提升的概念的,所以需要先声明后使用

local a = 5
local b = 3

function getNumber(a,b)
    if a>b then
       return a
    else
       return b
    end
end

value = getNumber(a,b+3
print(value) //output:6
local a = 5
local b = 3

function getNumber()
    local b = 10
    if a>b then
       return a
    else
       return b
    end
end

value = getNumber()
print(value)   --output:10 

函数中的b作用于函数块内,覆盖外部b的变量值


Math函数库

a = 1.2

print(math.floor(a)) --output : 1

print(math.ceil(a))  --output : 2

print(math.abs(a))   --output : 1.2

print(math.random(20,30)) --output : 随机

print(math.max(1,2,3,4,8,5,0)) --output : 8

print(math.min(1,2,3,4,8,5,0)) --output : 0

lua并没有四舍五入,如果实现可以使用math.floor

lua 中的math.floor函数是向下取整函数。
    math.floor(5.123)   -- 5
    math.floor(5.523)   -- 5
用此特性实现四舍五入
    math.floor(5.123 + 0.5)  --5
    math.floor(5.523 + 0.5)  --6
也就是对math.floor函数的参数进行 “+ 0.5” 计算

String函数库

s = 'abcd123'

print(string.len(s))  --output : 7

print(string.rep(s,2)) --output : abcd123abcd123

print(string.lower(s)) --output : abcd123

print(string.upper(s)) --output : ABCD123

print(string.sub(s,1,2)) --output : ab

local find = string.find
print(find('abcd haha 123','a',2)) --output:7
print(find('abcd haha 123','az',2)) --output:nil

print(string.format('%d',2.5 )) --output : 2

print(string.format("%.2f",1.256)); --output : 1.26

print(string.format('value: %s',s )) --output : value: abcd123

注意 string.sub 从1开始截取,截取2个字符。lua下标是从1开始的 %.2f也可以实现四舍五入

新类型-强大的talbe

local user = {
   name = "xiao ge ge",
   age  = {
     1,2,3
   }
}

print(user.name) --output : xiao ge ge

print(user.age[1]) --output : 1

local class = {'one class','two class'}

print(class[0]) --output : nil

print(class[1]) --output : one class

day1 = {2018,7,1,0,0,0}
print(#(day1)) --获取长度 6
print(table.getn(day1)) --获取长度 6
print(next(day1)) --验证是否为空

table函数库

tbl = {"alpha""beta""gamma"}

print(table.concat(tbl, ":"))   --output: alpha:beta:gamma

print(table.concat(tbl, nil12)) --output: alphabeta

print(table.concat(tbl, "\n"23)) --output: beta \n gamma
tbl = {"a""b""c"}

table.insert(tbl, "d")

print(table.concat(tbl,",")) --output: a,b,c,d

table.insert(tbl, "e"

print(table.concat(tbl,",")) --output: a,b,c,d,e
class = {1,2,3,4,5}
max = table.maxn(class);
print(max)   --output: 5
class = {1,2,3,4,5,6}
max = table.remove(class); 
print(max) --output: 6
print(table.concat(class,',')) --1,2,3,4,5

remove相当于其他语言的pop,移除最后一位

入栈 出栈操作

list = {'a','b','c'}

table.insert(list,'d');  --进栈

print(table.concat(list,',')) --a,b,c,d

table.remove(list)  --出栈

print(table.concat(list,',')) --a,b,c

队列操作

list = {'a','b','c'}

table.insert(list,1,'1'); --入队列 注意下标1

print(table.concat(list,',')) --1,a,b,c

table.remove(list)  --出队列

print(table.concat(list,',')) --1,a,b

日期时间函数

uninx时间戳

print(os.time()) --output : unix时间戳

day1 = {year=2018,month=7,day=1,hour=0,min=0,sec=0}
day1_time = os.time(day1) --output: 获取day1时间戳

day2 = {year=2018,month=7,day=1,hour=0,min=1,sec=0}
day2_time = os.time(day2)

print(os.difftime(day1_time,day2_time)) --day1-day2=-60

时间戳转时间

    temp = os.date("*t"906000490)
    --{year = 1998, month = 9, day = 16, yday = 259, wday = 4,hour = 23, min = 48, sec = 10, isdst = false}

    date = os.date('%Y-%m-%d %H:%M:%S',os.time())
    print(date)  --output: 2018-07-01 06:19:11

lua条件判断

关系运算符 说明
< 小于
> 大于
<= 小于等于
>= 大于等于
== 等于
~= 不等于

在使用"=="做等于判断时,要注意对于table,userdata和函数,lua是作引用比较的。也就是说,只有当两个变量引用同一个对象时,才认为他们相等。

listA = {'a','b','c'}
listB = {'a','b','c'}
print(listA==listB) --output false
local a,b,c = nil,2,3  --类似go的多赋值

print(a and b) --output: nil
print(a or b or c)  --output: 2
print(not a) --output true

上面用例and or在C语言会返回0或1,但是lua中a and b如果a为nil,则返回a 否则返回b, a or b中如果a为nil,则返回b否则返回a

function getList(users)
    local temp = ''
    for k,v in  ipairs(users) do
        temp = temp..'\n'..k..'=>'..v
    end
    return 'ok',temp
end

users = {1,2,nil,4,5,6}

msg,temp = getList(users) --output: ok    1=>1 \n 2=>2
print(msg,temp)
function getList(users)
    local temp = ''
    for k,v in  pairs(users) do
        temp = temp..'\n'..k..'=>'..v
    end
    return 'ok',temp
end

users = {1,2,nil,4,5,6}

msg,temp = getList(users) --output: ok    1=>1 2=>2 4=>4 5=>5 6=>6
print(msg,temp)

两段代码看似一样,但其实体现了ipairs和pairs的区别,ipairs遇到nil会终止,而pairs会跳过。 并且此示例程序还演示了多返回值的写法,和go很类似
接收值_可忽略参数
迭代文件中每行io.lines 迭代table pairs 迭代数组ipairs 迭代单词string.gmatch

控制结构

if else elseif for while break

x   = 1
sum = 0
while x<= 5 do
    sum = sum + 1
    x = x + 1
end

print(sum)  --output: 5
for x=0,5,1 do
  while true do
        if x % 2 == 0 then
          break
        end
        print(x)
        x = x + 1
    end
end

--output  1 3 5

lua是没有continue,上面代码变相实现了continue的功能,翻译下for循环可能就是我们常见的 for x=0;x<=5;x++ 操作。循环代码跟do关键字 条件判断为then

类似 do-while 循环

x = 10
repeat
    print(x)
until false

只有until为真才能退出,正好与C相反

函数的例子

foo = {}
foo.bar = function(a,b,c)
    print(a,b,c) --output: 1 2 3
end

foo.bar(1,2,3);

可变长参数

function func(...)
    local temp = {...}
    print(table.concat(temp,',')) --output: 1,2,3,4
end

func(1,2,3,4)
--更简化的循环遍历
myTable = {1,2,3,4,5}
sum = 0
for index = 1,#myTable do
    sum = sum + myTable[index]
end

print(sum)  --output:15

小tips

在参数传递过程中 当函数参数是table类型时,是按引用传递的,其他都是按赋值传递的。这点也和go有类似之处

function func(name,...)
        print(name) --ouput: xiaoming
        print(type(...)) --output: number
        print(select('#',...)) --output: 4 获取长度
        print(select(3,...)) --output: 3 4 从第三个位置开始返回
end

func('xiaoming',1,2,3,4)

lua模块

test.lua

local test = {}

name = 'xiaming'
age = 12 

user = {name=name,age=age}
function getUser()
    return user.name,user.age
end

function test.getList()
        return 'list','list';
end

return test

main.lua

test = require('test')

print(name)  --output: xiaoming 可以直接使用

val1,val2 = getUser() --output: xiaming    12

test.getList() --output: list,list

print(val1,val2)

上面简单示例了两种函数使用方式 getUser 和test.getList,推荐第二种写法,如果相同函数名的话后面会覆盖掉前面的

Lua 元表(Metatable)

_index 源方法

当你通过键来访问 table 的时候,如果这个键没有值,那么Lua就会寻找该table的metatable(假定有metatable)中的__index 键。如果__index包含一个表格,Lua会在表格中查找相应的键。

 other = {key3=10,key4=20}
 mytable = setmetatable({key1=1,key3=3},{__index=other})

 print(mytable.key4) --output: 20

for k,v in pairs(mytable) do
        print(k..'=>'..v)

end
--output : 1 3

同时可以使用函数逻辑处理

 mytable = setmetatable({key1 = "value1"}, {
  __index = function(mytable, key)
    if key == "key2" then
      return "metatablevalue"
    else
      return nil
    end
  end
})

print(mytable.key1,mytable.key2)

__newindex 元方法

__newindex 元方法用来对表更新,__index则用来对表访问 。当你给表的一个缺少的索引赋值,解释器就会查找__newindex 元方法:如果存在则调用这个函数而不进行赋值操作。

mymetatable = {}
mytable = setmetatable({key1 = "value1"}, { __newindex = mymetatable })

print(mytable.key1)

mytable.newkey = "新值2"
print(mytable.newkey,mymetatable.newkey)

mytable.key1 = "新值1"
print(mytable.key1,mymetatable.key1)
mytable = setmetatable({key1 = "value1"}, {
  __newindex = function(mytable, key, value)
        rawset(mytable, key, "\""..value.."\"")

  end
})

为表添加操作符
文档页面: http://www.runoob.com/lua/lua-metatables.html

__tostring 元方法

other = {key3=10,key4=20}
 mytable = setmetatable({key1=1,key3=3},{
 __index=other,
 __tostring = function(mytable)
                return 'todo处理'
              end
 })

print(mytable.key4) --output: 20
print(mytable) --output: todo处理

lua面向对象

lua的对象支持给人的第一感觉不像是以前所认知的面向对象写法,而大部分是table+function的一种组合

obj = {name='lili'}

function obj.getName()
        return obj.name
end
ret = obj.getName()
print(ret) --output: lili
Company = {title='',seo='',content=''}

function Company:new (title,seo,content)
     o = {}  --此处为真正的创建一个新对象
     setmetatable(o, self) 
     self.__index = self  --将self绑定到o这个新对象上
     self.title = title or ''
     self.seo = seo or ''
     self.content = content or ''
     return o  --返回新对象
end

function Company:getInfo()
        return string.format('title-seo-content: %s %s %s',self.title,self.seo,self.content );
end

obj = Company:new(1,2,3)
print(obj.title) --output:  1
ret = obj:getInfo()
print(ret) --output: title-seo-content: 1 2 3

:是lua面向对象的语法糖。Account:new(conf)等同于Account.new(self, conf),相当于将调用者自身当做第一个参数,使用冒号调用就相当于隐式地传递self参数。

参考部分连接整理

菜鸟教程
面向对象解释
Metatable


以上是关于自学成菜-流水账学习法lua入门的主要内容,如果未能解决你的问题,请参考以下文章

Lua学习基础入门

自学Java如何入门?

自学Java怎么入门?

Lua学习基础入门

Lua学习基础入门

Python要如何快速入门?