当前位置: 首页 > article >正文

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,减少性能损耗

相关文章:

Lua再学习

因为实习的项目用到了Lua,所以再来深入学习一下 函数 函数的的多返回值 Lua中的函数可以实现多返回值,实现方法是再return后列出要返回的值的列表,返回值也可以通过变量接收到,变量不够也不会影响接收对应位置的返回值 Lua中传…...

GitLab搭建与使用(SSH和Docker)两种方式

前言 目前公共的代码仓库有很多,比如:git、gitee等等仓库但是我们在公司中,还是要搭建属于本公司自己的一个代码仓库,原因有如下几点 代码私密性,我们公司开发的代码保密性肯定一级重要,那么我们放到公网上&#xff0c…...

Linux数据库篇、第零章_MySQL30周年庆典活动

MySQL考试报名网站 Oracle Training and Certification | Oracle 中国 活动时间 2025年 MySQL的30周年庆典将于2025年举行。MySQL于1995年首次发布,因此其30周年纪念日是2025年。为了庆祝这一里程碑,MySQL将提供免费的课程和认证考试,活动…...

Windows ABBYY FineReader 16 Corporate 文档转换、PDF编辑和文档比较

作为一名合格的工人,日常工作肯定离不开PDF文件,所以今天给大家找来了一款全新的PDF处理工具,保证能给你带来不一样的体验。 软件介绍 这是一个全能型的PDF处理器,集优秀的文档转换、PDF编辑和文档比较等功能于一身,…...

设计模式简述(十九)桥梁模式

桥梁模式 描述基本组件使用 描述 桥梁模式是一种相对简单的模式,通常以组合替代继承的方式实现。 从设计原则来讲,可以说是单一职责的一种体现。 将原本在一个类中的功能,按更细的粒度拆分到不同的类中,然后各自独立发展。 基本…...

【每日一题 | 2025年5.5 ~ 5.11】搜索相关题

个人主页:Guiat 归属专栏:每日一题 文章目录 1. 【5.5】P3717 [AHOI2017初中组] cover2. 【5.6】P1897 电梯里的尴尬3. 【5.7】P2689 东南西北4. 【5.8】P1145 约瑟夫5. 【5.9】P1088 [NOIP 2004 普及组] 火星人6. 【5.10】P1164 小A点菜7. 【5.11】P101…...

C语言速成之08循环语句全解析:从基础用法到高效实践

C语言循环语句全解析:从基础用法到高效实践 大家好,我是Feri,12年开发经验的程序员。循环语句是程序实现重复逻辑的核心工具,掌握while、do-while、for的特性与适用场景,能让代码更简洁高效。本文结合实战案例&#xf…...

多模态大语言模型arxiv论文略读(六十九)

Prompt-Aware Adapter: Towards Learning Adaptive Visual Tokens for Multimodal Large Language Models ➡️ 论文标题:Prompt-Aware Adapter: Towards Learning Adaptive Visual Tokens for Multimodal Large Language Models ➡️ 论文作者:Yue Zha…...

云计算-容器云-部署CICD-jenkins连接gitlab

安装 Jenkins 将Jenkins部署到default命名空间下。要求完成离线插件的安装,设置Jenkins的登录信息和授权策略。 上传BlueOcean.tar.gz包 [root@k8s-master-node1 ~]#tar -zxvf BlueOcean.tar.gz [root@k8s-master-node1 ~]#cd BlueOcean/images/ vim /etc/docker/daemon.json…...

精讲C++四大核心特性:内联函数加速原理、auto智能推导、范围for循环与空指针进阶

前引:在C语言长达三十余年的演进历程中,每一次标准更新都在试图平衡性能与抽象、控制与安全之间的微妙关系。从C11引入的"现代C"范式开始,开发者得以在保留底层控制能力的同时,借助语言特性大幅提升代码的可维护性与安全…...

【HarmonyOS 5】鸿蒙中常见的标题栏布局方案

【HarmonyOS 5】鸿蒙中常见的标题栏布局方案 一、问题背景: 鸿蒙中常见的标题栏:矩形区域,左边是返回按钮,右边是问号帮助按钮,中间是标题文字。 那有几种布局方式,分别怎么布局呢?常见的思维…...

Docker 部署 - Crawl4AI 文档 (v0.5.x)

Docker 部署 - Crawl4AI 文档 (v0.5.x) 快速入门 🚀 拉取并运行基础版本: # 不带安全性的基本运行 docker pull unclecode/crawl4ai:basic docker run -p 11235:11235 unclecode/crawl4ai:basic# 带有 API 安全性启用的运行 docker run -p 11235:1123…...

QuecPython+Aws:快速连接亚马逊 IoT 平台

提供一个可接入亚马逊 Iot 平台的客户端,用于管理亚马逊 MQTT 连接和影子设备。 初始化客户端 Aws class Aws(client_id,server,port,keep_alive,ssl,ssl_params)参数: client_id (str) - 客户端唯一标识。server (str) - 亚马逊 Iot 平台服务器地址…...

内存安全暗战:从 CVE-2025-21298 看 C 语言防御体系的范式革命

引言 2025 年 3 月,当某工业控制软件因 CVE-2025-21298 漏洞遭攻击,导致欧洲某能源枢纽的电力调度系统瘫痪 37 分钟时,全球网络安全社区再次被拉回 C 语言内存安全的核心战场。根据 CISA 年度报告,68% 的高危漏洞源于 C/C 代码&a…...

SpringCloud Gateway知识点整理和全局过滤器实现

predicate(断言): 判断uri是否符合规则 • 最常用的的就是PathPredicate,以下列子就是只有url中有user前缀的才能被gateway识别,否则它不会进行路由转发 routes:- id: ***# uri: lb://starry-sky-upmsuri: http://localhost:9003/predicate…...

全球实物文件粉碎服务市场洞察:合规驱动下的安全经济与绿色转型

一、引言:从纸质堆叠到数据安全的“最后一公里” 在数字化转型浪潮中,全球企业每年仍产生超过1.2万亿页纸质文件,其中包含大量机密数据、客户隐私及商业敏感信息。据QYResearch预测,2031年全球实物文件粉碎服务市场规模将达290.4…...

冒泡排序的原理

冒泡排序是一种简单的排序算法,它通过重复地遍历待排序的列表,比较相邻的元素并交换它们的位置来实现排序。具体原理如下: 冒泡排序的基本思想 冒泡排序的核心思想是通过相邻元素的比较和交换,将较大的元素逐步“冒泡”到列表的…...

Day22 Kaggle泰坦尼克号训练实战

​ 作业 自行学习参考如何使用kaggle平台,写下使用注意点,并对下述比赛提交代码 kaggle泰坦里克号人员生还预测 一、流程 思路概述 数据加载 :读取泰坦尼克号的训练集和测试集。数据预处理 :处理缺失值、对分类变量进行编码、…...

深入浅出之STL源码分析7_模版实例化与全特化

1.引言 显示实例话和全特化的区别,之前我们在讨论类模版的时候,讨论过,他俩不是同一个概念,类模版中你如果全特化了,还是需要实例化才能生成代码,但是对于函数模版,这个是不同的,函…...

CAPL -实现SPRMIB功能验证

系列文章目录 抑制肯定响应消息指示位(SPRMIB) 二十一、CANdelaStudio深入-SPRMIB的配置 文章目录 系列文章目录一、SPRMIB是什么?二、SetSuppressResp(long flag)三、GetSuppressResp 一、SPRMIB是什么? 正响应:表示…...

2025 Mac常用软件安装配置

1、homebrew 2、jdk 1、使用brew安装jdk: brew install adoptopenjdk/openjdk/adoptopenjdk8 jdk默认安装位置在 /Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk/Contents/Home 目录。 2、配置环境变量: vim ~/.zshrc# Jdk export JAVA_HOM…...

容器技术 20 年:颠覆、重构与重塑软件世界的力量

目录 容器技术发展史 虚拟化技术向容器技术转变 Docker的横空出世 容器编排技术与Kubernetes 微服务的出现与Istio 工业标准的容器运行时 容器技术与 DevOps 的深度融合​ 无服务架构推波助澜 展望未来发展方向 从 20 世纪硬件虚拟化的笨重,到操作系统虚拟…...

cmake:test project

本文主要探讨cmake在测试和项目中的应用。 add_test add_test(NAME <name> COMMAND <command> [<arg>...] [CONFIGURATIONS <config>...] [WORKING_DIRECTORY <dir>] [COMMAND_EXPAND_LISTS])  add_test(NAME test_uni COMMAND $<TARGET_F…...

C++开发过程中的注意事项详解

目录 C++开发过程中的注意事项详解 一、内存管理:避免泄漏与资源浪费 1.1 使用智能指针管理动态内存 1.2 避免手动内存管理的陷阱 1.3 利用RAII机制管理资源 1.4 容器与内存分配 二、安全性:防御攻击与未定义行为 2.1 输入验证与安全编码 2.2 使用安全的通信协议 2…...

OpenWrt开发第8篇:树莓派开发板做无线接入点

文/指尖动听知识库-谷谷 文章为付费内容,商业行为,禁止私自转载及抄袭,违者必究!!! 文章专栏:Openwrt开发-基于Raspberry Pi 4B开发板 树莓派开发板作为无线接入点的时候,可以通过电脑和手机打开WiFi功能搜索到相应打开的WiFi; 1 通过Web操作界面开启wifi 1...

Leetcode (力扣)做题记录 hot100(42,104,226,101)

力扣第42题&#xff1a;接雨水 42. 接雨水 - 力扣&#xff08;LeetCode&#xff09; 左边遍历一次记录左侧最大值 右边同理&#xff0c;最后遍历一次 左侧右侧最小值减去当前值即可。 class Solution {public int trap(int[] height) {int n height.length;int[] leftMax …...

第六天:Java数组

数组 数组概述 数组是相同类型数据的有序集合。数组中的元素可以是任意数据类型&#xff0c;包括基本类型和引用类型数组描述是相同类型的若干个数据&#xff0c;按照一定的先后顺序排列组合而成。数组下标从0开始。 数组声明与创建 数组的声明 int[] nums;//声明一个数组…...

李沐动手深度学习(pycharm中运行笔记)——09.softmax回归+图像分类数据集+从零实现+简洁实现

09.softmax回归图像分类数据集从零实现简洁实现&#xff08;与课程对应&#xff09; 目录 一、softmax回归 1、回归 vs 分类 2、经典分类数据集&#xff1a; 3、从回归到分类——均方损失 4、从回归到多类分类——无校验比例 5、从回归到多类分类——校验比例 6、softmax和…...

Kubernetes生产实战(二十):容器大镜像拉取优化指南

在 Kubernetes 中优化大容器镜像的拉取速度&#xff0c;需要结合 镜像构建策略、集群网络架构 和 运行时配置 多方面进行优化。以下是分步解决方案&#xff1a; 一、镜像构建优化&#xff1a;减小镜像体积 1. 使用轻量级基础镜像 替换 ubuntu、centos 为 alpine、distroless …...

Qt获取CPU使用率及内存占用大小

Qt 获取 CPU 使用率及内存占用大小 文章目录 Qt 获取 CPU 使用率及内存占用大小一、简介二、关键函数2.1 获取当前运行程序pid2.2 通过pid获取运行时间2.3 通过pid获取内存大小 三、具体实现五、写在最后 ​ 一、简介 近期在使用软件的过程中发现一个有意思的东西。如下所示&a…...