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

PHP serialize进行序列化工作的完全指南

如果你和我一样第一次在 PHP 中看到序列化字符串时会觉得很困惑。我当时在做一个 Laravel 项目想搞清楚将任务推送到队列时到底发生了什么。我发现一些数据被序列化了但不知道为什么以及怎么工作的。不过在我花时间研究序列化后发现它其实没那么复杂。本文会介绍什么是序列化以及工作原理。然后会说明如何使用 PHP 的内置序列化函数让你能在应用中序列化和反序列化数据。最后会讲如何编写测试来确保序列化代码正常工作。读完这篇文章你应该能理解什么是序列化并且能放心地在项目中使用。什么是序列化序列化就是把变量、对象或数据结构转换成字符串格式的过程。这种字符串格式能表示原始数据方便存储或传输。反过来反序列化在 PHP 中通常叫unserialization就是把序列化的数据转换回原来的形式。序列化很重要常用于把数据存储到缓存、数据库或文件中。数据可以序列化成很多格式比如 JSON、XML甚至二进制格式比如 gRPC API 用的 Protocol Buffers。不过这篇文章主要讲 PHP 的内置序列化函数。举个例子如果你用过 Laravel应该注意到这个框架在把任务推送到队列时会序列化数据。比如下面这个 Laravel 中被推到队列的待处理任务为了好看分了行并去掉了一些属性12345678{uuid:3d05be68-8cd0-4c3a-8d05-71e86871713a,data: {commandName:App\\Jobs\\SendOneTimePassword,command: O:28:\App\\Jobs\\SendOneTimePassword\:1:{s:15:\oneTimePassword\;s:6:\123456\;}}}在这个待处理任务的 JSON 例子中data.command属性是个序列化字符串代表一个App\Jobs\SendOneTimePassword任务。队列工作器拿到这个任务时会把序列化字符串反序列化创建App\Jobs\SendOneTimePassword类的实例来处理。如果现在看不懂也没关系后面会有更多例子来解释。PHP 中的序列化如何工作PHP 中可以用serialize和unserialize函数来序列化和反序列化数据。serialize函数接受要序列化的数据返回字符串格式。unserialize函数接受序列化的数据返回原来的数据结构。看看怎么在 PHP 中序列化和反序列化不同类型的数据序列化字符串序列化字符串很简单直接传给serialize函数1$serialized serialize(Hello);这将返回一个序列化字符串s:5:Hello;这乍看起来有点奇怪但一旦你注意到模式你会发现它并不像看起来那么可怕。我们的序列化数据遵循格式data_type:string_length:string;。所以在上面序列化字符串的情况下s代表字符串并表示反序列化数据时的数据类型5是字符串的长度。然后我们可以将该序列化字符串传递给unserialize函数以获取原始字符串1$string unserialize(s:5:Hello;);序列化整数和浮点数我们也可以在 PHP 中序列化整数和浮点数。以下是序列化整数的方法1serialize(123);这将返回一个序列化字符串i:123;你可能已经注意到结构与我们之前看到的序列化字符串略有不同。整数使用格式data_type:data;进行序列化。注意这里我们没有像字符串那样的大小。在这种情况下序列化数据的数据类型是i表示整数。同样我们可以序列化浮点数1serialize(123.45);这将返回一个序列化字符串d:123.45;这个结构类似于整数序列化但数据类型是d表示双精度浮点数。序列化布尔值我们也可以在 PHP 中序列化布尔值。例如我们可以序列化true1serialize(true);这将返回一个序列化字符串其中b作为数据类型1表示 true作为值b:1;同样我们可以序列化false1serialize(false);这将返回一个序列化字符串其中b作为数据类型0表示 false作为值b:0;序列化数组我们可以这样在 PHP 中序列化数组1serialize([1,2,3]);这将返回一个序列化字符串a:3:{i:0;i:1;i:1;i:2;i:2;i:3;}现在你可能已经注意到这比我们已经看过的其他序列化数据要复杂一些。让我们分解一下。字符串具有data_type:size:{key_data_type:key_data;value_data_type:value_data;...}的结构。在这种情况下data_type是a表示数组size是3因为数组有 3 个元素。如果我们然后查看{ }内的数据我们可以看到键由i表示整数值也由i表示整数。通过将它们分成新行来可视化结构可能会有所帮助i:0;i:1;i:1;i:2;i:2;i:3;作为另一个例子让我们看看序列化的字符串数组可能是什么样子。我们可以序列化以下数组1serialize([a,b,c]);这将返回一个序列化字符串a:3:{i:0;s:1:a;i:1;s:1:b;i:2;s:1:c;}正如我们在上面的序列化字符串中看到的键仍然由i表示而值由s表示字符串。为了帮助可视化结构我们可以将数据分成新行i:0;s:1:a;i:1;s:1:b;i:2;s:1:c;同样我们也可以序列化关联数组1serialize([aA,bB,cC]);这将返回一个序列化字符串a:3:{s:1:a;s:1:A;s:1:b;s:1:B;s:1:c;s:1:C;}正如我们所看到的结构与我们已经看过的序列化数组非常相似。但是在这种情况下键由s表示字符串。为了帮助可视化结构我们可以将数据分成新行s:1:a;s:1:A;s:1:b;s:1:B;s:1:c;s:1:C;序列化枚举我们也可以在 PHP 中序列化枚举。作为一个基本示例假设我们有以下表示博客文章状态的枚举12345678namespaceApp\Enums;enum PostStatus: string{casePublished published;caseDraft draft;casePending in_review;}让我们想象然后创建此枚举的新实例并像这样序列化它1serialize(PostStatus::Published);这将返回一个序列化字符串E:30:App\Enums\PostStatus:Published;序列化枚举的结构是data_type:size:enum_type:enum_value;。在这种情况下数据类型由E表示大小是30因为类名是App\Enums\PostStatus枚举值是Published。序列化对象到目前为止我们已经介绍了序列化如何适用于基本数据类型如字符串、整数、浮点数、布尔值、数组和枚举。但是对象呢默认情况下除了少数内置 PHP 类之外所有对象都是可序列化的。为了解释对象序列化的工作原理让我们以一个基本的App\User类为例它包含三个公共属性12345678910namespaceApp;classUser{publicfunction__construct(publicstring$name,publicstring$email,publicstring$apiToken,) { }}我们将创建此类的新实例并序列化它1234567$usernewUser(name:Ash Allen,email:mailashallendesign.co.uk,apiToken:secret,);serialize($user);这将返回一个序列化字符串O:8:App\User:3:{s:4:name;s:9:Ash Allen;s:5:email;s:25:mailashallendesign.co.uk;s:8:apiToken;s:6:secret;}让我们分解序列化对象的结构。我们有以下结构12345data_type:class_name_size:class_name:property_count:{property_name_type:property_name_size:property_name;property_value_type:property_value_size:property_value;...}因此从这个结构中我们可以看到数据类型是O表示对象类名大小是8类名是App\User属性计数是3因为对象有 3 个属性。然后我们可以看到{ }内的每个序列化属性。然后我们可以将此序列化字符串传递给unserialize函数以获取原始对象12345$serializedO:8:App\User:3:{s:4:name;s:9:Ash Allen.;s:5:email;s:25:mailashallendesign.co.uk;s:8:.apiToken;s:6:secret;};$user unserialize($serialized);这将返回App\User类的实例每个属性都像原始对象一样设置。属性可见性序列化对象时属性的可见性很重要因为它会影响返回的字符串。让我们更新我们的App\User类以具有公共、受保护和私有属性12345678910namespaceApp;classUser{publicfunction__construct(publicstring$name,protectedstring$email,privatestring$apiToken,) { }}然后我们将创建此类的新实例并序列化它1234567$usernewUser(name:Ash Allen,email:mailashallendesign.co.uk,apiToken:secret,);serialize($user);这将返回一个序列化字符串O:8:App\User:3:{s:4:name;s:9:Ash Allen;s:8:\0*\0email;s:25:mailashallendesign.co.uk;s:18:\0App\User\0apiToken;s:6:secret;}字符串格式与我们之前的序列化对象非常相似。但是email和apiToken属性的名称略有不同。当 PHP 序列化对象时它将为属性名添加前缀以指示属性的可见性。受保护的属性由*前缀指示私有属性由类名前缀指示。所以我们可以看到我们有\0*\0email和\0App\User\0apiToken\0表示空字节而不是email和apiToken。让我们将序列化字符串分成新行以帮助可视化结构s:4:name;s:9:Ash Allen;s:8:\0*\0email;s:25:mailashallendesign.co.uks:18:\0App\User\0apiToken;这意味着通过查看序列化对象我们可以确定属性的可见性。序列化包含其他对象的对象有时你可能需要序列化包含另一个对象的对象。我们将快速看一下包含另一个对象的序列化对象可能是什么样子。假设我们有一个简单的App\ValueObjects\Address类123456789namespaceApp\ValueObjects;classAddress{publicfunction__construct(publicint$number,publicstring$postalCode,) { }}然后我们假设我们的App\User类有一个App\ValueObjects\Address对象作为属性。我们可能想要创建一个新对象并序列化它12345678$usernewUser(name:Ash Allen,email:mailashallendesign.co.uk,apiToken:secret,address:newAddress(18,SW1A 2AA),);serialize($user);这将导致如下序列化字符串O:8:App\User:4:{s:4:name;s:9:Ash Allen;s:5:email;s:25:mailashallendesign.co.uk;s:8:apiToken;s:6:secret;s:7:address;O:24:App\ValueObjects\Address:2:{s:6:number;i:18;s:10:postalCode;s:8:SW1A 2AA;}}让我们将此对象的内容分解到单独的行上s:4:name;s:9:Ash Allen;s:5:email;s:25:mailashallendesign.co.uk;s:8:apiToken;s:6:secret;s:7:address;O:24:App\ValueObjects\Address:2:{s:6:number;i:18;s:10:postalCode;s:8:SW1A 2AA;}正如我们在这里看到的App\ValueObjects\Address对象只是作为App\User对象的属性序列化。反序列化时的错误处理处理尝试反序列化无效数据时可能发生的任何错误很重要。根据你尝试反序列化的无效数据PHP 8.3 将发出E_WARNING或抛出\Exception或\Error。例如让我们看看这个无效的序列化字符串它对字符串hello的长度为 10 而不是预期的 51unserialize(s:10:hello;);如果我们在 PHP 8.3 中运行此代码将发出E_WARNING错误消息如下Warning: unserialize(): Error at offset 2 of 13 bytes in/www/serialization.php on line 3为了处理警告以便我们可以在代码中捕获和处理它们我们可以使用set_error_handler函数设置自定义错误处理程序。这将允许我们捕获警告并将它们作为异常抛出。为此我们首先创建一个新的App\Services\Serializer类如下所示12345678910111213141516171819202122232425declare(strict_types1);namespaceApp\Services;finalreadonlyclassSerializer{publicfunctionunserialize(string$serialized): mixed{try{set_error_handler(staticfunction($severity,$message,$file,$line) {thrownew\ErrorException($message, 0,$severity,$file,$line);});$result unserialize($serialized);} finally {restore_error_handler();}return$result;}}在此类中我们添加了一个接受序列化字符串的unserialize方法。然后我们覆盖错误处理程序以便我们可以捕获任何警告并将它们作为异常抛出。然后我们尝试反序列化数据。如果发出警告它将作为异常抛出。然后我们在finally块内将错误处理程序恢复到其原始状态无论反序列化是否成功都会运行。假设成功我们然后返回反序列化的数据。然后我们可以使用此类来反序列化数据12345useApp\Services\Serializer;$result (newSerializer())-unserialize(serialized:s:10:hello;);运行上述代码将导致抛出\ErrorException消息如下1unserialize(): Error at offset 2 of 13 bytes或者我们可以运行以下代码12345useApp\Services\Serializer;$result (newSerializer())-unserialize(serialized:s:5:hello;);这将导致返回字符串hello。目前有一个 RFC部分实现旨在改进反序列化数据时的错误处理。RFC 包含一个提案从 PHP 9.0 开始改变unserialize的行为使其抛出\UnserializationFailedException而不是发出E_WARNING。因此如果实现了这一点我们不需要覆盖错误处理程序来捕获警告并将它们作为异常抛出就像我们上面所做的那样。在 PHP 中定义序列化逻辑正如我们在上面已经看到的PHP 默认提供序列化和反序列化对象的能力。但是有时你可能想要为对象定义自定义序列化逻辑。这可能有几个原因例如在序列化之前加密敏感数据或者你可能需要在反序列化对象时执行一些额外的逻辑。值得庆幸的是PHP 提供了两个魔术方法你可以使用它们来定义如何序列化和反序列化对象__serialize和__unserialize。为了了解这可能如何工作让我们看一个例子。坚持我们之前的App\User类假设我们想要在序列化对象之前加密apiToken属性并在反序列化对象时解密它。这可能是因为我们将序列化数据存储在缓存或队列中所以我们想要确保数据在受到威胁时是安全的。为了本文的目的我们将假设我们有两个可以调用来加密和解密数据的函数encrypt和decrypt。我们现在不需要担心这些函数的实现我们只是假设它们存在。如果你们中的任何人是 Laravel 开发者你们可能会认识这些函数因为它们都随 Laravel 一起提供。让我们更新我们的App\User类以包含__serialize和__unserialize方法然后讨论正在做什么12345678910111213141516171819202122232425262728declare(strict_types1);namespaceApp;classUser{publicfunction__construct(publicstring$name,publicstring$email,publicstring$apiToken,) { }publicfunction__serialize():array{return[name$this-name,email$this-email,apiToken encrypt($this-apiToken),];}publicfunction__unserialize(array$data): void{$this-name $data[name];$this-email $data[email];$this-apiToken decrypt($data[apiToken]);}}在__serialize方法中我们返回要序列化的属性数组。我们在返回之前加密apiToken属性。这意味着当我们对对象调用serialize时apiToken属性将被加密。让我们创建App\User类的新实例并序列化它1234567$usernewUser(name:Ash Allen,email:mailashallendesign.co.uk,apiToken:secret,);$serialized serialize($user);序列化字符串可能如下所示为简洁起见缩短了加密字符串O:8:App\User:3:{s:4:name;s:9:Ash Allen;s:5:email;s:25:mailashallendesign.co.uk;s:8:apiToken;s:200:eyJpdiI6Ikx0N3BDQwYzcwMzE1NGQy...sdfsfsfdssInRhZyI6IiJ9;}正如我们所看到的apiToken属性现在已加密没有加密密钥就无法解密数据。现在如果我们想从序列化字符串创建App\User类的实例我们可以对字符串调用unserialize将调用__unserialize方法。此__unserialize方法接受序列化数据的数组因此我们可以分配每个属性并解密apiToken属性。测试你的序列化代码就像应用程序的任何其他部分一样如果你正在自定义对象的序列化和反序列化方式你可能会想要为序列化逻辑编写测试。这是确保你的序列化代码按预期工作并且你可以捕获任何错误的好方法。例如让我们看看我们刚刚看过的前面的例子。如果我们意外地从apiToken属性的__unserialize()函数中删除了decrypt()函数调用会发生什么这将导致我们拥有一个具有加密令牌而不是我们期望的原始未加密值的对象。

相关文章:

PHP serialize进行序列化工作的完全指南

如果你和我一样,第一次在 PHP 中看到序列化字符串时会觉得很困惑。我当时在做一个 Laravel 项目,想搞清楚将任务推送到队列时到底发生了什么。我发现一些数据被序列化了,但不知道为什么以及怎么工作的。不过在我花时间研究序列化后&#xff0…...

WuliArt Qwen-Image Turbo效果对比:FP16黑图频发 vs BF16稳定出图实测

WuliArt Qwen-Image Turbo效果对比:FP16黑图频发 vs BF16稳定出图实测 1. 引言:从“黑图”困扰到稳定出图 如果你用过一些本地部署的文生图模型,可能遇到过这样的糟心事儿:满怀期待地输入一段描述,点击生成&#xff…...

Qwen3.5-9B快速上手:3步启动WebUI(supervisorctl restart)超详细步骤

Qwen3.5-9B快速上手:3步启动WebUI(supervisorctl restart)超详细步骤 1. 开篇介绍 Qwen3.5-9B是一款拥有90亿参数的开源大语言模型,具备强大的逻辑推理、代码生成和多轮对话能力。特别值得一提的是,它的多模态变体Qw…...

lingbot-depth-pretrain-vitl-14多场景落地:AR实时遮挡、3D重建、工业检测一文详解

lingbot-depth-pretrain-vitl-14多场景落地:AR实时遮挡、3D重建、工业检测一文详解 想象一下,你手里只有一部普通的手机摄像头,却想让它像人眼一样“感知”距离,知道哪个物体离你近,哪个离你远。或者,你有…...

GLM-OCR GPU算力优化实践:vLLM推理加速+令牌下采样,吞吐提升2.3倍

GLM-OCR GPU算力优化实践:vLLM推理加速令牌下采样,吞吐提升2.3倍 1. 项目背景与优化需求 GLM-OCR是一个基于GLM-V编码器-解码器架构构建的多模态OCR模型,专门为复杂文档理解而设计。这个模型集成了在大规模图文数据上预训练的CogViT视觉编码…...

Qwen3.5-9B-AWQ-4bit部署教程:双卡RTX 4090 D显存优化与AWQ量化优势解析

Qwen3.5-9B-AWQ-4bit部署教程:双卡RTX 4090 D显存优化与AWQ量化优势解析 1. 模型概述 Qwen3.5-9B-AWQ-4bit是一个支持图像理解的多模态模型,能够结合上传图片与文字提示词,输出中文分析结果。这个模型特别适合处理以下任务: 图…...

丹青幻境效果对比:Z-Image底座 vs SDXL在人物结构准确率与衣纹表现力评测

丹青幻境效果对比:Z-Image底座 vs SDXL在人物结构准确率与衣纹表现力评测 1. 评测背景与意义 在数字艺术创作领域,人物结构准确性和衣纹表现力一直是衡量AI绘画模型质量的关键指标。本次评测聚焦于丹青幻境采用的Z-Image底座与业界知名的SDXL模型&…...

Nunchaku FLUX.1-dev部署教程:Linux系统下CUDA驱动与PyTorch匹配指南

Nunchaku FLUX.1-dev部署教程:Linux系统下CUDA驱动与PyTorch匹配指南 想用最新的Nunchaku FLUX.1-dev模型生成惊艳的AI图片,结果卡在了环境配置上?别担心,这篇教程就是为你准备的。很多朋友在部署时遇到的最大障碍,往…...

RVC与ElevenLabs对比:开源可控性vs商业易用性深度分析

RVC与ElevenLabs对比:开源可控性vs商业易用性深度分析 想用AI克隆自己的声音,或者让喜欢的角色开口唱歌?现在市面上有两大主流选择:开源的RVC和商业化的ElevenLabs。一个免费但需要折腾,一个付费但开箱即用。到底哪个…...

千问3.5-27B效果实测:低质量扫描件文字区域检测与内容还原

千问3.5-27B效果实测:低质量扫描件文字区域检测与内容还原 1. 模型介绍 Qwen3.5-27B是Qwen官方发布的视觉多模态理解模型,具备强大的文本对话与图片理解能力。本镜像已在4张RTX 4090 D 24GB显卡环境下完成部署,提供中文Web对话界面、流式文…...

WuliArt Qwen-Image Turbo高清图展示:1024×1024下4K显示器100%缩放无模糊

WuliArt Qwen-Image Turbo高清图展示:10241024下4K显示器100%缩放无模糊 提示:本文所有展示图片均为WuliArt Qwen-Image Turbo模型直接生成,未经任何后期处理 1. 项目概述:重新定义个人GPU文生图体验 WuliArt Qwen-Image Turbo是…...

OpenClaw任务链设计:千问3.5-35B-A3B-FP8复杂流程自动化

OpenClaw任务链设计:千问3.5-35B-A3B-FP8复杂流程自动化 1. 为什么需要任务链自动化 上周我遇到一个典型的工作场景:需要从20份PDF报告中提取关键数据,整理成Excel表格,再根据这些数据生成分析图表,最后通过邮件发送…...

C++编程中new与delete操作符的深度解析

C编程中new与delete操作符的深度解析 在C编程的广阔天地里,内存管理是一个既基础又至关重要的环节。对于每一位C开发者而言,掌握内存的动态分配与释放是构建高效、稳定应用程序的基石。在众多内存管理工具中,new与delete操作符无疑是最为核心…...

C++编程中堆与栈内存的差异解析

C编程中堆与栈内存的差异解析 在C编程的世界里,内存管理是一个核心且至关重要的概念。其中,堆(Heap)与栈(Stack)作为两种主要的内存分配区域,各自扮演着不同的角色,理解它们之间的区…...

C++编程进阶:探索内建数学函数与C++20的<numbers>头文件

C编程进阶:探索内建数学函数与C20的头文件 在C编程的世界里,数学运算无处不在,无论是游戏开发中的物理模拟、图形处理,还是数据分析中的复杂计算,数学函数都是不可或缺的工具。随着C标准的不断演进,C20引入…...

OpenClaw模型微调集成:Qwen3-14b_int4_awq领域适配实战

OpenClaw模型微调集成:Qwen3-14b_int4_awq领域适配实战 1. 为什么需要领域专用模型 去年我在处理法律合同自动化生成项目时,发现通用大模型在专业术语和条款逻辑上总是差强人意。模型要么生成过于笼统的表述,要么在引用法律条文时出现事实性…...

阶跃星辰(Step):前微软小冰之父的 AI 豪赌

阶跃星辰(Step):前微软小冰之父的 AI 豪赌 一句话概括:阶跃星辰(StepFun)是由微软小冰前负责人姜大鑫创立的 AI 公司,其 Step-2 大模型达到万亿参数级别,是国内少数真正挑战顶级闭源…...

Nature Microbiology|质粒驱动的抗菌素耐药性进化:插入序列介导的基因失活新机制

背景 抗菌素耐药性(AMR)是全球公共卫生面临的严峻挑战。细菌进化出耐药性的主要途径包括基因突变和通过水平基因转移(Horizontal Gene Transfer, HGT)获得外源耐药基因。在后者中,接合质粒扮演了核心角色,它…...

DeepSeek LeetCode 1125.最小的必要团队 public int[] smallestSufficientTeam(String[] req_skills, List<List

这是 LeetCode 1125 “最小的必要团队”问题。要求从候选人中选择一个最小的团队,使得团队成员的技能集合覆盖所有必需的技能。问题理解 有一个技能需求列表 req_skills,如 ["java", "python", "cpp"]有 people 列表&…...

InfluxDB(一)——一个高效处理数据的时序数据库

目录 一、什么是时序数据库InfluxDB? 关系型数据库(行式存储)是怎么存的? 时序数据库(列式存储)是怎么存的? 二、InfluxDB的特点 1. 极致的写入性能 2. 高效的存储压缩 3. 独特的数据模型…...

DeepSeek LintCode 3706 · 满足条件的数对的数量 public long countValidPairs(int[] nums1, int[] nums2, int dif

这个问题是 LintCode 3706 “满足条件的数对的数量”&#xff0c;要求统计满足 nums1[i] - nums1[j] < nums2[i] - nums2[j] diff&#xff08;其中 i < j&#xff09;的数对 (i, j) 的数量。 问题理解 给定两个数组 nums1 和 nums2&#xff0c;以及一个整数 diff&#…...

光伏混合储能直流微电网simulink模型 1.直流微电网由锂电池,超级电容,光伏和直流负载组成 2

光伏混合储能直流微电网simulink模型 1.直流微电网由锂电池&#xff0c;超级电容&#xff0c;光伏和直流负载组成 2.光伏采用电导增量法实现最大功率输出 3.锂电池和超级电容采用直流母线电压控制策略&#xff0c;根据直流母线电压高低实现充放电 实现以下目标&#xff1a; 1.光…...

OpenClaw省钱全攻略,掌握这5招,每月少花几百块冤枉钱

手把手教你一键部署OpenClaw&#xff0c;连接微信、QQ、飞书、钉钉等&#xff0c;1分钟全搞定&#xff01; 刚把OpenClaw折腾好&#xff0c;你可能正沉浸在AI秒回代码、自动理任务的神奇体验里&#xff0c;心里直呼过瘾。可还没等新鲜劲过去&#xff0c;一翻后台账单&#xff…...

别只盯着 Claw 了,这波“真香”技能才是真的生产力神器!

手把手教你一键部署OpenClaw&#xff0c;连接微信、QQ、飞书、钉钉等&#xff0c;1分钟全搞定&#xff01; 说白了&#xff0c;各家大厂出的 Claw 产品&#xff0c;核心逻辑就是“AI 大模型 技能插件”。模型是地基&#xff0c;而你用得爽不爽&#xff0c;全看这些技能给不给…...

深夜调车的时候突然发现,Apollo的泊车轨迹优化藏着不少“骚操作“。咱们今天不聊虚的,直接扒开代码看三个核心模块怎么打架...哦不,怎么配合的

apollo 泊车轨迹优化代码 hybridastariaps平滑优化obca平滑优化 第一个图是matlab绘制 后面的图是程序用sdl库绘制先看Hybrid A*这个愣头青。这货生成的轨迹就像刚拿驾照的新手&#xff0c;能避开障碍物但轨迹拧巴得很。看看它扩展节点的代码片段&#xff1a; Node3D* expand(…...

Ruby开发工具JetBrains RubyMine

链接&#xff1a;https://pan.quark.cn/s/6d78ff88b12eJetBrains RubyMine是一个全新的为Ruby 和 Rails开发者准备的代码编辑器 &#xff0c;对于Ruby这种比较新兴的编程语言&#xff0c;如果你是Ruby的爱好者&#xff0c;不妨试试使用它作为你的开发工具。软件是建立在IntellJ…...

Python面向对象:封装、继承、多态

作为Python面向对象编程&#xff08;OOP&#xff09;的三大核心特性&#xff0c;封装、继承、多态是从编程新手进阶到熟练开发者的必备知识。它们不是晦涩的理论&#xff0c;而是能让代码更简洁、复用性更强、扩展性更好的实用工具。 一、什么是面向对象&#xff1f; 在讲三大特…...

COMSOL锂枝晶生长仿真模拟:四场耦合(化学场、浓度场、电场、应力场)

comsol锂枝晶生长仿真模拟-应力耦合。 化学场、浓度场、电场、应力场&#xff0c;四场耦合模拟锂枝晶的生长。锂金属负极在固态电池中总爱搞事情&#xff0c;枝晶刺穿隔膜的戏码天天上演。实验室里做破坏性测试成本太高&#xff0c;数值仿真就成了预判枝晶生长路径的透视眼。CO…...

SecGPT-14B+OpenClaw联调指南:解决模型响应超时问题

SecGPT-14BOpenClaw联调指南&#xff1a;解决模型响应超时问题 1. 问题背景与场景定位 上周在尝试用OpenClaw调用SecGPT-14B分析一份12万字的网络安全报告时&#xff0c;遭遇了令人头疼的响应超时问题。这个场景很典型——当我们需要处理长文本安全分析时&#xff0c;模型推理…...

【Pygame】第15章 游戏人工智能基础、行为控制与寻路算法实现

摘要 人工智能是游戏开发中的重要组成部分&#xff0c;它能够赋予非玩家角色更自然的行为表现&#xff0c;使游戏世界显得更加真实、生动&#xff0c;并且具有挑战性。 在 2D 游戏中&#xff0c;AI 通常并不追求真正意义上的“智能”&#xff0c;而是通过一系列规则、状态和算…...