Lua再学习

因为实习的项目用到了Lua,所以再来深入学习一下

函数

函数的的多返回值

Lua中的函数可以实现多返回值,实现方法是再return后列出要返回的值的列表,返回值也可以通过变量接收到,变量不够也不会影响接收对应位置的返回值

Lua中传入参数和参数个数不匹配也不会报错,只会补空或丢弃

函数的重载

在Lua中他是不支持函数的重载的,默认调用最后声明的这个函数,但是使用重载的方法也不会报错

变长参数

变长参数在函数内使用时需要先用一个表存起来,然后再去操作

function add(...)  
local s = 0  for i, v in ipairs{...} do   --> {...} 表示一个由所有变长参数构成的数组  s = s + v  end  return s  
end  
print(add(3,4,5,6,7))  --->25

函数嵌套

function F8(x)return function(y)//不需要命名return x+yend
end
f9=F8(10)//相当于返回一个函数类型的变量
print(f9(5))//15

这也是Lua中闭包的体现
改变传入参数的生命周期
传入参数x本应在执行完之后被销毁,但因为闭包改变了x的生命周期让其可以持续存在

table

lua中所有的复杂类型都是table,数组二维数组字典类都是用table实现的
数组
lua中索引从1开始
a={1,2,4,“123”}
#是通用的获取长度的关键字
如果表中某一位为nil会影响#获取长度(5.1已改),长度从nil开始截断
二维数组

a={{1,2,3},{4,5,6}}
for i=1,#a dob=a[i]for j=1,#b doprint(b[j])end
end

table实现类

lua中复杂一点的数据结构都是通过类来实现的
lua中没有面向对象的概念,需要我们自己来实现

Student={age=1,sex=true,Up=function()//函数体//在表内部的函数调用表内部的变量必须要指定是谁的print(Student.age)end,Learn=function(t)//把自己作为参数传进来print(t.age)//函数体end
}
//不像C#一样需要new一个对象来实现调用
Student.Up()
//可以在表外申明表的变量和方法
Student.name="111"
Student.Speak=function()
end
function Student.Speak2()
end
//冒号会把调用者作为第一个参数传入
//如果使用冒号申明函数,相当于有一个默认参数
Student:Learn()
Student.Learn(Student)

协程

协程的创建
协程的创建一般依附于一个函数
协程的本质是一个线程对象

--常用方式
--返回的是一个线程
fun=function()
end
co=coroutine.create(fun)
--返回的是一个函数
co2=coroutine.wrap(fun)

协程的运行
两种创建方式对应的运行方式也不同

coroutine.resume(co)
--因为协程返回的是一个函数,所以可以直接运行
co2()

协程的挂起

fun2=function()while ture doprint("123")--挂起函数coroutine.yield()//协程也可以返回值--coroutinre.yield(i)end
end
co3=coroutine.create(fun2)
--区别于C#的协程,lua中的协程每调用一次执行一次对应的函数
coroutine.resume(co3)
-- 默认第一个返回值是协程是否启动成功--这种方式的协程调用也可以有返回值,只是没有默认第一个返回值了
co4=coroutine.wrap(fun2)
co4()
co4()

协程的状态
dead结束
running运行
suspended暂停

coroutine.status(协程对象)
--获取正在运行的协程的协程号
coroutine.running()

元表

元表概念
任何表变量都可以作为另一个表变量的元表
任何表变量都可以有自己的元表
当我们子表(有元表的表)进行一定操作时会执行元表中的内容

设置元表

mete={}
mytable={}
--设置元表函数,第一个参数子表,第二个参数元表
setmetatable(mete,mytable)
getmetatable(mete)--获得子表对应的元表

元表的特定操作

__tostring(用的多)

mete={--当子表要作为字符串使用时,会默认调用元表中的__tostring 方法__tostring=function(t)return t.nameend
}
mytable={name="123"
}
setmetatable(mete,mytable)
print(mytable)--输出123

__call(用的多)

mete={--当子表被当作一个函数来使用时,会默认调用这个__call中的内容--当希望传参数时第一个参数一定是调用者自己__call=function(a,b)print(a)print(b)end
}
mytable={name="123"
}
setmetatable(mete,mytable)
print(mytable)
--输出123
1

运算符重载(用的可能不多)

mete={--相当于运算符重载 当子表使用对应运算符时会调用该方法-- +__add=function(a,b)return a.name+b.nameend,-- ==调用的两个表的元表必须一致,才能准确调用此方法__eq=function(a,b)return trueend
}
mytable={name=1
}
mytable2={name=2
}
setmetatable(mete,mytable)
print(mytable+mytable2)
--输出123
1

__index

mete={}
meta.__index={age=2}
-- __index的赋值写在表外面来初始化,和C++的构造函数不可以是虚函数一个道理,自己都没有初始化好要怎么指向自己内部的东西呢
mytable={}
setmetatable(mete,mytable)
__index:当子表中找不到某一个属性时,会到元表中__index指定的表去找属性
print(mytable.age)--输出2

__index还可以实现“套娃”,当子表中找不到某一个属性时,会到元表中找这个属性,如果元表中也找不到该属性则会到元表的元表中去寻找

__newIndex

__newIndex当赋值时,如果赋值一个不存在的索引,那么会把这个值赋值到__newIndex所指的表中,不会修改自己

mete={}
meta.__newIndex={}
mytable={
}
setmetatable(mete,mytable)
mytable.age=1
print(mytable.age)--输出2

使用rawget和rawset可以直接设置对应的表,而非索引指向的元表

实现面向对象

表就是表现类的一种形式

在Lua中,冒号语法糖用于简化方法的定义和调用,自动传递self参数。当用冒号定义方法时,实际上隐式地添加了self作为第一个参数。例如,obj:method() 转换成 obj.method(obj)
如果用点号调用时冒号声明的方法,需要显式传递self。

封装

声明对象实际上是声明了一张空表,获取属性是通过设置元表后获取元表的属性实现的

--self代表的是我们默认传入的第一个参数
--对象就是变量,返回一个新的变量
--返回出去的内容本质是一个表对象Object={}
Object.id=1
function Object:Test()print(self.id)
endfunction Object:new()local obj={}--当子表中找不到某一个属性时,会到元表中__index指定的表去找属性self.__index=selfsetmetatable(obj,self)return obj
endlocal myobj=Object:new()
myobj:Test()--输出1
对空表中申明一个新的属性叫做id
myobj.id=2
myobj:Test()--输出2

继承

接上文
_G来根据字符串创建一个新的表(类)
在这里插入图片描述

function Object:subClass(classNmae)-- _G是总表 所有声明的全局标量 都以键值对的形式存在在其中_G[className]={}local obj=_G[className]self.__index=selfsetmetatable(obj,self)
end
Object:subClass("Person")
local p1=Person:new()
print(p1.id)--输出1

多态

多态的本质是相同的方法执行不同的逻辑

代码接上文
方法1:子类直接重写这个方法
方法2:通过给子类添加base属性保留父类逻辑执行

function Object:subClass(classNmae)-- _G是总表 所有声明的全局标量 都以键值对的形式存在在其中_G[className]={}local obj=_G[className]self.__index=self-- 为子类定义base属性 base属性代表父类obj.base=selfsetmetatable(obj,self)
endObject:subClass("GameObject")
GameObject.PosX=0
GameObject.PosY=0function GameObject:Move()self.PosX=self.PosX+1self.PosY=self.PosY+1
end
Object:subClass("Player")function Player:Move()
-- base指的是GameObject表()
-- 这种调用方式相当于是把基类表作为第一个参数传入了方法中self.base:Move()
endlocal p1=Player:new()
p1:Move()
local p2=Player:new()
p2:Move()

目前这种写法有坑,不同对象使用的成员变量是相同的成员变量,不是自己的

更正版

function Player:Move()
-- 如果我们要执行父类逻辑,则需要避免将父类传入到方法中
-- 所以要使用.去调用,自己传入第一个参数self.base.Move(self)
end

总结

Object={}
Object.id=1
function Object:new()local obj={}--给空对象设置元表和__indexself.__index=selfsetmetatable(obj,self)return obj
endfunction Object:subClass(classNmae)-- 根据名字生成一张表,即一个类_G[className]={}local obj=_G[className]--给子类设置元表以及__indexself.__index=self--设置自己的父类obj.base=selfsetmetatable(obj,self)
end--申明一个新的类
Object:subClass("GameObject")
--成员变量
GameObject.PosX=0
GameObject.PosY=0
--成员方法
function GameObject:Move()self.PosX=self.PosX+1self.PosY=self.PosY+1
end-- 实例化对象使用
local obj=GameObject:new()
obj:Move()--申明一个新的类,Player继承GameObject
Object:subClass("Player")--重写了Move方法
function Player:Move()
--base调用父类方法,自己传第一个参数self.base.Move(self)
endlocal p1=Player:new()
p1:Move()

垃圾回收

collectgarbage

test={id=1}
-- lua中的机制和垃圾回收很类似,置空之后就认定为垃圾
test=nil
--进行垃圾回收,理解有点像C#的GC
collectgarbage("collect")
--获取当前lua占用内存数
collectgarbage("count")

lua中有自动定时进行GC的方法
但是在热更新开发中通常不会使用自动GC,而是选择在内存占用量达到一定程度时手动GC,减少性能损耗

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/80981.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

TCP协议十大核心特性深度解析:构建可靠传输的基石

TCP(传输控制协议)作为互联网的"交通指挥官",承载着全球80%以上的网络流量。本文将深入解析TCP协议的十大核心特性,通过原理剖析、流程图解和实战案例,揭示其如何实现高效可靠的数据传输。 一、面向连接的可…

基于 Spring Boot 瑞吉外卖系统开发(十三)

基于 Spring Boot 瑞吉外卖系统开发(十三) 查询套餐 在查询套餐信息时包含套餐的分类名,分类名称在category表中,因此这里需要进行两表关联查询。 自定义SQL如下: select s.* ,c.name as category_name from setmeal…

华为IP(6)

VLAN聚合 VLAN聚合产生的技术背景 在一般是三层交换机中,通常采用一个VLAN接口的方式实现广播域之间的互通,这在某些情况下导致了IP地址的浪费 因为一个VLAN对应的子网中,子网号、子网广播地址、子网网关地址不能用作VLAN内的主机IP地址&a…

深度解析IP静态的工作原理,IP静态的应用场景又哪些?

一、什么是IP静态? 当我们谈到“IP静态”时,大家可能首先想到的是与“动态IP”相对的概念。确实如此,静态IP是一种固定分配的IP地址,也就是说,在特定时间内,分配给你的IP地址不会有所更改——无论你完成多…

docker(四)使用篇一:docker 镜像仓库

前文我们已经介绍了 docker 并安装了 docker,下面我们将正式步入使用环节,本章是第一个使用教学:docker 镜像仓库。 一、什么是镜像仓库 所谓镜像仓库,其实就是负责存储、管理和分发镜像的仓库,并且建立了仓库的索引…

单片机开发软件

目录 纯编码 vscode Ardunio Keil 1. 集成化开发环境(IDE) 2. 多架构芯片支持 3. 高效的代码生成与优化 4. 强大的调试与仿真功能 5. 丰富的库函数与生态系统 6. 教育与企业级适用性 典型应用场景 半编码半图形化 STM32CUBEIED 1. 图形化配置…

【虚幻引擎】UE5独立游戏开发全流程(商业级架构)

本套课程我将会讲解一下知识 1.虚幻引擎的常用功能节点、模块包含但不限于动画模块、UI模块、AI模块、碰撞模块、伤害模块、背包模块、准心模块、武器模块、可拾取物品模块、死亡等模块。 2.整个游戏的设计思路(游戏架构),本套教程讲解了如…

ABP-Book Store Application中文讲解 - Part 2: The Book List Page

本章用于介绍如何创建Book List Page。 TBD 1. 汇总 ABP-Book Store Application中文讲解-汇总-CSDN博客 2. 前一章 ABP-Book Store Application中文讲解 - Part 1: Creating the Server Side 项目之间的引用关系。 目录 1. 多语言配置 1.1 zh-Hans.json 1.2 en.jso…

6、登录功能后端开发

6、登录功能后端开发 https://xiaoxueblog.com/ai/%E7%99%BB%E5%BD%95%E5%8A%9F%E8%83%BD%E5%90%8E%E7%AB%AF%E5%BC%80%E5%8F%91.html 1、新建用户表SQL脚本 -- CREATE DATABASE aicloud CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;-- 创建用户表 drop table if exi…

随机矩阵放大的方式 生成相位数据集,用于相位展开

import os import numpy as np import matplotlib.pyplot as plt from scipy.ndimage import zoom import gc from tqdm import tqdm from zernike import RZerndef wrap_phase(phase):"""将相位包裹到[-π, π]区间"""return np.angle(np.exp(1…

Java面试全记录:Spring Cloud+Kafka+Redis实战解析

Java面试全记录:Spring CloudKafkaRedis实战解析 人物设定 姓名:张伟(随机生成唯一姓名) 年龄:28岁 学历:硕士 工作年限:5年 工作内容: 基于Spring Cloud搭建微服务架构使用Kafka…

Java Socket编程完全指南:从基础到实战应用

Socket编程是构建网络应用的基石,Java通过java.net包提供了强大的Socket API。本文将深入解析Java Socket类的核心用法,涵盖TCP/UDP协议实现、多线程通信及性能优化技巧,助您快速掌握网络编程精髓。 一、Socket编程核心概念 1.1 网络通信模型…

vue实现导出echarts图片和table表格

安装依赖 "xlsx": "^0.18.5","xlsx-style": "^0.8.13""file-saver": "^2.0.5",工具类 toolUtil const autoHeight () > {let winHeight 0if (window.innerHeight) {winHeight window.innerHeight} else if…

AI预测3D新模型百十个定位预测+胆码预测+去和尾2025年5月15日第78弹

从今天开始,咱们还是暂时基于旧的模型进行预测,好了,废话不多说,按照老办法,重点8-9码定位,配合三胆下1或下2,杀1-2个和尾,再杀6-8个和值,可以做到100-300注左右。 (1)定…

兰亭妙微B端UI设计:融合多元风格,点亮品牌魅力

在B端产品市场,独特的品牌形象是企业脱颖而出的关键。兰亭妙微专注于B端UI设计,通过融合多元风格,为企业点亮品牌魅力,助力品牌价值提升。 兰亭妙微主创团队源自清华,历经多年沉淀,积累了丰富的设计经验。…

MMTEA-DTS--用于多目标多任务优化的基于分解的迁移选择

MMTEA-DTS–用于多目标多任务优化的基于分解的迁移选择 title: Multiobjective Multitasking Optimization With Decomposition-Based Transfer Selection author: Qiuzhen Lin, Zhongjian Wu, Lijia Ma, Maoguo Gong , Jianqiang Li, and Carlos A. C…

Python机器学习笔记(二十三 模型评估与改进-网格搜索)

上一次学习了评估一个模型的泛化能力,现在继续学习通过调参来提升模型的泛化性能。scikit-learn中许多算法的参数设置,在尝试调参之前,重要的是要理解参数的含义。找到一个模型的重要参数(提供最佳泛化性能的参数)的取值是一项棘手的任务,但对于几乎所有模型和数据集来说…

集成DHTMLX 预订排期调度组件实践指南:如何实现后端数据格式转换

在企业级应用中,预订系统(Booking System)作为典型的调度类应用,广泛用于酒店、会议室、设备预约、医疗排班等业务场景。而DHTMLX Scheduler作为一款功能强大且高度可定制的 JavaScript 日程安排控件,已成为众多开发者…

35页AI应用PPT《DeepSeek如何赋能职场应用》DeepSeek本地化部署与应用案例合集

这份名为《DeepSeek如何赋能职场应用》的PPT文档详细介绍了DeepSeek这一人工智能工具在职场中的多样化应用场景和操作技巧。内容涵盖了从基础模型到深度思考模型的不同功能,以及如何通过提示语技巧实现高效的人机协作。文档还展示了DeepSeek在制作可视化图表、PPT、…

Axure疑难杂症:母版菜单设置打开链接后菜单选中效果

亲爱的小伙伴,在您浏览之前,烦请关注一下,在此深表感谢! Axure产品经理精品视频课已登录CSDN可点击学习https://edu.csdn.net/course/detail/40420 课程主题:菜单打开链接后子菜单选中效果 主要内容:母版设计、选中效果 应用场景:页面赋值 案例展示: 案例视频: