<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>会走路的三百块</title>
        <link>http://ooowl.fun/</link>
        <description>生命不息，代码不止</description>
        <lastBuildDate>Mon, 25 May 2026 16:58:05 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>zh-CN</language>
        <copyright>Copyright 2026</copyright>
        <atom:link href="http://ooowl.fun/feed.xml" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[CICD]]></title>
            <link>http://ooowl.fun/blogs/Web%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/%E6%B5%8B%E8%AF%95%E8%BF%90%E7%BB%B4/CICD.html</link>
            <guid isPermaLink="false">http://ooowl.fun/blogs/Web%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/%E6%B5%8B%E8%AF%95%E8%BF%90%E7%BB%B4/CICD.html</guid>
            <pubDate>Wed, 21 Jan 2026 23:16:55 GMT</pubDate>
            <content:encoded><![CDATA[<h1 id="cicd" tabindex="-1">CICD <a class="header-anchor" href="#cicd" aria-label="Permalink to &quot;CICD&quot;">&ZeroWidthSpace;</a></h1><p class="article-meta">创建于 2026年1月22日 07:16:55 · 约253字</p>
<p>只做业务要用到的最简单的CICD。<br>
基于LLM话疗和规模调研，最终选择的是 release分支-&gt;Drone自动打包-&gt;推送k3s。<br>
选型比较：</p>
<ul>
<li>github runner也是个不错的选择，但是这样镜像就得走一遍网络，而且会随着github的政策变化。</li>
<li>gitea runner也不错，出来的时间比较短，而且自定义程度不如drone。</li>
<li>jekins是行业标准但是java比较亲和，配置复杂度高了不止一点。<br>
Drone有大公司背书，活的时间也比较久，star多资料多，资源占用少，纯docker runner好限制和调整，带UI界面也是写yaml配置简单，适合我们小团队及格的使用。<br>
内部工具没那么严格，崩了大不了晚点上线。目前能考虑到的地方就是如果打包出错了，pod版本不一致，怎么做保证原子性。</li>
</ul>
<p>原因：Submariner 默认仅支持导出 ClusterIP 类型的服务（或者 headless service）</p>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[K3S]]></title>
            <link>http://ooowl.fun/blogs/Web%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/%E5%AE%B9%E5%99%A8%E6%8A%80%E6%9C%AF/K3S.html</link>
            <guid isPermaLink="false">http://ooowl.fun/blogs/Web%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/%E5%AE%B9%E5%99%A8%E6%8A%80%E6%9C%AF/K3S.html</guid>
            <pubDate>Wed, 21 Jan 2026 23:09:01 GMT</pubDate>
            <content:encoded><![CDATA[<h1 id="k3s" tabindex="-1">K3S <a class="header-anchor" href="#k3s" aria-label="Permalink to &quot;K3S&quot;">&ZeroWidthSpace;</a></h1><p class="article-meta">创建于 2026年1月22日 07:09:01 · 约187字</p>
<p>没有太多时间去细细学特性，速通一下赶紧用起来。<a href="https://www.geekhour.net/2023/12/23/kubernetes/" target="_blank" rel="noreferrer">K8s一小时入门笔记 GeekHour</a><br/><a href="https://www.bilibili.com/video/BV1Se411r7vY/" target="_blank" rel="noreferrer">Kubernetes一小时轻松入门_哔哩哔哩_bilibili</a><br>
整个k8s运维消耗太大，使用<a href="https://k3s.io/" target="_blank" rel="noreferrer">K3s</a>在1000个节点内应该完全不是问题，而且也是有大公司使用过背书。兼容性和后续移植性非常好，跟着 <a href="http://docs.kubernetes.org.cn/" target="_blank" rel="noreferrer">Kubernetes(K8S)中文文档 Kubernetes中文社区</a>学就可以。<br>
现在有AI了，笔记只提纲挈领的帮助回忆结构。<br>
<a href="https://space.bilibili.com/49560624/lists/5905692" target="_blank" rel="noreferrer">程序员Rocky的个人空间-程序员Rocky个人主页-哔哩哔哩视频</a><br/>
<a href="https://github.com/dream-mo/bilibili-systematic-k8s" target="_blank" rel="noreferrer">GitHub - dream-mo/bilibili-systematic-k8s: B站: 程序员Rocky B站最清晰讲解,全面体系化掌握K8S课程</a></p>
<p><a href="https://helm.sh/zh/docs/intro/install" target="_blank" rel="noreferrer">Installing Helm</a>
<a href="https://artifacthub.io/" target="_blank" rel="noreferrer">Artifact Hub | Helm Source</a></p>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Sqlite]]></title>
            <link>http://ooowl.fun/blogs/Web%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/%E5%AD%98%E5%82%A8%E6%8A%80%E6%9C%AF/Sqlite.html</link>
            <guid isPermaLink="false">http://ooowl.fun/blogs/Web%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/%E5%AD%98%E5%82%A8%E6%8A%80%E6%9C%AF/Sqlite.html</guid>
            <pubDate>Tue, 14 Oct 2025 11:28:08 GMT</pubDate>
            <content:encoded><![CDATA[<h1 id="sqlite" tabindex="-1">Sqlite <a class="header-anchor" href="#sqlite" aria-label="Permalink to &quot;Sqlite&quot;">&ZeroWidthSpace;</a></h1><p class="article-meta">创建于 2025年10月14日 19:28:08 · 约3字</p>
<p><a href="https://sqlite.org/" target="_blank" rel="noreferrer">SQLite Home Page</a></p>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Rustfs对象存储]]></title>
            <link>http://ooowl.fun/blogs/Web%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/%E9%98%9F%E5%88%97%E5%92%8C%E5%AF%B9%E8%B1%A1%E5%AD%98%E5%82%A8/Rustfs%E5%AF%B9%E8%B1%A1%E5%AD%98%E5%82%A8.html</link>
            <guid isPermaLink="false">http://ooowl.fun/blogs/Web%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/%E9%98%9F%E5%88%97%E5%92%8C%E5%AF%B9%E8%B1%A1%E5%AD%98%E5%82%A8/Rustfs%E5%AF%B9%E8%B1%A1%E5%AD%98%E5%82%A8.html</guid>
            <pubDate>Tue, 16 Sep 2025 11:26:14 GMT</pubDate>
            <content:encoded><![CDATA[<h1 id="rustfs对象存储" tabindex="-1">Rustfs对象存储 <a class="header-anchor" href="#rustfs对象存储" aria-label="Permalink to &quot;Rustfs对象存储&quot;">&ZeroWidthSpace;</a></h1><p class="article-meta">创建于 2025年9月16日 19:26:14 · 约22字</p>
<p>MINIO要钱，更新完了控制台改桶权限都不能用了，遂换之。</p>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Caddy]]></title>
            <link>http://ooowl.fun/blogs/Web%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/%E7%BD%91%E5%85%B3/Caddy.html</link>
            <guid isPermaLink="false">http://ooowl.fun/blogs/Web%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/%E7%BD%91%E5%85%B3/Caddy.html</guid>
            <pubDate>Sun, 14 Sep 2025 11:47:00 GMT</pubDate>
            <content:encoded><![CDATA[<h1 id="caddy" tabindex="-1">Caddy <a class="header-anchor" href="#caddy" aria-label="Permalink to &quot;Caddy&quot;">&ZeroWidthSpace;</a></h1><p class="article-meta">创建于 2025年9月14日 19:47:00 · 约43字</p>
<p>项目github在<a href="https://github.com/caddyserver/caddy/" target="_blank" rel="noreferrer">这里</a>，非常的轻量级，适合本地玩中等的流量也扛得住，release不依赖go环境。<br>
代理一个本地单文件夹。</p>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">8000</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> #监听本地0.0.0.0:8000</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">root </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> .</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">/</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">tao </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 这个文件夹作为网页根目录</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">file_server</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#等价命令  caddy file-server --root ./tao  --listen :8000</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">try_files {path} </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">/</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">index.html </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 遇到 404 时重写为首页</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br></div></div>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Unity-经典MMO]]></title>
            <link>http://ooowl.fun/blogs/Game/Unity/Unity-%E7%BB%8F%E5%85%B8MMO.html</link>
            <guid isPermaLink="false">http://ooowl.fun/blogs/Game/Unity/Unity-%E7%BB%8F%E5%85%B8MMO.html</guid>
            <pubDate>Sat, 13 Sep 2025 23:30:33 GMT</pubDate>
            <content:encoded><![CDATA[<h1 id="unity-经典mmo" tabindex="-1">Unity-经典MMO <a class="header-anchor" href="#unity-经典mmo" aria-label="Permalink to &quot;Unity-经典MMO&quot;">&ZeroWidthSpace;</a></h1><p class="article-meta">创建于 2025年9月14日 07:30:33 · 约0字</p>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Unity-个人Demo]]></title>
            <link>http://ooowl.fun/blogs/Game/Unity/Unity-%E4%B8%AA%E4%BA%BADemo.html</link>
            <guid isPermaLink="false">http://ooowl.fun/blogs/Game/Unity/Unity-%E4%B8%AA%E4%BA%BADemo.html</guid>
            <pubDate>Sat, 13 Sep 2025 23:29:29 GMT</pubDate>
            <content:encoded><![CDATA[<h1 id="unity-个人demo" tabindex="-1">Unity-个人Demo <a class="header-anchor" href="#unity-个人demo" aria-label="Permalink to &quot;Unity-个人Demo&quot;">&ZeroWidthSpace;</a></h1><p class="article-meta">创建于 2025年9月14日 07:29:29 · 约48字</p>
<p>unitask场景异步Loading带进度条
无限背包列表
新手引导动态AI遮罩
排行榜滚动TopN
Spine换装
unitask+dotween流畅的异步动画
Timeline转场动画</p>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Unity-天命6源码]]></title>
            <link>http://ooowl.fun/blogs/Game/Unity/Unity-%E5%A4%A9%E5%91%BD6%E6%BA%90%E7%A0%81.html</link>
            <guid isPermaLink="false">http://ooowl.fun/blogs/Game/Unity/Unity-%E5%A4%A9%E5%91%BD6%E6%BA%90%E7%A0%81.html</guid>
            <pubDate>Sat, 13 Sep 2025 23:28:56 GMT</pubDate>
            <content:encoded><![CDATA[<h1 id="unity-天命6源码" tabindex="-1">Unity-天命6源码 <a class="header-anchor" href="#unity-天命6源码" aria-label="Permalink to &quot;Unity-天命6源码&quot;">&ZeroWidthSpace;</a></h1><p class="article-meta">创建于 2025年9月14日 07:28:56 · 约502字</p>
<p>求职用的，主要扒游戏管理和UI部分。想要可以找我要，我有翻译韩语完的。<br>
游戏中最好不要使用魔法值，所有的值都应该用常量定义出来，放到Scripts/GameDefine下面。<br>
游戏从Logo场景开始，一个简单的动画控制，播放对应商店的Logo Sprite，Logo播放完毕的时候加载Certification场景。</p>
<p>这个系统的UI用的是NGUI，每个面板用不同的摄像机然后叠加culling。把组件都挂到Animation下面，便于控制动画和效果</p>
<p>从Logo场景进入，Logo场景很简单，就是一个logo，判断了一个莫名其妙的宏，加载动画，然后进入Certification场景</p>
<p>Certification场景目前来的功能是验证AB包+验证身份登录（？
UI部分重要的结构</p>
<div class="language-C vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">C</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">UStartPackage_Launcher: UStartPackage</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Certification下</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">加载脚本的顺序是:</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> UStartPackage_Launcher : UStartPackage</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    -</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> 这里面塞了三个全局prefab管理器</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        -</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> GlobalFontManager 字体</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        -</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> BGM Module 背景音乐</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        -</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> UI Root Dialog 全局的UI提示弹窗</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">     -</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> 单例触发ULocalPlayer</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> ULoginCtrl</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> ULauncherCtrl</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> 表驱动</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> 网络</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> 搞定两个UI</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br></div></div><p>UStartPackage
设置UI缩放和分辨率，读取预制体，加载三个模块的预制体，中间重置本地客户端的旧数据
如果PlayerPrefs中没有保存数据，则从旧文件中读取信息并保存到PlayerPrefs（我好像没怎么弄懂这东西的数据持久化是怎么管理的
Lancher完事了</p>
<p>ULocalPlayer 是“全局玩家与系统服务的聚合单例”，涵盖资源、网络、设置、前后台行为等。没有全看完，<code>ULocalPlayer.Instance.LocalPushMgr.CancelLocalPush();</code>里面包含了一个服务通知推送管理模块，底层推送使用的是NMSDK
聚合单例使用partial关键字分段编写，降低合作编写难度和耦合。
LobbyMenuData是大厅(战斗外)的核心数据单例，战斗时的核心数据单例使用的是另一个上下文。</p>
<p>此时已经初始化好了UI缩放适配，音乐，游戏设置，AB包的资源，全局字体管理器。</p>
<p>接下来使用的是，ULoginCtrl，</p>
<p>仅针对非战斗部分
首先是基础架构和业务使用分开
基础架构看
网络
数据</p>
<p>跨场景管理</p>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[基本前端常识]]></title>
            <link>http://ooowl.fun/blogs/Web%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/%E4%BA%A7%E5%93%81%E9%97%AD%E7%8E%AF/%E5%9F%BA%E6%9C%AC%E5%89%8D%E7%AB%AF%E5%B8%B8%E8%AF%86.html</link>
            <guid isPermaLink="false">http://ooowl.fun/blogs/Web%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/%E4%BA%A7%E5%93%81%E9%97%AD%E7%8E%AF/%E5%9F%BA%E6%9C%AC%E5%89%8D%E7%AB%AF%E5%B8%B8%E8%AF%86.html</guid>
            <pubDate>Wed, 06 Aug 2025 23:52:54 GMT</pubDate>
            <content:encoded><![CDATA[<h1 id="基本前端常识" tabindex="-1">基本前端常识 <a class="header-anchor" href="#基本前端常识" aria-label="Permalink to &quot;基本前端常识&quot;">&ZeroWidthSpace;</a></h1><p class="article-meta">创建于 2025年8月7日 07:52:54 · 约13字</p>
<p>#todo h</p>
<h2 id="快速的前端基础" tabindex="-1">快速的前端基础 <a class="header-anchor" href="#快速的前端基础" aria-label="Permalink to &quot;快速的前端基础&quot;">&ZeroWidthSpace;</a></h2>
<h2 id="平台区分" tabindex="-1">平台区分 <a class="header-anchor" href="#平台区分" aria-label="Permalink to &quot;平台区分&quot;">&ZeroWidthSpace;</a></h2>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[文档分发与产品安全]]></title>
            <link>http://ooowl.fun/blogs/Web%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/%E4%BA%A7%E5%93%81%E9%97%AD%E7%8E%AF/%E6%96%87%E6%A1%A3%E5%88%86%E5%8F%91%E4%B8%8E%E5%AE%89%E5%85%A8.html</link>
            <guid isPermaLink="false">http://ooowl.fun/blogs/Web%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/%E4%BA%A7%E5%93%81%E9%97%AD%E7%8E%AF/%E6%96%87%E6%A1%A3%E5%88%86%E5%8F%91%E4%B8%8E%E5%AE%89%E5%85%A8.html</guid>
            <pubDate>Wed, 06 Aug 2025 23:52:54 GMT</pubDate>
            <content:encoded><![CDATA[<h1 id="文档分发与产品安全" tabindex="-1">文档分发与产品安全 <a class="header-anchor" href="#文档分发与产品安全" aria-label="Permalink to &quot;文档分发与产品安全&quot;">&ZeroWidthSpace;</a></h1><p class="article-meta">创建于 2025年8月7日 07:52:54 · 约18字</p>
<p>#todo hhh</p>
<h2 id="安全" tabindex="-1">安全 <a class="header-anchor" href="#安全" aria-label="Permalink to &quot;安全&quot;">&ZeroWidthSpace;</a></h2>
<h2 id="文档" tabindex="-1">文档 <a class="header-anchor" href="#文档" aria-label="Permalink to &quot;文档&quot;">&ZeroWidthSpace;</a></h2>
<h2 id="分发" tabindex="-1">分发 <a class="header-anchor" href="#分发" aria-label="Permalink to &quot;分发&quot;">&ZeroWidthSpace;</a></h2>
<h2 id="运维" tabindex="-1">运维 <a class="header-anchor" href="#运维" aria-label="Permalink to &quot;运维&quot;">&ZeroWidthSpace;</a></h2>
<h2 id="运营资质" tabindex="-1">运营资质 <a class="header-anchor" href="#运营资质" aria-label="Permalink to &quot;运营资质&quot;">&ZeroWidthSpace;</a></h2>
<p>备案
收钱</p>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[跨平台应用脚手架]]></title>
            <link>http://ooowl.fun/blogs/Web%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/%E4%BA%A7%E5%93%81%E9%97%AD%E7%8E%AF/%E8%B7%A8%E5%B9%B3%E5%8F%B0%E5%BA%94%E7%94%A8%E8%84%9A%E6%89%8B%E6%9E%B6.html</link>
            <guid isPermaLink="false">http://ooowl.fun/blogs/Web%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/%E4%BA%A7%E5%93%81%E9%97%AD%E7%8E%AF/%E8%B7%A8%E5%B9%B3%E5%8F%B0%E5%BA%94%E7%94%A8%E8%84%9A%E6%89%8B%E6%9E%B6.html</guid>
            <pubDate>Wed, 06 Aug 2025 23:52:54 GMT</pubDate>
            <content:encoded><![CDATA[<h1 id="跨平台应用脚手架" tabindex="-1">跨平台应用脚手架 <a class="header-anchor" href="#跨平台应用脚手架" aria-label="Permalink to &quot;跨平台应用脚手架&quot;">&ZeroWidthSpace;</a></h1><p class="article-meta">创建于 2025年8月7日 07:52:54 · 约31字</p>
<p>#todo hh</p>
<h2 id="目标" tabindex="-1">目标 <a class="header-anchor" href="#目标" aria-label="Permalink to &quot;目标&quot;">&ZeroWidthSpace;</a></h2>
<h2 id="技术选型" tabindex="-1">技术选型 <a class="header-anchor" href="#技术选型" aria-label="Permalink to &quot;技术选型&quot;">&ZeroWidthSpace;</a></h2>
<h3 id="轻量级后端" tabindex="-1">轻量级后端 <a class="header-anchor" href="#轻量级后端" aria-label="Permalink to &quot;轻量级后端&quot;">&ZeroWidthSpace;</a></h3>
<h3 id="独立web" tabindex="-1">独立web <a class="header-anchor" href="#独立web" aria-label="Permalink to &quot;独立web&quot;">&ZeroWidthSpace;</a></h3>
<h2 id="构建跨平台应用" tabindex="-1">构建跨平台应用 <a class="header-anchor" href="#构建跨平台应用" aria-label="Permalink to &quot;构建跨平台应用&quot;">&ZeroWidthSpace;</a></h2>
<h2 id="平台权限" tabindex="-1">平台权限 <a class="header-anchor" href="#平台权限" aria-label="Permalink to &quot;平台权限&quot;">&ZeroWidthSpace;</a></h2>
<h2 id="工作范式" tabindex="-1">工作范式 <a class="header-anchor" href="#工作范式" aria-label="Permalink to &quot;工作范式&quot;">&ZeroWidthSpace;</a></h2>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Games101]]></title>
            <link>http://ooowl.fun/blogs/Game/Games%E7%B3%BB%E5%88%97/Games101.html</link>
            <guid isPermaLink="false">http://ooowl.fun/blogs/Game/Games%E7%B3%BB%E5%88%97/Games101.html</guid>
            <pubDate>Mon, 14 Apr 2025 11:27:12 GMT</pubDate>
            <content:encoded><![CDATA[<h1 id="games101" tabindex="-1">Games101 <a class="header-anchor" href="#games101" aria-label="Permalink to &quot;Games101&quot;">&ZeroWidthSpace;</a></h1><p class="article-meta">创建于 2025年4月14日 19:27:12 · 约94字</p>
<h2 id="基本资料" tabindex="-1">基本资料 <a class="header-anchor" href="#基本资料" aria-label="Permalink to &quot;基本资料&quot;">&ZeroWidthSpace;</a></h2>
<ul>
<li>原课程链接<a href="https://sites.cs.ucsb.edu/~lingqi/teaching/games101.html" target="_blank" rel="noreferrer">GAMES101: 现代计算机图形学入门</a></li>
<li><a href="https://www.bilibili.com/video/BV1X7411F744/" target="_blank" rel="noreferrer">GAMES101-bilibili</a></li>
<li>手写一个简单的渲染器<a href="https://github.com/ssloy/tinyrenderer" target="_blank" rel="noreferrer">GitHub - ssloy/tinyrenderer: A brief computer graphics / rendering course</a></li>
<li><a href="https://games-cn.org/forums/" target="_blank" rel="noreferrer">Title Unavailable | Site Unreachable</a></li>
<li>虎书第五版
约翰卡马克
<a href="https://zh.wikipedia.org/wiki/%E5%B9%B3%E6%96%B9%E6%A0%B9%E5%80%92%E6%95%B0%E9%80%9F%E7%AE%97%E6%B3%95" target="_blank" rel="noreferrer">平方根倒数速算法 - 维基百科，自由的百科全书</a></li>
</ul>
<h2 id="todo" tabindex="-1">todo <a class="header-anchor" href="#todo" aria-label="Permalink to &quot;todo&quot;">&ZeroWidthSpace;</a></h2>
<p>以后再说</p>
<h2 id="图形学常见算法" tabindex="-1">图形学常见算法 <a class="header-anchor" href="#图形学常见算法" aria-label="Permalink to &quot;图形学常见算法&quot;">&ZeroWidthSpace;</a></h2>
<h3 id="画家算法" tabindex="-1">画家算法 <a class="header-anchor" href="#画家算法" aria-label="Permalink to &quot;画家算法&quot;">&ZeroWidthSpace;</a></h3>
<h3 id="柏林噪声" tabindex="-1">柏林噪声 <a class="header-anchor" href="#柏林噪声" aria-label="Permalink to &quot;柏林噪声&quot;">&ZeroWidthSpace;</a></h3>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[订单和支付模块]]></title>
            <link>http://ooowl.fun/blogs/Web%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/%E9%80%9A%E7%94%A8%E6%A8%A1%E5%9D%97/%E8%AE%A2%E5%8D%95%E5%92%8C%E6%94%AF%E4%BB%98%E6%A8%A1%E5%9D%97.html</link>
            <guid isPermaLink="false">http://ooowl.fun/blogs/Web%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/%E9%80%9A%E7%94%A8%E6%A8%A1%E5%9D%97/%E8%AE%A2%E5%8D%95%E5%92%8C%E6%94%AF%E4%BB%98%E6%A8%A1%E5%9D%97.html</guid>
            <pubDate>Thu, 13 Mar 2025 14:18:32 GMT</pubDate>
            <content:encoded><![CDATA[<h1 id="订单和支付模块" tabindex="-1">订单和支付模块 <a class="header-anchor" href="#订单和支付模块" aria-label="Permalink to &quot;订单和支付模块&quot;">&ZeroWidthSpace;</a></h1><p class="article-meta">创建于 2025年3月13日 22:18:32 · 约80字</p>
<p>订单的主要状态
创建</p>
<ul>
<li>可能创建了之后还要拿着订单号做一些事情
支付中</li>
<li>拉起支付了</li>
<li>可以记录拉起次数
支付成功</li>
<li>由tx回调完成状态转换
退款</li>
<li>单独</li>
<li></li>
</ul>
<p>支付对接细节
他们有时候会改
微信
支付宝</p>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Unity-Lua补充]]></title>
            <link>http://ooowl.fun/blogs/Game/Unity/Unity-Lua%E8%A1%A5%E5%85%85.html</link>
            <guid isPermaLink="false">http://ooowl.fun/blogs/Game/Unity/Unity-Lua%E8%A1%A5%E5%85%85.html</guid>
            <pubDate>Tue, 04 Mar 2025 09:41:22 GMT</pubDate>
            <content:encoded><![CDATA[<h1 id="unity-lua补充" tabindex="-1">Unity-Lua补充 <a class="header-anchor" href="#unity-lua补充" aria-label="Permalink to &quot;Unity-Lua补充&quot;">&ZeroWidthSpace;</a></h1><p class="article-meta">创建于 2025年3月4日 17:41:22 · 约2,399字</p>
<h2 id="反直觉常识" tabindex="-1">反直觉常识 <a class="header-anchor" href="#反直觉常识" aria-label="Permalink to &quot;反直觉常识&quot;">&ZeroWidthSpace;</a></h2>
<p>安装不多说去看文档。在IDEA中使用<code>emmylua</code>插件支持lua（settings-&gt;Editor-&gt;FileType-&gt;luaLanguage虽然里面已经添加了一个<code>*.lua.txt</code>但是不管用再加一个一模一样的就管用了）<br>
安装</p>
<p>在文件开头加入<code>#!/usr/local/bin/lua</code>就可以像执行shell一样去执行lua<br>
动态，弱类型语言, 在默认情况下，变量总是认为是全局的。全局变量不需要声明，哪怕是语句块或是函数里，除非用local 显式声明局部变量，否则全是全局的。<br>
<strong>在实践中，建议给所有变量加上local，除非你确认一定需要全局变量</strong>。不加local所造成的奇怪bug会让你终身难忘，而且local更会快<br>
给一个变量赋值后即创建了这个全局变量，访问一个没有初始化的全局变量也不会出错，只不过得到的结果是：<code>nil</code>如果想删除一个全局变量，只需要将变量赋值为<code>nil</code><br>
<strong>只有nil和false是假；0也是真</strong><br>
从1开始的下标（？从其他语言取的时候一定要注意
<strong>一般约定，以下划线开头连接遗传大写字母的名字（比如 <code>_VERSION</code>）是Lua内部全局变量的保留字</strong><br>
本身有JIT速度还可以，和其他语言交互比较慢。<br>
lua语法老严格了，最好按照强迫症风格来写，lua是纯解释，被调用的必须要比调用者先声明。
Lua是运行在一个单线程虚拟机上运行所以只有单线程</p>
<h2 id="奇怪的语法" tabindex="-1">奇怪的语法 <a class="header-anchor" href="#奇怪的语法" aria-label="Permalink to &quot;奇怪的语法&quot;">&ZeroWidthSpace;</a></h2>
<p>userdata是和其他语言交互的核心，存储任意C的数据结构；table看你存什么，它相当于把数组和字典混合了起来，底层用哈希表还是顺序表看心情（看你存啥他自己转换<br>
对字符串进行算数操作，Lua会尝试类型转换为数字然后操作，转不了就报错（？</p>
<div class="language-lua vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">lua</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">a,b,c</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> -- 1,nil,nil 多的就nil</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">a</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">3</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> -- 1 少了就扔</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">type</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(x)</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">==</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">nil</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> -- false 因为返回的是"nil"</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">type</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(x)</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">==</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"nil" </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">-- 这回对了</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">x</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">~=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">nil</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  -- 不等于也很奇葩</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"2" </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 6</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">8.0</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> -- 神奇.</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">6</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> ..</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 8</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">68</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> -- 注意返回的是数字 用 .. 的时候必须要有空格</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br></div></div><ul>
<li><code>t.i</code>和<code>t[i]</code>本质都是函数调用，类似于getattr</li>
<li>table的自然数索引部分会自己扩容一半按2的倍数扩，hash部分每次重哈希消耗比较大
<ul>
<li>array部分和其他语言一样，统计多少，然后扩容+memcpy，<strong>但是即使是数组扩容也会把旧表的hash部分重新计算</strong>，它有一个重新分配元素是整数索引还是hash索引的过程</li>
<li>hash部分和array内存中是分开管理的，只有设置metatable的<code>__eq</code>或超过阈值才会触发rehash，hash会重新计算一遍key插入新表</li>
<li>表在存储的时候连续自然数是放在array部分的，负数，<code>[1, t-&gt;asize]</code>外的数都会被存放在hash部分，rehash的时候会重新计算是不是放入array部分合适</li>
<li>建议使用的时候如果知道大小就提前初始化<code>t={nil,nil,nil}</code>，如果过于稀疏了array部分甚至会收缩</li>
</ul>
</li>
<li>table遍历是按照key的hash来的而不是顺序。</li>
<li>table的名称引用之间赋值也是浅拷贝</li>
<li>使用ipairs只会顺着自然数统计数量，截断就停止，使用#和getn也是统计到自然数截断就停止</li>
<li>获取表真的有多少那就老老实实<code>for k,v in pairs(t) do</code>统计（有点笨</li>
<li>当k被删除的时候如果k被table引用作为key是不会被GC的，只是引用没了此时为强引用
<ul>
<li>给table设置<code>__mode=&quot;k&quot;</code>此时如果key被删除了，那么table也会移除这个k-v</li>
<li>有三种模式，k，v，kv看字面意思就懂</li>
<li>当我把key的引用删除本质上是table在检测这个值是不是只有在此table中是最后一个被引用的地方，如果是那就删除</li>
</ul>
</li>
</ul>
<div class="language-lua vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">lua</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">local</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> M</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{}</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">funciton M.</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">func1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">end</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> -- 这样就可以在外面调用</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> M </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">-- 结束</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">local</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> M </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> require</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"moduletest"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">-- 在另一个文件中获得M调用函数即可</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br></div></div><p>多文件其实和单文件一模一样，非local修饰就对全局空间赋予变量操作，
local修饰是表示在当前作用域中是本地的，在函数里面声明就限制在函数里。</p>
<ol>
<li>通常在模块开发中，推荐使用 local 表 然后显式返回，这样可以更好地控制作用域</li>
<li>加载多文件不仅会拿到返回的table，还会在全局<code>package.loaded</code>中注册此module，<a href="https://www.yuque.com/chengxuyuanchangfeng/kre5yb/uyd7fgf5wg0psx21" target="_blank" rel="noreferrer">热更新原理</a>就是把它置为nil然后重新require替换掉
<ul>
<li>也会出现循环依赖</li>
<li>这个变量通过环境变量 LUA_CPATH 来初始化没有就用默认的</li>
</ul>
</li>
<li>公开函数可以访问私有函数，反之不行</li>
<li>私有函数实际上也可以赋值或者闭包返回，但是不要这么做</li>
<li>引用了之后没有被local修饰变量就会注册到全局，即便没有导出也会有，<strong>如果俩文件声明重名变量，可能会导致变量覆盖</strong></li>
<li>使用<code>function M:test() end</code> 相当于带了个py中的self进去，而且调用的时候不能混着调用，<code>:</code>定义就<code>:</code>调用点的就点调用。</li>
<li><code>function M.test(n, ...) local args={...} end</code>  这样就拿到了可变参数，都是按照自然数索引传的</li>
</ol>
<p>元表，相当于py中的魔术方法，可重载的函数也是有限的。把元表指定给某个表后，相当于为该表添加了特定的重载行为。<br>
两个变量里面都没有发现对应的行为就会报错，行为会优先调用元表的方法没有再调原生，再没有就报错<br>
经典示例两表合并重载加运算符</p>
<ul>
<li>使用<code>get/setmetatable</code>获取或者设置某table的元表，拿到就可以修改他原先元表的行为</li>
<li>给全局表<code>_G</code>设置metatable重载<code>__newindex</code> <code>__index</code> 可以阻止团队里滥用全局变量</li>
<li>使用rawset和rawget可以绕过元表的index相关方法拿值</li>
</ul>
<div class="language-lua vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">lua</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">local</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> mt</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{}</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">mt.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">__add</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=function</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(t1,t2) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">-- +的重载函数</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">  local</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> temp</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{}</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">  for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> _,v </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> pairs</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(t1)</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">do</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> table.insert</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(temp,v)</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">end</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">  for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> _,v </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> pairs</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(t2)</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">do</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> table.insert</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(temp,v)</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">end</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">  return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> temp</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">end</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">local</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> t1</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">local</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> t2</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">setmetatable</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(t1,mt)</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">local</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> t3</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">t1</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">t2</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">local</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> st</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"{"</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> _,v </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> pairs</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(t3)</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">do</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> st</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">st</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">..</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">v</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">..</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"," </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">end</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">st</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">st</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">..</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"}"</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(st)</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">-- {1,2,3,2,}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br></div></div><p>看一下<a href="https://www.runoob.com/lua/lua-coroutine.html" target="_blank" rel="noreferrer">协程</a>基本就是yield那一套，可以暂停函数的执行</p>
<p>常用深拷贝</p>
<div class="language-lua vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">lua</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">function</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> deepCopy</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(object)</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    local</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> lookup_table </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {}  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">-- 创建一个查找表，用于存储已经复制过的对象，避免循环引用。</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    local</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> function</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> _copy</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(object)</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        if</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> type</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(object) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">~=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "table" </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">then</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  -- 如果对象不是表，则直接返回该对象。</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> object</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        end</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> lookup_table[object] </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">then</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  -- 如果对象已经在查找表中，则直接返回对应的已复制对象。</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> lookup_table[object]</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        end</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        local</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> new_table </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {}  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">-- 创建一个新的表，并将当前对象与新表的对应关系存入查找表。</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        lookup_table[object] </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> new_table</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> key, value </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> pairs</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(object) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">do</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  -- 遍历原表的每个键值对，递归复制值，并设置到新表中。</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            new_table[</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">_copy</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(key)] </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> _copy</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(value)</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        end</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        setmetatable</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(new_table, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">getmetatable</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(object))  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">-- 设置新表的metatable为原表的metatable，确保元方法等特性也被复制。</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> new_table  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">-- 返回新创建的表。</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    end</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> _copy</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(object)  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">-- 调用内部复制函数，开始复制过程。</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">end</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br></div></div><p><a href="https://www.yuque.com/chengxuyuanchangfeng/kre5yb/bifewxt58ieuxuv0#" target="_blank" rel="noreferrer">实现简单的面向对象</a> 看好他的表，利用表的重载方法和metatable， 实现类似于OOP的东西（有点过于灵活了</p>
<p>lua的闭包和其他语言闭包一样，也是函数里面套函数，内部的函数引用的资源内存调用栈变量等都会存放起来，upvalue就是指向引用外部变量的指针，循环upvalue linked list查找，创建的时候标open用完了就置为close，下次GC就删掉。<br>
整个lua就是被包在<code>function main (...)</code>中，所以所有的函数实际上都是闭包，同理函数upvalue一开始就是指向全局栈，当被当作闭包返回才会指向指向upvalue linked list。</p>
<p>lua的GC使用标记-删除法，分代回收新申请的更容易被扫描，lua虚拟机提供了collectgarbage函数手动回收，但是一般不用。<a href="https://www.yuque.com/chengxuyuanchangfeng/kre5yb/vlnbnwzg7ddf2q98#" target="_blank" rel="noreferrer">GC八股看一下</a><br>
但是小心在lua引用的C#对象如果一直不释放就会导致内存泄漏</p>
<div class="warning custom-block"><p class="custom-block-title">[⚠️Warning]</p>
<p>热更代码中old_module已经在运行产生的数据变化和变量等不会被影响吗，热更新被替换的函数，万一还有正在运行的不久有问题了吗。我看市面上的解决方法是让玩家退出然后重新进游戏，是不是就是说重新运行游戏相当于lua虚拟机重启了重新加载了一次</p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>gpt</span></span>
<span class="line"><span>## 为什么游戏要求重新登录？</span></span>
<span class="line"><span>你的理解完全正确！ 重新登录 = Lua虚拟机重启 = 完全重新加载</span></span>
<span class="line"><span></span></span>
<span class="line"><span>### 重启的好处：</span></span>
<span class="line"><span>1. 状态清理 ：所有变量、连接、缓存都重新初始化</span></span>
<span class="line"><span>2. 避免版本混乱 ：不会出现新旧代码混合执行的情况</span></span>
<span class="line"><span>3. 内存清理 ：避免内存泄漏和垃圾数据</span></span>
<span class="line"><span>4. 确保一致性 ：所有模块都是同一版本</span></span>
<span class="line"><span>## 真正的热更新挑战</span></span>
<span class="line"><span>### 安全的热更新需要：</span></span>
<span class="line"><span>1. 状态迁移机制 ：保存关键数据，更新后恢复</span></span>
<span class="line"><span>2. 版本兼容性检查 ：确保数据结构兼容</span></span>
<span class="line"><span>3. 执行时机控制 ：在安全的时间点进行更新</span></span>
<span class="line"><span>4. 回滚机制 ：更新失败时能够恢复</span></span>
<span class="line"><span>### 实际应用中的策略：</span></span>
<span class="line"><span>- 配置热更 ：只更新配置数据，相对安全</span></span>
<span class="line"><span>- 功能热更 ：只在特定安全点（如玩家空闲时）进行</span></span>
<span class="line"><span>- 分模块更新 ：只更新独立性强的模块</span></span>
<span class="line"><span>- 灰度更新 ：先在少数玩家上测试</span></span>
<span class="line"><span>所以你看到的"要求重新登录"确实是最稳妥的方案，避免了热更新的各种风险。真正的无缝热更新技术门槛很高，需要精心设计的架构支持。</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br></div></div></div>
<p>lua和C#在交互的时候值类型也可能会因为拆装箱产生GC。
lua中的字符串分长短字符串40个为界，短字符串创建的时候就计算好了hash如果再创建或者调用相同的字符串会指向同一个，长字符串则每次都重新创建并设置GC相关，而且是用到的时候才赋值。</p>
<p>luaGC完了会 整理内存碎片 执行finalizer析构 更新弱引用
不太明白或者不太熟的有
<a href="https://www.yuque.com/chengxuyuanchangfeng/kre5yb/zregeuhb1k547mdy#" target="_blank" rel="noreferrer">为什么值传递有GC</a><br/>
<a href="https://www.yuque.com/chengxuyuanchangfeng/kre5yb/vlnbnwzg7ddf2q98#" target="_blank" rel="noreferrer">Lua的GC机制</a><br/>
<a href="https://www.yuque.com/chengxuyuanchangfeng/kre5yb/ke080d09iuvbrv5o#" target="_blank" rel="noreferrer">C#调用Lua细节</a><br/>
<a href="https://www.yuque.com/chengxuyuanchangfeng/kre5yb/bifewxt58ieuxuv0#" target="_blank" rel="noreferrer">实现简单的面向对象</a></p>
<h2 id="踩坑" tabindex="-1">踩坑 <a class="header-anchor" href="#踩坑" aria-label="Permalink to &quot;踩坑&quot;">&ZeroWidthSpace;</a></h2>
<p>作为一门副语言够用就行，在这整理遇到的坑<br>
lua在unity中不会被识别为资源文件，所以要改名为<code>script.lua.txt</code>这种后缀<br>
在Rider中安装</p>
<p>#todo Rider使用EmmyLua代码提示</p>
<p><a href="https://github.com/CppCXY/EmmyLua-Unity-LS" target="_blank" rel="noreferrer">GitHub - CppCXY/EmmyLua-Unity-LS</a><br/>
<a href="https://networm.me/2021/09/05/emmylua-debug-ignore/" target="_blank" rel="noreferrer">忽略 EmmyLua 调试代码 - 狂飙</a></p>
<p>使用Xlua的套路</p>
<div class="language-lua vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">lua</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">-- 一个面板一个表  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">BagPanel</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{}  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">-- 面板自身对象  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">BagPanel.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">panelObj</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">nil</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">-- 面板上的对象  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">BagPanel.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">CloseButton</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">nil</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">BagPanel.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">EquiToggl</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">nil</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">BagPanel.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">ItemToggle</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">nil</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">BagPanel.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GemToggle</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">nil</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">-- 成员方法  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">function</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> BagPanel</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Init</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">-- 初始化</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    if</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">panelObj</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> ==</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> nil</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> then</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        --实例化面板  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        --拿控件  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        --绑定事件  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    end</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">end</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">-- 显隐方法</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">function</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> BagPanel</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">ShowMe</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">Init</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">panelObj</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">SetActive</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">end</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">function</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> BagPanel</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">HideMe</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">panelObj</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">SetActive</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">end</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br></div></div><p>在Lua中TMP使用的应该是<code>TMPro.TextMeshProUGUI</code>和Csharp中不一样<br>
Xlua和AB打包有冲突，需要先清Xlua的ClearGenerateCode再打包。</p>
<h2 id="工程实践" tabindex="-1">工程实践 <a class="header-anchor" href="#工程实践" aria-label="Permalink to &quot;工程实践&quot;">&ZeroWidthSpace;</a></h2>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Unity-进阶知识]]></title>
            <link>http://ooowl.fun/blogs/Game/Unity/Unity-%E8%BF%9B%E9%98%B6%E7%9F%A5%E8%AF%86.html</link>
            <guid isPermaLink="false">http://ooowl.fun/blogs/Game/Unity/Unity-%E8%BF%9B%E9%98%B6%E7%9F%A5%E8%AF%86.html</guid>
            <pubDate>Tue, 04 Mar 2025 09:24:35 GMT</pubDate>
            <content:encoded><![CDATA[<h1 id="unity-进阶知识" tabindex="-1">Unity-进阶知识 <a class="header-anchor" href="#unity-进阶知识" aria-label="Permalink to &quot;Unity-进阶知识&quot;">&ZeroWidthSpace;</a></h1><p class="article-meta">创建于 2025年3月4日 17:24:35 · 约13,107字</p>
<h2 id="零碎" tabindex="-1">零碎 <a class="header-anchor" href="#零碎" aria-label="Permalink to &quot;零碎&quot;">&ZeroWidthSpace;</a></h2>
<h3 id="黑话" tabindex="-1">黑话 <a class="header-anchor" href="#黑话" aria-label="Permalink to &quot;黑话&quot;">&ZeroWidthSpace;</a></h3>
<ul>
<li>微端: 指很小的客户端通常是十几，几十MB，下载就开玩，边玩边下载即时用到的资源(这个概念不是特别严谨的定义)。</li>
<li>首包: 类似于LOL那种，下了10G就可以玩，高模资源等在后台下载。</li>
<li>常见黑话可能对于行业内的属于常识了。（来自 b 站 up 主隼流阿哲，相关账号已注销）</li>
</ul>
<details class="details custom-block"><summary>不装逼会死吗</summary>
<p>装逼会死吗</p>
<table tabindex="0">
<thead>
<tr>
<th>游戏类型</th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td>AVG</td>
<td>文字冒险游戏</td>
<td>Adventure Game</td>
</tr>
<tr>
<td>SLG</td>
<td>模拟策略游戏</td>
<td>Simulation Game</td>
</tr>
<tr>
<td>RTS</td>
<td>及时战略游戏</td>
<td>Real Time Strategy Game</td>
</tr>
<tr>
<td>MMO</td>
<td>大型多人在线游戏</td>
<td>Massive Multiplayer Online Game</td>
</tr>
<tr>
<td>MOBA</td>
<td>多人在线战术竞技游戏</td>
<td>Multiplayer Online Battle Area</td>
</tr>
<tr>
<td>TBS</td>
<td>回合制策略游戏</td>
<td>Turn Based Strategy Game</td>
</tr>
<tr>
<td>FTG</td>
<td>格斗游戏</td>
<td>Fighting Game</td>
</tr>
<tr>
<td>STG</td>
<td>射击游戏</td>
<td>Shooting Game</td>
</tr>
<tr>
<td>PZL</td>
<td>益智游戏</td>
<td>Puzzle Game</td>
</tr>
<tr>
<td>RCG</td>
<td>竞速游戏</td>
<td>Racing Game</td>
</tr>
<tr>
<td>SPT</td>
<td>体育游戏</td>
<td>Sports Game</td>
</tr>
<tr>
<td>CAG</td>
<td>卡牌游戏</td>
<td>Card Game</td>
</tr>
<tr>
<td>TAB</td>
<td>桌面游戏</td>
<td>Table Game</td>
</tr>
<tr>
<td>MSC</td>
<td>音乐游戏</td>
<td>Music Game</td>
</tr>
</tbody>
</table>
<table tabindex="0">
<thead>
<tr>
<th>游戏内名词</th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td>PVE</td>
<td>玩家VS AI敌人 Player VS Environment</td>
</tr>
<tr>
<td>PVP</td>
<td>玩家VS玩家 Player VS Player</td>
</tr>
<tr>
<td>HOT</td>
<td>指持续性治疗效果 Heal Over Time</td>
</tr>
<tr>
<td>DOT</td>
<td>持续性伤害效果 Damage Over Time</td>
</tr>
<tr>
<td>AOE</td>
<td>法术场效果 Area of effect</td>
</tr>
<tr>
<td>AFK</td>
<td>脱手操作，放置型 Away from keyboard</td>
</tr>
<tr>
<td>DD</td>
<td>直接伤害，非持续性伤害 Direct Damage</td>
</tr>
<tr>
<td>DPS</td>
<td>每秒造成伤害 Damage per second</td>
</tr>
<tr>
<td>BUFF</td>
<td>主要指辅助类角色为别人施加的有益状态，通俗的说法就是“加状态”</td>
</tr>
<tr>
<td>NPC</td>
<td>Non Player Character（非玩家角色）</td>
</tr>
</tbody>
</table>
<table tabindex="0">
<thead>
<tr>
<th>运营术语</th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td>ACU</td>
<td>Average Concurrent Users</td>
<td>24小时内每小时平均在线用户</td>
</tr>
<tr>
<td>DAU</td>
<td>Daily Active User</td>
<td>日活跃用户量</td>
</tr>
<tr>
<td>PCU</td>
<td>Peek Concurrent Users</td>
<td>24小时内同时最高在线人数</td>
</tr>
<tr>
<td>DNU</td>
<td>Daily New User</td>
<td>单日新增用户</td>
</tr>
<tr>
<td>URR</td>
<td>Users Retention Ratio</td>
<td>用户留存率</td>
</tr>
<tr>
<td>ARPU</td>
<td>Average Revenue Per User</td>
<td>平均每个用户产生的收入</td>
</tr>
<tr>
<td>ARPPU</td>
<td>Average Revenue Per Paying User</td>
<td>平均每个付费用户产生的收入</td>
</tr>
<tr>
<td>DCR</td>
<td>Daily Churn Rate</td>
<td>日流失率</td>
</tr>
<tr>
<td>CP</td>
<td>Content Provider</td>
<td>内容提供商</td>
</tr>
<tr>
<td>SP</td>
<td>Server Provider</td>
<td>服务提供商</td>
</tr>
<tr>
<td>QA</td>
<td>Quality Assesment</td>
<td>质量测试</td>
</tr>
<tr>
<td>QC</td>
<td>Quality Control</td>
<td>质量控制</td>
</tr>
<tr>
<td>CB</td>
<td>Close Beta</td>
<td>封闭删档测试</td>
</tr>
<tr>
<td>OB</td>
<td>Open Beta</td>
<td>开放不删档测试</td>
</tr>
</tbody>
</table>
<table tabindex="0">
<thead>
<tr>
<th>国产原创黑话</th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td>大中小R</td>
<td>什么都充，活动充，新手礼包充</td>
</tr>
<tr>
<td>洗人</td>
<td>把玩家从某个游戏拉到另一个游戏</td>
</tr>
<tr>
<td>马甲包</td>
<td>换皮，稍微改一点点美术变成另一个游戏</td>
</tr>
<tr>
<td>冲榜</td>
<td>冲击各种游戏榜单</td>
</tr>
<tr>
<td>起量</td>
<td>流量逐渐上升</td>
</tr>
<tr>
<td>爆量</td>
<td>流量短期突然上升</td>
</tr>
<tr>
<td>买量</td>
<td>通过花钱打广告获得流量和用户</td>
</tr>
<tr>
<td>换量</td>
<td>不用应用内的广告相互推广，我的点进你的，你的进我的</td>
</tr>
<tr>
<td>导量</td>
<td>通过渠道把用户引入游戏内</td>
</tr>
<tr>
<td>卖量</td>
<td>渠道把流量卖给应用商</td>
</tr>
<tr>
<td>七大类</td>
<td>广电总局规定的，七种审核类型。“不涉及政治、军事、民族、宗教等题材内容,<br/>办理周期短且无故事情节或者情节简单的<br/>消除类、跑酷类、飞行类、棋牌类、解谜类、体育类、音乐舞蹈类</td>
</tr>
</tbody>
</table>
<table tabindex="0">
<thead>
<tr>
<th>互联网通用黑话</th>
<th>这个随便看看，反正遍地是</th>
</tr>
</thead>
<tbody>
<tr>
<td>复盘</td>
<td>回忆总结之前的工作</td>
</tr>
<tr>
<td>闭环</td>
<td>一套成体系自洽的方案</td>
</tr>
<tr>
<td>脑暴</td>
<td>头脑风暴，点子idea</td>
</tr>
<tr>
<td>痒点</td>
<td>没有也还行，有更好的东西</td>
</tr>
<tr>
<td>痛点</td>
<td>没有他不太行，但他还真没有的东西</td>
</tr>
<tr>
<td>爽点</td>
<td>成功给到了他想要的东西</td>
</tr>
<tr>
<td>差异化</td>
<td>要不同有区别</td>
</tr>
<tr>
<td>底层逻辑</td>
<td>深层原理</td>
</tr>
<tr>
<td>对/碰</td>
<td>讨论</td>
</tr>
<tr>
<td>对齐</td>
<td>意见统一</td>
</tr>
<tr>
<td>生态</td>
<td>某个领域圈子</td>
</tr>
<tr>
<td>颗粒度</td>
<td>细致程度</td>
</tr>
<tr>
<td>引爆点</td>
<td>突然让人关注的地方</td>
</tr>
<tr>
<td>背书</td>
<td>找有名的人，机构做担保，推荐</td>
</tr>
</tbody>
</table>
</details>
<h3 id="指标术语" tabindex="-1">指标术语 <a class="header-anchor" href="#指标术语" aria-label="Permalink to &quot;指标术语&quot;">&ZeroWidthSpace;</a></h3>
<h3 id="项目设置" tabindex="-1">项目设置 <a class="header-anchor" href="#项目设置" aria-label="Permalink to &quot;项目设置&quot;">&ZeroWidthSpace;</a></h3>
<p>包管理的几种方式 #todo 包管理啊嗯</p>
<ul>
<li><code>manifest.json</code>定义自动安装</li>
<li>Window-&gt;PackageManager</li>
<li>DLL文件放到Assets/Plugins</li>
<li>源码扔Assets
补充注意事项</li>
<li>在dotnet中可以使用nuget安装，但是untiy不直接使用dotent的包管理器。两种方式，将对应的DLL文件放到Assets/Plugins下面；或者在<code>Window-&gt;PackageManager</code>中<code>Add package from git URL</code>填入对应的地址。
<ul>
<li>这里调用的git不会使用shell里的代理，必须git config单独设置代理</li>
</ul>
</li>
<li>在nuget.org可以下载nuget包,就是压缩包解压之后可以获得已经编译好的dll，一般在lib里自己翻翻</li>
<li>自定义package源Edit-&gt;ProjectSetting-&gt;PackageManager 按照人家给的软件源注册进去，Window-&gt;PackageManager-&gt;选择repo</li>
<li>Window-&gt;PackageManager-&gt;AddPackageByName可以类似于manifest.json一样引入包
<ul>
<li>有时PackageManager或者manifest.json装了，但 Unity 并没有生成 <code>.dll</code> 到Library里，在 Unity 编辑器里 <code>Assets-&gt;ReimportAll</code>或者删除Library重启  .</li>
</ul>
</li>
<li><a href="https://github.com/GlitchEnzo/NuGetForUnity" target="_blank" rel="noreferrer">NuGetForUnity</a>照着README安，tools上会出现Nuget栏，后面就可以愉快的使用了。</li>
<li><a href="https://openupm.com/" target="_blank" rel="noreferrer">openupm</a>是Nodejs的一个库，可以用来安装Unity的包<code>npm install -g openupm-cli</code>就可以使用openupm的命令了</li>
<li>当有A文件编译错误的时候，整个untiy都是未编译的状态，这时用unitypackage导入包B，可能根本没有到编译那一步看起来就和没导入一样</li>
<li>当出现死循环的时候整个unity会卡主，IDE中断点只能断到死循环附近不定那一行，单步执行不定哪一步就进不去了</li>
<li>自定义宏ProjectSettings-&gt;PlayerSettings-&gt;OtherSettings-&gt;ScriptingDefineSymbols，可以定义项目的宏
<ul>
<li>define只能影响当前文件；ScriptingDefineSymbols 会在整个项目（或指定平台、指定程序集）统一生效，适合跨多文件的条件编译需求。</li>
<li>Scripting Define Symbols 可以按 Build Target（如 Android、iOS、Standalone）分别设置，define做不到</li>
</ul>
</li>
</ul>
<details class="details custom-block"><summary>常用预处理器指令(并非常用)</summary>
<p>用预处理器指令(并非常用)</p>
<table tabindex="0">
<thead>
<tr>
<th>常用预处理器指令</th>
<th>描述</th>
</tr>
</thead>
<tbody>
<tr>
<td>UNITY_EDITOR</td>
<td>脚本符号，用于从游戏代码中调用 Unity 编辑器脚本。</td>
</tr>
<tr>
<td>UNITY_EDITOR_WIN</td>
<td>Windows 上编辑器代码的脚本符号。</td>
</tr>
<tr>
<td>UNITY_EDITOR_OSX</td>
<td>Mac OS X 上编辑器代码的脚本符号。</td>
</tr>
<tr>
<td>UNITY_EDITOR_LINUX</td>
<td>Linux 上编辑器代码的脚本符号。</td>
</tr>
<tr>
<td>UNITY_STANDALONE_OSX</td>
<td>脚本符号，用于编译或执行专门针对 Mac OS X 的代码（包括通用、PPC 和英特尔架构）。</td>
</tr>
<tr>
<td>UNITY_STANDALONE_WIN</td>
<td>脚本符号，用于专门为 Windows 独立应用程序编译/执行代码。</td>
</tr>
<tr>
<td>UNITY_STANDALONE_LINUX</td>
<td>脚本符号，用于专门为 Linux 独立应用程序编译/执行代码。</td>
</tr>
<tr>
<td>UNITY_STANDALONE</td>
<td>脚本符号，用于为任何独立平台（Mac OS X、Windows 或 Linux）编译/执行代码。</td>
</tr>
<tr>
<td>UNITY_WII</td>
<td>用于编译/执行 Wii 控制台代码的脚本符号。</td>
</tr>
<tr>
<td>UNITY_IOS</td>
<td>用于为 iOS 平台编译/执行代码的脚本符号。</td>
</tr>
<tr>
<td>UNITY_IPHONE</td>
<td>已弃用，改用 UNITY_IOS。</td>
</tr>
<tr>
<td>UNITY_ANDROID</td>
<td>安卓平台的脚本符号。</td>
</tr>
<tr>
<td>UNITY_LUMIN</td>
<td>Magic Leap OS 平台的脚本符号。您也可以使用 PLATFORM_LUMIN。</td>
</tr>
<tr>
<td>UNITY_TIZEN</td>
<td>Tizen 平台的脚本符号。</td>
</tr>
<tr>
<td>UNITY_TVOS</td>
<td>Apple TV 平台的脚本符号。</td>
</tr>
<tr>
<td>UNITY_WSA</td>
<td>通用 Windows 平台的脚本符号。此外，在针对 .NET Core 编译 C# 文件并使用 .NET 脚本后端时，将定义 NETFX_CORE。</td>
</tr>
<tr>
<td>UNITY_WSA_10_0</td>
<td>通用 Windows 平台的脚本符号。此外，在针对 .NET Core 编译 C# 文件时，还会定义 WINDOWS_UWP。</td>
</tr>
<tr>
<td>UNITY_WEBGL</td>
<td>WebGL 的脚本符号。</td>
</tr>
<tr>
<td>UNITY_FACEBOOK</td>
<td>Facebook 平台的脚本符号（WebGL 或 Windows 独立）。</td>
</tr>
<tr>
<td>UNITY_ANALYTICS</td>
<td>用于从游戏代码调用 Unity 分析方法的脚本符号，版本 5.2 及更高版本。</td>
</tr>
<tr>
<td>UNITY_ASSERTIONS</td>
<td>断言控制过程的脚本符号。</td>
</tr>
<tr>
<td>UNITY_64</td>
<td>64 位平台的脚本符号。</td>
</tr>
</tbody>
</table>
</details>
<h2 id="imgui" tabindex="-1">IMGUI <a class="header-anchor" href="#imgui" aria-label="Permalink to &quot;IMGUI&quot;">&ZeroWidthSpace;</a></h2>
<h3 id="组件核心" tabindex="-1">组件核心 <a class="header-anchor" href="#组件核心" aria-label="Permalink to &quot;组件核心&quot;">&ZeroWidthSpace;</a></h3>
<p><a href="https://docs.unity3d.com/2022.3/Documentation/ScriptReference/UnityEngine.IMGUIModule.html" target="_blank" rel="noreferrer">IM<strong>GUI</strong></a>（Immediate Mode GUI即时模式图形用户界面）一般简称GUI。是一个代码驱动的UI系统，不要用它为玩家制作UI功能，GUI主要用于开发和调试阶段创建游戏内调试工具在运行时检查和调整游戏状态；制作Unity的拓展工具和编辑器UI。比如地图编辑器，技能编辑器，资源打包自定义等。<br>
在 MonoBehaviour中有一个特殊的函数<code>void OnGUI</code>在里面写GUI相关的代码，类似于生命周期每帧执行，在OnDisable和LateUpdate之间执行，这意味着Inspector修改参数会有即时反馈。<br>
<strong>Texture的缩放比例会始终保持一致</strong>，一般把这东西放出来都是为了编辑，权限public就行。 <mark>GUI的画布原点(0,0)是在左上角</mark><br>
所有控件必传的是<strong>位置信息</strong>和<strong>内容</strong></p>
<ul>
<li>使用 <code>Rect</code> 参数来指定控件的位置和尺寸。<code>Rect</code> 包含 <code>x</code> 和 <code>y</code> 位置以及 <code>width</code> 和 <code>height</code> 尺寸</li>
<li>内容可以点进函数里面看，大部分都接受<code>GUIContent</code>比如下面的btncontent</li>
<li>选传 <code>GUIStyle</code>，可以先声明一个GUIStyle对象，就可以编辑CSS啦😄（哈哈兜兜转转又回到web</li>
</ul>
<p>按钮只有在按钮内部进行一次按下和点击才算点击。只能按一次，但是RepeatButton可以长按一直触发（竟然用if来判断我为什么感觉这方式有点沙币<br>
使用GUIStyle 中的 FixedWidth FixedHeight去修改图片的大小和响应区域，不要改Rect<br>
Normal(false)/OnNormal(true)修改是否选中的状态，单选可以自己做出来，<strong>注意看在一个循环返回中怎么处理的</strong><br>
窗口必须 <strong>赋值</strong> 且 <strong>在函数中DragWindow</strong>才能拖动！！！DragWindow可以确定可以拖动的范围</p>
<details class="details custom-block"><summary>IMGUI基本使用</summary>
<p>MGUI基本使用</p>
<div class="language-Csharp vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">Csharp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> IMGUI</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> : </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">MonoBehaviour</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    // 测试文本  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> GUIContent</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> content</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Rect</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> rect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Rect</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> rect1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Texture</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> tex</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    // 测试按钮  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Rect</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> btnrect</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Rect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">600</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">800</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">100</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">100</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> GUIContent</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> btncontent</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    // toggle选项框  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    private</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> bool</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> isSealed0</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    private</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> bool</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> isSealed1</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    private</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> int</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> isSealed3</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> GUIStyle</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> style1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    //  文字和密码  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> string</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> inputString</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"请接收输入"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> string</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> inputStringPasswd</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"输入密码"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    //  滑动条  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> float</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> nowValue</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">5f</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">minVlaue</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0f</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">maxVlaue</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">10f</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    // 画个图  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Texture2D</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> demoTexture</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    //  多选工具栏(按钮)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> int</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> toolbarIndex</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    private</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> string</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[] </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">toolbarNames</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=new</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> string</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[]{</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"选项一"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"选项二"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"选项三"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">};  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> int</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> gridIndex</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    private</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> string</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[] </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">gridNames</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=new</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> string</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[]{</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"选项一"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"选项二"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"选项三"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"选项2一"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"选项2二"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"选项2三"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">};  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    private</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> string</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[] </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">demogride</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =new</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> string</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[]{</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"选项一"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"选项二"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"选项三"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"选项2一"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"选项2二"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"选项2三"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"选项3一"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"选项3二"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"选项3三"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"选项4一"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"选项4二"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"选项4三"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">};  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    //  遮罩窗口  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Rect</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> groupos</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Rect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">50</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">660</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">200</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">200</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    //  滑动条窗口  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Rect</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> scPos</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Rect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Vector2</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> nowPos</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Vector2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Rect</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> showPos</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Rect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    //  窗口相关  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> int</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> windowUid</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Rect</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> windowPos</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Rect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">50</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">800</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">200</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">200</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    private</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> OnGUI</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {   </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        GUI.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Label</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Rect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">100</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">20</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">),</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"烤全羊啊嗯"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  使用Label绘制  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        GUI.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Label</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(rect,tex);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        content.text </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "打组一块显示"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        content.image </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> tex;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        content.tooltip </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "中嘞！"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  鼠标移动上去显示  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        GUI.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Label</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(rect1,content); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 可以给GUI组件设置tooltip  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        // 鼠标移上去的时候就可以直接显示tooltip,默认是空字符串，他会一直打印很烦  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(GUI.tooltip</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">!=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">""</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) Debug.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(GUI.tooltip);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        btncontent.text </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "按钮哎"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (GUI.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Button</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(btnrect, btncontent)) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 这按钮只能按一次，但是RepeatButton可以长按一直触发  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        {  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">            print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"你们这是什么按钮啊，你们这个按钮害人不浅！"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        }  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        // toggle选项框  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        isSealed0 </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> GUI.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Toggle</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Rect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">100</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">30</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">),isSealed0, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"效果开关0"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        isSealed1 </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> GUI.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Toggle</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Rect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">300</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">300</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">100</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">30</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">),isSealed1, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"效果开关1"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,style1); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// rect 的宽高是toggle的响应位置  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(GUI.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Toggle</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Rect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">50</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">80</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">100</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">30</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">),isSealed3</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">==</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"效果开关3-0"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">))isSealed3 </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(GUI.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Toggle</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Rect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">50</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">100</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">100</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">30</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">),isSealed3</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">==</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"效果开关3-1"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">))isSealed3 </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(GUI.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Toggle</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Rect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">50</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">120</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">100</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">30</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">),isSealed3</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">==</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"效果开关3-2"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">))isSealed3 </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(GUI.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Toggle</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Rect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">50</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">140</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">100</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">30</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">),isSealed3</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">==</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">4</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"效果开关3-3"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">))isSealed3 </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 4</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        //  文字和密码  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        inputString </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> GUI.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">TextField</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Rect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">50</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">160</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">100</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">30</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">), inputString);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        inputStringPasswd </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> GUI.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">PasswordField</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Rect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">50</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">200</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">100</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">30</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">), inputStringPasswd,</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'星'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 接收密码字段  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        //  滑动条  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        nowValue </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> GUI.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">HorizontalSlider</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Rect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">50</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">250</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">100</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">30</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">), nowValue, minVlaue, maxVlaue);  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        // 直接画个图  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        // 后面是 ScaleToFit 计算宽高，等比例缩放不裁剪 StretchToFill 无视比例拉伸 ScaleAndCrop 等比例缩放会裁剪  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        // imageAspect 自定义缩放宽高比  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        GUI.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">DrawTexture</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Rect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">50</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">350</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">100</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">100</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">),demoTexture,</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">scaleMode</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:ScaleMode.StretchToFill,</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">alphaBlend</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">imageAspect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">10</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        GUI.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Box</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Rect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">50</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">400</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">100</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">100</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">),</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"这是个盒子，一个非常单纯的盒子"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        //  多选工具栏(按钮)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        toolbarIndex</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">GUI.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Toolbar</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Rect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">50</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">500</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">200</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">50</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">),toolbarIndex,toolbarNames); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 需要不断赋值，可以使用switch case赋值  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        gridIndex</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">GUI.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">SelectionGrid</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Rect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">50</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">560</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">200</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">50</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">), gridIndex, gridNames,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 就是满了会自动换行  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        //  相当于html里的遮罩，只显示窗口位置  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        GUI.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">BeginGroup</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(groupos); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// Rect  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        GUI.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Button</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Rect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">80</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">60</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">),</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"你们这个按钮也害人不浅啊"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        GUI.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">EndGroup</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        //  Rect position组件的位置大小 Vector2 scrollPosition滑动到哪了 Rect viewRect 内容的范围大小  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        nowPos</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">GUI.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">BeginScrollView</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(scPos,nowPos,showPos);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        GUI.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">SelectionGrid</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Rect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">200</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">50</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">), </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, demogride,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">4</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 注意位置已经是相对位置了  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        GUI.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">EndScrollView</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        //  窗口相关，必须 赋值 且 在函数中DragWindow才能拖动！！！  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        windowPos</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">GUI.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Window</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(windowUid, windowPos, DrawWindow,</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"窗口标题"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 会调用函数里面的东西进行绘制  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        GUI.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">ModalWindow</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(windowUid</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, windowPos, DrawWindow,</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"窗口标题"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 相当于获取了焦点的窗口，相当于alert了  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    private</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> DrawWindow</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">int</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> windowID</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  实际上这东西绑在了一个委托上  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        //  可以通过windowID来判断不同窗口的处理逻辑  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        GUI.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">RepeatButton</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Rect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">10</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">10</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">40</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">50</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">), </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"按钮按钮"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (windowUid </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">==</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 给第一个窗口用的  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        {   </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 允许拖动这一步也是必须的  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            GUI.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">DragWindow</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Rect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1000</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">20</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 允许拖动哪一块范围，默认全能拖  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        }  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }   </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br><span class="line-number">50</span><br><span class="line-number">51</span><br><span class="line-number">52</span><br><span class="line-number">53</span><br><span class="line-number">54</span><br><span class="line-number">55</span><br><span class="line-number">56</span><br><span class="line-number">57</span><br><span class="line-number">58</span><br><span class="line-number">59</span><br><span class="line-number">60</span><br><span class="line-number">61</span><br><span class="line-number">62</span><br><span class="line-number">63</span><br><span class="line-number">64</span><br><span class="line-number">65</span><br><span class="line-number">66</span><br><span class="line-number">67</span><br><span class="line-number">68</span><br><span class="line-number">69</span><br><span class="line-number">70</span><br><span class="line-number">71</span><br><span class="line-number">72</span><br><span class="line-number">73</span><br><span class="line-number">74</span><br><span class="line-number">75</span><br><span class="line-number">76</span><br><span class="line-number">77</span><br><span class="line-number">78</span><br><span class="line-number">79</span><br><span class="line-number">80</span><br><span class="line-number">81</span><br><span class="line-number">82</span><br><span class="line-number">83</span><br><span class="line-number">84</span><br><span class="line-number">85</span><br><span class="line-number">86</span><br><span class="line-number">87</span><br><span class="line-number">88</span><br><span class="line-number">89</span><br><span class="line-number">90</span><br><span class="line-number">91</span><br><span class="line-number">92</span><br><span class="line-number">93</span><br><span class="line-number">94</span><br><span class="line-number">95</span><br><span class="line-number">96</span><br><span class="line-number">97</span><br><span class="line-number">98</span><br><span class="line-number">99</span><br></div></div></details>
<div class="tip custom-block"><p class="custom-block-title">[💡Tip]</p>
<p>GUI控制显示隐藏，可以写在一个脚本中，用变量控制启用；或者挂在对象上，控制脚本是否启用；或者控制对象是是否启用。<br>
一般是控制对象，高级一点的UI框架都是这么封装的</p>
</div>
<h3 id="guilayout" tabindex="-1">GUILayout <a class="header-anchor" href="#guilayout" aria-label="Permalink to &quot;GUILayout&quot;">&ZeroWidthSpace;</a></h3>
<p>GUILayout 可以用来写顶栏工具和Inspector不太适合直接写UI
设置全局颜色<code>GUI.color</code>然后再设置文本颜色<code>GUI.contentColor</code>或<code>GUI.backgroundColor</code>这两个颜色会相乘好怪，就这仨颜色。 <mark>颜色会跨脚本影响看执行顺序</mark><br>
<strong>右键创建GUI Skin</strong> 可以直接读取预设的主题，使用<code>GUISkin skin</code>来创建，赋值创建的GUISkin文件就可以了。绘制时使用了<code>GUIStyle</code>会优先使用指定的样式。</p>
<details class="details custom-block"><summary>IMGUI的常用布局示例</summary>
<p>MGUI的常用布局示例</p>
<div class="language-Csharp vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">Csharp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">private</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> OnGUI</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    //  全局颜色  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    GUI.color </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Color</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1f</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0f</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0f</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1f</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// RGBA颜色  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    GUI.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Label</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Rect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">150</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">100</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">100</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">100</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">),</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"This is red text"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    // GUI.color = Color.white;</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> // 白色重置颜色  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    GUI.skin </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 规定接下来绘制使用GUISkin  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    // GUILayout 可以用来写顶栏工具和Inspector  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    GUILayout.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Button</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"按钮1哦"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,GUILayout.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">ExpandWidth</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// GUILayout.Width(300);在此控件上失效  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    GUILayout.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Button</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"按钮2哦"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    GUILayout.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Button</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"按钮3哦"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    GUILayout.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">BeginVertical</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 布局控制  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    GUILayout.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">EndVertical</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    //  GUILayoutOption提供的选项  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    // 控件的固定宽高  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    GUILayout.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Width</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">300</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    GUILayout.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Height</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">200</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    // 允许控件的最小宽高  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    GUILayout.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">MinWidth</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">50</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    GUILayout.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">MinHeight</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">50</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    // 允许控件的最大宽高  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    GUILayout.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">MaxWidth</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">100</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    GUILayout.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">MaxHeight</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">100</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    // 允许或禁止水平的样式  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    GUILayout.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">ExpandWidth</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 允许水平  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    GUILayout.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">ExpandHeight</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 禁止高度  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br></div></div></details>
<p>IMGUI缺点是 <strong>代码控制繁琐，运行时才能看效果，不能分辨率自适应</strong>。  <mark><strong>在mono类加特性<code>[ExecuteAlways]</code>可以让UI所见即所得</strong></mark> （其他的脚本其实也能用</p>
<p>UI血条跟随屏幕动，使用IMGUI的小框架，因为屏幕的Y轴是从左下角算起的，而IMGUI原点是从右上角算的，注意怎么转换</p>
<div class="language-Csharp vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">Csharp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Texture</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> maxHpBG</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Texture</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> hpBG</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Rect</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> maxHpRect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Rect</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> hpRect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">private</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> OnGUI</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    Vector3</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> screenPos</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Camera.main.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">WorldToScreenPoint</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">this</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.transform.position);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    screenPos.y </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Screen.height </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> screenPos.y; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 因为屏幕的Y轴是从左下角算起的，而IMGUI原点是从右上角算的，注意怎么转换  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    maxHpRect.x </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> screenPos.x </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 50</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    maxHpRect.y </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> screenPos.y </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 50</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    maxHpRect.width </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 100</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    maxHpRect.height </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 15</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    // 画血条背景</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    GUI.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">DrawTexture</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(maxHpRect, maxHpBG);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    hpRect.x </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> screenPos.x </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 50</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    hpRect.y </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> screenPos.y </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 50</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    hpRect.width </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">float</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)Hp </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">/</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> maxHP </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 100f</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    hpRect.height </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 15</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    // 画血条</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    GUI.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">DrawTexture</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(hpRect, hpBG);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br></div></div><h2 id="ugui" tabindex="-1">UGUI <a class="header-anchor" href="#ugui" aria-label="Permalink to &quot;UGUI&quot;">&ZeroWidthSpace;</a></h2>
<p>NGUI太老了，听劝学UGUI<br>
Unity内置的右键Create-&gt;UI创建 一旦创建UI组件会自动创建Canvas和EventSystem。在 <strong>Game窗口-&gt;Stats(Statistics)-&gt;Batches</strong>就是DrawCall的数量。</p>
<h3 id="组件核心-1" tabindex="-1">组件核心 <a class="header-anchor" href="#组件核心-1" aria-label="Permalink to &quot;组件核心&quot;">&ZeroWidthSpace;</a></h3>
<p><strong>Canvas</strong> 负责渲染所有的子UI，不在Canvas的UI渲染不了，场景上允许有多个Canvas以设置不同的渲染和分辨率适应，但是一般情况只有一个。参数如下：<br>
RenderMode渲染模式</p>
<ul>
<li>默认ScreenSpaceOverlay屏幕空间，UI始终在前。WorldSpace世界空间3D模式（VRAR常用，游戏不常用）
<ul>
<li>PixelPerfect无锯齿精确渲染，性能换效果(图集够清楚就不用)</li>
<li>SortOrder控制多个Canvas的渲染顺序，越小的在越前</li>
</ul>
</li>
<li>ScreenSpaceCamera屏幕空间摄像机模式，3D物体可以显示在UI之前。
<ul>
<li>RenderCamera使用屏幕空间时的参数。
<ul>
<li>一般 <mark>不推荐使用主摄像机，使用单独UI摄像机ClearFlags-&gt;DepthOnly，CullingMask-&gt;UI，去掉音频监听，主摄像机CullingMask不渲染UI层，以便控制UI和3D物体先后顺序</mark></li>
<li>3D物体和粒子想要显示在前面就直接扔UI摄像机下面，改变大小，粒子有单独的OrderInLayer。或者使用右键Create-&gt;<strong>RenderTexture</strong>，设置好摄像机，挂载到RawImage。</li>
</ul>
</li>
<li>PlaneDistance控制UI层离摄像机远近</li>
<li>SortingLayer+SortingOrder层和层内Order对多个Canvas排序（回忆一下层排序的方法</li>
</ul>
</li>
<li>WorldSpace 作为一个对象存在场景内，很多时候在世界中做跟随角色血条用
<ul>
<li>使用世界空间的时候，既处理元素与其他元素的位置，又要处理相对摄像机视角位置，不同设备分辨率又不一样很麻烦</li>
</ul>
</li>
</ul>
<p><strong>CanvasScaler</strong> 用于画布缩放分辨率自适应。注意他不负责位置由RectTransform去负责。选中指定Canvas之后在RectTransform中可以看到<strong>宽高</strong>和<strong>缩放系数</strong>，符合公式 <mark>宽高x缩放系数=分辨率</mark><br>
更改这个组件本质上来说就是<strong>屏幕分辨率</strong>和<strong>参考分辨率</strong>经过<strong>不同算法</strong>计算得出<strong>缩放系数</strong>然后参与RectTransform计算<br>
UIScaleMode</p>
<ul>
<li>ConstantPixelSize默认UI始终固定大小(用的少，除非用代码计算
<ul>
<li>ScaleFactor 手动指定RectTransform的缩放系数</li>
<li>ReferencePixelsPerUnit参考单位像素 符合公式 <mark>UI原始尺寸=图片大小(像素)/(PixelsPerUnit/ReferencePixelsPerUnit)</mark></li>
</ul>
</li>
<li><strong>ScaleWithScreenSize</strong>缩放模式
<ul>
<li>ReferenceResolution参与分辨率自适应的计算(美术出图的标准分辨率</li>
<li>ScreenMatchMode
<ul>
<li>Expand：拓展画布的宽或高使其高于参考分辨率，可能产生黑边。 <mark>缩放系数=Mathf.Min(屏幕宽/参考分辨率宽，屏幕高/参考分辨率高); 画布尺寸=屏幕尺寸/缩放系数</mark></li>
<li>Shrink：裁剪画布区域根据宽高比<strong>放大</strong>画布，可能产生裁剪。 <mark>缩放系数=Mathf.Max(屏幕宽/参考分辨率宽，屏幕高/参考分辨率高); 画布尺寸=屏幕尺寸/缩放系数</mark></li>
<li>MatchWidthOrHeight：以宽高或者二者的平均值作为参考来缩放画布区域(使用对数计算)复习到的时候最好还是看看效果
<ul>
<li>Match竖屏游戏=0 保证宽度优先，高了上下会有黑边，矮了左右会被裁剪，但是保持UI缩放大小不变</li>
<li>Match横屏游戏=1 保证高度优先，宽了左右会有黑边，窄了左右会被裁剪，但是保持UI缩放大小不变</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li>ConstantPhysicalSizeUI始终保持相同物理大小
<ul>
<li>PhysicalUnit使用什么单位计算</li>
<li>后面三个都是DPI的设置FallbackScreenDPI获取不到系统DPI的回滚值，DefaultSpriteDPI美术出图的参考DPI  ReferencePixelsPerUnit单位参考像素
<ul>
<li><mark>新单位参考像素=单位参考像素xPhysicalUnit/DefaultSpriteDPI</mark> 然后再用这个新单位参考像素执行ConstantPixelSize的计算</li>
<li>和ConstantPixelSize相比都不会进行缩放有多大显示多大，会根据DPI调整大小以保持物理像素一样</li>
</ul>
</li>
</ul>
</li>
<li>使用建议一般使用ScaleWithScreenSize，存在横竖屏切换就Expand或Shrink，否则就MatchWidthOrHeight</li>
</ul>
<p><strong>GraphicRaycaster</strong> 检测UI输入事件的射线发射器，是通过<strong>图形</strong>不是通过刚体碰撞器完成的。屏幕空间摄像机模式下面参数才能起效</p>
<ul>
<li>IgnoreReversedGraphics是否忽略反转图形，如果元素XY被反转过，能不能被响应点击。</li>
<li>BlockingObjects 会被哪些碰撞器挡住射线</li>
<li>BlockingMask 和第二个配合，可以指定某些层的挡住射线，其他不能</li>
</ul>
<p><strong>EventSystem</strong> 事件系统，管理输入事件都会被它轮询检测并分发给UI控件</p>
<ul>
<li>First Selected：一开始就的焦点，可以设置到哪个对象上</li>
<li>SendNavigationEvents：是否允许导航事件键盘wasd在元素间移动焦点</li>
<li>DragThreshold：拖拽操作的阈值（移动多少像素算拖拽）</li>
</ul>
<p><strong>StandaloneInputModule</strong> 一般不会进行修改，相当于UGUI和InputManager对接的模块。注意下面参数</p>
<ul>
<li>InputActionsPerSecond每秒允许持续输入的数量</li>
<li>RepeatDelay触发持续输入生效的时间，持续摁下多久才会被认为是持续输入</li>
</ul>
<p><strong>RectTransform</strong> 继承了Transform每个UI组件上都有</p>
<p>Anchor锚点，默认为(0.5,0.5),PosX和PosY的距离是中心点Pivot相对于锚点Anchor的距离，左边的更改也是更改锚点的预设。<br>
当我们进行分辨率位置自适应的时候，是以Anchor为坐标原点计算的。当Anchor被分开是一个范围的时候，LeftTopRightBottom是UI元素相对于父元素的margin距离，会跟随父矩形拉伸而拉伸，一般只有背景图对齐的时候才会用。<br>
使用快捷设置的时候，按住Shift点击鼠标左键可以同时设置轴心点(相对自身矩形)；按住Alt点击鼠标左键可以同时设置位置。<br>
挂载到UI元素上的脚本使用<code>this.transform as RectTransform</code> 使用里氏替换原则父类装子类，类型转换一下就可以了。</p>
<h3 id="控件" tabindex="-1">控件 <a class="header-anchor" href="#控件" aria-label="Permalink to &quot;控件&quot;">&ZeroWidthSpace;</a></h3>
<p><strong>Panel</strong> 此组件就挂载了一个Image，基本上就是分组用的，可以设置遮罩射线等。<br>
<strong>Image</strong> 参数注意 RaycastTarget是否响应射线检测响应，会拦截射线后面的UI元素没有响应了。ImageType使用Sliced最好是在SpriteEditor中先规定九宫格的线，PixelsPerUnitMultiplier可以设置像素对应大小。Tiled经常会用来做填充。Filled经常用来做CD缓冲或者血条效果。</p>
<p><strong>RawImage</strong> 一般用作大图,不需要打图集的图片，Texture支持的格式比较多。UVRect是控制图的偏移，只展示图性能消耗小</p>
<p><strong>Text</strong> 字体过大RectTransform太小会直接消失，BestFit会自动调整字体大小，可以规定字体最大最小。注意 <strong>经常出现Text的RectTransform挡住按钮的情况，出问题检查一下</strong>。边缘线<code>Outline</code>和阴影<code>Shadow</code>组件可以添加效果。2020某版本后TMP是UGUI默认使用的文本组件</p>
<p><strong>Button</strong> 挂了一个Button和Image，子对象是Text，如果按钮的图片上已经有字了可以删除Text子对象。修改button的图一般是拿Button的Image改Sprite<br>
按钮的点击必须是<strong>在按钮内点击并抬起算一次</strong>。注意参数</p>
<ul>
<li>Navigation相当于是否参与在元素间移动焦点，点击下面的Visualize可以在场景窗口查看导航连线。</li>
<li>Transition
<ul>
<li>TragetGraphic控制的使用哪张图片作为按钮图片，</li>
<li>ColorHint剩余参数基本都是控制的是按钮的过渡颜色(选中，焦点，禁用)</li>
<li>SpriteSwap就是每种状态使用不同的Sprite</li>
<li>Animation没每种状态播放不同的动画，直接AutoGenerateAnimation生成一个状态机，事件也自动绑定，剩下的State绑定AnimationClip就好了</li>
</ul>
</li>
</ul>
<p><strong>Toggle</strong> 单选,多选控件。BackGround是未勾选的图片，勾选的图片是它的子对象CheckMark控制，更改这两个对象上的Image组件就可以。<br>
用一个空对象(任何对对象都可以)挂载<strong>ToggleGroup</strong>，在Toggle的Group选择此Group可以达到在Group内单选的效果。</p>
<p><strong>InputField</strong> 输入框，下面的对象Placeholder和Text，用来提示输入和存储输入的Text</p>
<ul>
<li><strong>TextComponent和Placeholder关联了子对象Placeholder和Text</strong></li>
<li>先看本体挂载的TMP
<ul>
<li>ContentType可以限制输入的东西，比如限制只能输入整数小数密码等等，LineType是不是允许多行等设置。</li>
<li>CaretBlinkRate CaretWidth CustomCaretColor光标闪烁频率，宽度，光标颜色</li>
</ul>
</li>
</ul>
<p><strong>Slider</strong> 滑动条下面的子对象有Background背景，Fill填充，Handle滑块 分别挂载了一个image组件组成的。分别绑定了连个React</p>
<ul>
<li>Direction 可以设置滑动条的方向</li>
<li>WholeNumbers只能选整数</li>
</ul>
<p><strong>ScrollBar</strong> 一般不单独用，会和ScrollView配合使用。自身挂载的Image是后面图片的背景，Handle是滑块的图。</p>
<ul>
<li>NumberOfSteps 可以改变这个滑块为多少次的滑动而不是平滑的值，0就是平滑滑动</li>
<li>Size滑块大小
<strong>ScrollView</strong> 滚动视图，但挂载组件名字是ScrollRect。子组件由Viewport，ScrollbarHorizontal，ScrollbarVertical三部分组成，后两个是俩ScrollBar。Viewport和ScrollView都挂载了一个Image。</li>
<li>Content 默认绑定你在Viewport下的Content，是所有要显示内容的父对象。Viewport多大显示的内容范围就有多大。</li>
<li>MovementType能不能拖动，会不会回弹，Elasticity使用回弹的时候控制回弹的系数，越大回弹越慢</li>
<li>Inertia使用惯性，DecelerationRate使用惯性拖动完之后会像有惯性一样移动一小点距离</li>
<li>ScrollSensitivity 滚动快慢系数</li>
<li>一般 人物装备只能单横或者竖，地图可以左右随便拖</li>
<li>如果不需要横或者竖向滚动，删除对应的Scrollbar后，记得绑定的地方Missing置为None，否则可能出bug
<strong>Dropdown</strong> 下拉列表由一个Label，Arrow，和Template(ScrollView)模板组成，调整Template模板样式，会自动根据模板样式和Options的内容生成下拉Item。自己挂载的Image可以修改背景图，修改Arrow的Image可以修改箭头，Lable的Text是在Options中规定的</li>
<li>Template关联的下拉列表，这下拉列表只负责展示，真正存储内容是在Options中的文本和图片，点击的item传对应的index value，可以通过代码获取value</li>
<li>CaptionText 关联的显示Label</li>
<li>CaptionImage 也可以关联显示图片</li>
<li>ItemText ItemImage 选中时获取当前所选选项的哪个子对象</li>
<li>value 当前选项的索引值，和下面的Options列表配合使用。</li>
<li>AlphaFadeSpeed 下拉表显示隐藏时，淡入淡出速度</li>
<li>#todo 自适应下拉</li>
</ul>
<h3 id="事件接口" tabindex="-1">事件接口 <a class="header-anchor" href="#事件接口" aria-label="Permalink to &quot;事件接口&quot;">&ZeroWidthSpace;</a></h3>
<p>可以让组件添加自定义的事件监听，比如给文本控件额外添加点击双击等。UGUI中提供了常用的事件接口。挂载的脚本类需要继承指定接口然后类中实现指定的方法，挂载的控件会自动调用，事件检测</p>
<ul>
<li><code>PointerEnterHandler</code>接口实现函数<code>OnPointerEnter</code> - 当指针进入对象时调用 （鼠标进入）移动设备上不存在</li>
<li><code>IPointerExitHandler</code>接口实现函数<code>OnPointerExit</code> - 当指针退出对象时调用 （鼠标离开）移动设备上不存在</li>
<li><code>IPointerDownHandler</code>接口实现函数<code>OnPointerDown</code> - 在对象上按下指针时调用 （按下）</li>
<li><code>IPointerUpHandler</code>接口实现函数<code>OnPointerUp</code> - 松开指针时调用（在指针正在点击的游戏对象上调用）（抬起）</li>
<li><code>IPointerClickHandler</code>接口实现函数<code>OnPointerClick</code> - 在同一对象上按下再松开指针时调用 （点击）</li>
<li><code>IBeginDragHandler</code>接口实现函数<code>OnBeginDrag</code> - 即将开始拖动时在拖动对象上调用 （开始拖拽）</li>
<li><code>IDragHandler</code>接口实现函数<code>OnDrag</code> - 发生拖动时在拖动对象上调用 （拖拽中）</li>
<li><code>IEndDragHandler</code>接口实现函数<code>OnEndDrag</code> - 拖动完成时在拖动对象上调用 （结束拖拽）<br>
携带的参数是继承BaseEventData的<code>PointerEventData</code>注意的参数看代码。<br>
使用组件EventTrigger挂载到组件上，把需要回调的函数统一声明在Panel的脚本中，拖进去选择自己想要回调的函数，同样能达到效果。但是参数是BaseEventData类型as类型转换一下就行。（也可以用代码但是我感觉会比较麻烦不写了</li>
</ul>
<details class="details custom-block"><summary>控件和事件API演示</summary>
<p>件和事件API演示</p>
<div class="language-Csharp vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">Csharp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Test1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> : </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">MonoBehaviour</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">IPointerClickHandler</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">IPointerEnterHandler</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">IPointerExitHandler</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> // 继承事件接口</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Start</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        //Image</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        Image</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> image</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> GetComponent</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Image</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>();  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        image.sprite </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Resources.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Load</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Sprite</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"t1"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  从Resources中加载资源替换掉sprite</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        RectTransform</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> rectTrans</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> this</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.transform </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">as</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> RectTransform</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  点进去看比transform多了多少属性  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        rectTrans.sizeDelta </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Vector2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">80</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, rectTrans.sizeDelta.y); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 不能直接修改某一个属性，只能一次性赋值  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        // Text</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        TextMeshProUGUI</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> t</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> GetComponent</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">TextMeshProUGUI</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>();  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        t.text </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "test"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        // Button</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        Button</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> btn</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> GetComponent</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Button</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>();  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        //  也可以RemoveListener(FunctionName)  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        //  RemoveAllListener() 无法移除Editor中拖拽的  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        btn.onClick.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">AddListener</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=></span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  //  委托绑定</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        {  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            Debug.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"click!"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        });</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        // toggle</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        Toggle</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> tog</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> GetComponent</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Toggle</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>();</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        tog.isOn </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  toggle是否被选中</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        tog.onValueChanged.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">AddListener</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">((</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">bool</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> on</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=></span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> // 绑定事件响应</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            Debug.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">$"toggle changed to {</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">on</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">}"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        }); </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        //  toggleGroup</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        ToggleGroup</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> g</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> GetComponent</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">ToggleGroup</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>();</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        g.allowSwitchOff </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        foreach</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Toggle</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> activeToggle</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> in</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> g.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">ActiveToggles</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  获得备选中toggle</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        {</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">            Text</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> text</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> activeToggle.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetComponentInChildren</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Text</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>();</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            Debug.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">$" toggle {</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">activeToggle</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">name</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">} label {</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">text</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">text</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">} on is {</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">activeToggle</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">isOn</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">}"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        // inputField</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        InputField</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> inf</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> this</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetComponent</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">InputField</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>();</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(inf.text);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        inf.text </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"112222222"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        inf.onValueChanged.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">AddListener</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">delegate</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> { </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(inf.text); }); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 值改变的时候获取内容</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        inf.onEndEdit.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">AddListener</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">delegate</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> { </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">$"结束输入 {</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">inf</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">text</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">}"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); }); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  按回车结束输入的时候</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        // Slider</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        Slider</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> sdr</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> this</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetComponent</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Slider</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>();</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(sdr.value); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 获取slider当前的值</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        sdr.value </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 0.5f</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  初始化一个值</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        sdr.onValueChanged.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">AddListener</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">((</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">v</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> { </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(v); }); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 接收一个float</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        // ScrollBar  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        Scrollbar</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> scb</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> this</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetComponent</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Scrollbar</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>();  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        scb.value </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1.0f</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        scb.size </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 0.2f</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        scb.onValueChanged.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">AddListener</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">((</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">v</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> { scb.value </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> v; }); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 监听事件</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        // ScrollView</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        ScrollRect</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> srr</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> this</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetComponent</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">ScrollRect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>();  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        srr.content.sizeDelta </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Vector2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">200</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">2</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">/</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">00</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 改变content大小，可以拖多少都是根绝它来  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        srr.normalizedPosition </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Vector2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0.5f</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 不需要计算横着没拖，竖着拖了一半的效果  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        srr.onValueChanged.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">AddListener</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">((</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">xypos</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{Debug.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(xypos);}); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 传入的是Vector2，表示横x竖y拖动到了那个地方(百分比</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        // Dropdown  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        Dropdown</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> dd</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> GetComponent</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Dropdown</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>();  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(dd.value); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 当前选中了哪个  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(dd.options[dd.value].text); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 用options获取当前选中的元素  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        dd.options.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Add</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Dropdown</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">OptionData</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">() { text </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "OP"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> }); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 通过代码去添加一个选项。可以传图片文字等  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        dd.onValueChanged.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">AddListener</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">((</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">int</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> value</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> { Debug.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">$"current choose index {</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">value</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">}"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); });</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    //  事件接口</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> OnPointerClick</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">PointerEventData</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> eventData</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">$"pointer info : "</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> +</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">              $"{</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">eventData</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">position</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">} "</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> +</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> //  屏幕座标系鼠标的位置</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">              $"{</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">eventData</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">pointerId</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">} "</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> +</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> //  左中右哪个键点击</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">              $"{</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">eventData</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">pressPosition</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">} "</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> +</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> // 屏幕座标系鼠标点击的位置</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">              $"{</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">eventData</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">delta</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">} "</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> +</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> // 拖动增量</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">              $"{</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">eventData</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">clickTime</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">} "</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> +</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> // 点击时系统时间</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">              $"{</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">eventData</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">clickCount</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">}"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  点了几次</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(eventData.pressEventCamera); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 最后一个点击事件关联的摄像机</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(eventData.enterEventCamera); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 最后一个鼠标进入事件关联的摄像机</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Debug.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"pointer click"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> OnPointerEnter</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">PointerEventData</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> eventData</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Debug.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"pointer enter"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> OnPointerExit</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">PointerEventData</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> eventData</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Debug.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"pointer leave"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br><span class="line-number">50</span><br><span class="line-number">51</span><br><span class="line-number">52</span><br><span class="line-number">53</span><br><span class="line-number">54</span><br><span class="line-number">55</span><br><span class="line-number">56</span><br><span class="line-number">57</span><br><span class="line-number">58</span><br><span class="line-number">59</span><br><span class="line-number">60</span><br><span class="line-number">61</span><br><span class="line-number">62</span><br><span class="line-number">63</span><br><span class="line-number">64</span><br><span class="line-number">65</span><br><span class="line-number">66</span><br><span class="line-number">67</span><br><span class="line-number">68</span><br><span class="line-number">69</span><br><span class="line-number">70</span><br><span class="line-number">71</span><br><span class="line-number">72</span><br><span class="line-number">73</span><br><span class="line-number">74</span><br><span class="line-number">75</span><br><span class="line-number">76</span><br><span class="line-number">77</span><br><span class="line-number">78</span><br><span class="line-number">79</span><br><span class="line-number">80</span><br><span class="line-number">81</span><br><span class="line-number">82</span><br><span class="line-number">83</span><br><span class="line-number">84</span><br><span class="line-number">85</span><br><span class="line-number">86</span><br><span class="line-number">87</span><br><span class="line-number">88</span><br><span class="line-number">89</span><br><span class="line-number">90</span><br><span class="line-number">91</span><br><span class="line-number">92</span><br><span class="line-number">93</span><br><span class="line-number">94</span><br><span class="line-number">95</span><br><span class="line-number">96</span><br><span class="line-number">97</span><br></div></div></details>
<p>#todo UGUI P16 P30 P32，有时间P25也做完，再有时间P27也做了
#todo UGUI P24 15min scroll三种模式，content和viewport的关系</p>
<h3 id="零散知识点" tabindex="-1">零散知识点 <a class="header-anchor" href="#零散知识点" aria-label="Permalink to &quot;零散知识点&quot;">&ZeroWidthSpace;</a></h3>
<p><strong>图集</strong> 设置详细用法在基础SpriteAltas中，UGUI可以不打就能用，NGUI需要先打图集才能用Edit-&gt;PorjectSettings-&gt;Editor-&gt;SpritePacker，Enabled是运行和构建都打，EnabledForBuilds是只构建打。<br>
创建一个SpriteAltas，因为是UI图集取消AllowRotation和TightPacking。<mark>相同图集的图堆叠，只会有一次DrawCall但是如果如果AABA这样堆叠打断了批处理，这样就多2次DrawCall</mark>，Text等也会打断，插入到中间且重叠会增加DrawCall</p>
<p><strong>坐标转换</strong> 使用这函数可以制作摇杆<code>RectTransformUtility.ScreenPointToLocalPointInRectangle</code>,此函数的作用是把屏幕上的点转换为以某元素为原点的点，下例</p>
<details class="details custom-block"><summary>制作摇杆</summary>
<p>作摇杆</p>
<div class="language-Csharp vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">Csharp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div></details>
<p><strong>遮罩</strong> 一般是和Image配合使用，在父对象上挂载Mask组件，想要被遮罩的Image勾上Maskable，子UI对象都会被遮罩。此时带Mask对象的Image组件关联的图片，透明的地方被遮罩，不透明的地方显示。<br>
注意: <strong>RectMask是通过RectTransform矩形判断停留在应用阶段，消耗低但是只能遮罩RectTransform的矩形部分</strong>。</p>
<p><strong>异形按钮</strong> 不规则的图片。</p>
<ul>
<li>按钮的<strong>Image子对象</strong>RectTransform覆盖的区域会把事件传递给父按钮组件。于是我们可以创建一个小的透明的Buttion，让不规则的图完全遮住他，把TargetGraphic关联到需要显示按钮图片的Sprite，然后再在这个按钮下创建多个Image拼出不太精确的此图片的轮廓。节省内存，笨但好用</li>
<li>使用透明度阈值检测，Button修改Sprite，把Sprite的ReadWriteEnable设为打开；设置这个Button-&gt;Image组件的<code>img.alphaHitTestMinimumThreshold = 0.1f;</code> 效果就是此图片透明通道必须有值的才能响应检测，而且不会拦截射线</li>
</ul>
<p><strong>世界物体检测</strong> <code>Camera</code>+<code>PhysicsRaycaster</code> 组件可以 让UI事件系统可以作用到 3D 物体上，Unity 的 <code>EventSystem</code> 在每一帧都会收集输入事件（鼠标、触屏）它会从输入位置（比如鼠标点的位置 Input.mousePosition）通过摄像机发出一条 物理射线。这条射线会和场景中的 Collider 进行物理检测。如果射中了某个带有 Collider 的物体，就会把这个物体当成 UI 事件的接收者。当然可以用Physics.Raycast手动写，但是用Camera+PhysicsRaycaster之后就可以直接在物体上实现UI的回调函数或者挂UI组件用了</p>
<h3 id="自动布局空间" tabindex="-1">自动布局空间 <a class="header-anchor" href="#自动布局空间" aria-label="Permalink to &quot;自动布局空间&quot;">&ZeroWidthSpace;</a></h3>
<p><strong>CanvasGroup</strong> 组件，给Panle控件挂载可以用来整体淡入淡出和禁用，主要参数Interactable是否启用不影响射线拦截 BlocksRaycasts 进行射线检测，如果不进行射线检测，那么如果后面有被遮挡的UI就可以接收到。IgnoreParentGroups忽略父级的CanvasGroup对自己的影响。</p>
<p>在UI元素的Inspector中，切换到LayoutProperties,里面的属性就是自动布局使用的属性不懂的问问GPT，其实不太重要，知道有影响就行。主要有两个<code>VerticalLayoutGroup</code>，<code>HorizontalLayoutGroup</code>组件参数差不多。</p>
<ul>
<li>padding盒模型不说了，Spacing 子元素间距，ChildAlignment 对齐方式</li>
<li>ControlChildSize自动缩放子对象以充满父对象的空间</li>
<li>UseChildScale如果不考虑子对象的缩放，一般子对象不会缩放知道就行。</li>
<li>ChildForceExpand平均分割空间每个空间固定填充一个元素</li>
<li>在子元素上添加<strong>LayoutElement</strong>组件可以规定元素跟随缩放的最小最大值
<ul>
<li>缩放到比Min小or比Preferred的大的时候元素不会继续跟随缩放<br>
<code>GridLayoutGroup</code>是网格布局组件，说点和上面两个参数不一样的。</li>
</ul>
</li>
<li>StartCorner 从哪个角开始排列</li>
<li>StartAxis 沿哪个轴排列</li>
<li>ChildAlignment 九宫格对齐方式</li>
<li>Constraint默认自适应，可以手动规定多少行和列
<code>ContentSizeFitter</code> 内容大小自适应组件，自动调整RectTransform大小适应，一般在Text或者配合其他组件使用，比如搭配ScrollContentView固定宽度然后根据物品多少自动设置高度</li>
<li>默认Unconstrained不调整。</li>
<li>Min使用LayoutPorperties中的min宽度</li>
<li><strong>Preferred Size</strong> 使用LayoutPorperties偏好宽度,可以根据子元素占据大小调整<br>
<code>AspectRatioFitter</code>这个了解就行，可以让元素自己根据宽或者高调整大小，可以自定义宽高比；也可以适应父对象。</li>
</ul>
<h3 id="源码简单解析" tabindex="-1">源码简单解析 <a class="header-anchor" href="#源码简单解析" aria-label="Permalink to &quot;源码简单解析&quot;">&ZeroWidthSpace;</a></h3>
<p><a href="https://www.bilibili.com/video/BV17W4y1d7dY" target="_blank" rel="noreferrer">UGUI源码深度剖析_哔哩哔哩_bilibili</a></p>
<p><a href="https://chatgpt.com/c/68bd1002-4110-8333-854d-03b2da9f803e" target="_blank" rel="noreferrer">ChatGPT</a></p>
<h3 id="常见case实现" tabindex="-1">常见Case实现 <a class="header-anchor" href="#常见case实现" aria-label="Permalink to &quot;常见Case实现&quot;">&ZeroWidthSpace;</a></h3>
<p>ViewContent下拉，在Content中使用ContentSizeFitter+LayoutGrop/GrideLayout动态下拉和伸缩
对照目录查漏补缺<a href="https://www.sikiedu.com/my/course/468" target="_blank" rel="noreferrer">Fetching Title#hno5</a></p>
<hr>
<h2 id="ui经验总结" tabindex="-1">UI经验总结 <a class="header-anchor" href="#ui经验总结" aria-label="Permalink to &quot;UI经验总结&quot;">&ZeroWidthSpace;</a></h2>
<div class="info custom-block"><p class="custom-block-title">[📝Note] UI经验总结</p>
<p>I经验总结
UI动态生成的思路。一个经典的权衡问题，提示框弹出来的时候，用代码控制是一个按钮还是两个按钮，如果是一个按钮就居中两个按钮就排布；或者做两个面板，分别调用。<br/>
如果使用动态生成的思路，应该写一个按钮栏父对象+HorizontalLayout，然后写一个按钮类，传入指定的文字图片Action返回按钮Object挂到按钮栏上。</p>
</div>
<blockquote>
<p>UI控件主要学习三个事情:UI控件使用，事件响应，分辨率自适应(大小 位置)<br>
做UI其实就三件事，<strong>数据准备-&gt;拼界面-&gt;写逻辑</strong><br>
在UI中一般都是用一个单独的根对象避免和其他的对象混合管理增加管理难度，命名最好有规范，比如<code>btnBegine</code>一看就知道这是啥，写C#写多了直接大驼峰罢<br>
先分层，业务逻辑和响应解耦</p>
</blockquote>
<hr>
<h2 id="unityeditor" tabindex="-1">UnityEditor <a class="header-anchor" href="#unityeditor" aria-label="Permalink to &quot;UnityEditor&quot;">&ZeroWidthSpace;</a></h2>
<p>Uinty自带的编辑器的UI，可以凑活用，做地图技能编辑器什么的。</p>
<p>这里面的API就是在街面上点击按钮操作的API，</p>
<p><code>EditorUserBuildSettings.SwitchActiveBuildTarget(BuildTargetGroup group, BuildTarget target);</code>
Editor中可以切换平台相当于File-&gt;BuildSettings-&gt;Platform-&gt;Android-&gt;SwitchPlatform。</p>
<div class="language-Csharp vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">Csharp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">MenuItem</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Tools/MyCustom"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)] </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 加在函数上创建自定义Editor菜单,至少有一个斜杠,只支持静态方法</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">EditorUtility.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">DisplayProgressBar</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Title"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Message"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, progress); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  进度条，想要变化那就改变progress(float 0-1f)的值和 标题 信息</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">EditorUtility.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">ClearProgressBar</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">EditorUtility.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">DisplayDialog</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Title"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Message"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"OK"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Cancel"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span>
<span class="line"></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Object</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[] </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">selectedAssets</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Selection.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetFiltered</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">typeof</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Object</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">), SelectionMode.DeepAssets);</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 获取在Project窗口中选中的资源</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">string</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> assetPath</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> AssetDatabase.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetAssetPath</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(asset); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 获取 资源的路径 格式是 Asset/xxx/xxx</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">AssetDatabase.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">CopyAsset</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(assetPath, destinationPath); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  Unity有自带的API可以在Asset中复制文件</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">AssetDatabase.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Refresh</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  刷新一下Editor界面</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br></div></div><p>#todo 没时间了，先跟着做用到啥算啥，有时间跟着<a href="https://www.bilibili.com/video/BV1YE411Z7nj/" target="_blank" rel="noreferrer">这个教程</a>摸个够用就行</p>
<h2 id="odin编辑器ui" tabindex="-1">odin编辑器UI <a class="header-anchor" href="#odin编辑器ui" aria-label="Permalink to &quot;odin编辑器UI&quot;">&ZeroWidthSpace;</a></h2>
<p>广受好评的编辑器UI框架，感觉完全是UnityEditor上位替代，有时间再摸
<a href="https://www.bilibili.com/video/BV1kwAkepEwp" target="_blank" rel="noreferrer">Unity使用Odin完成编辑器开发 【基础知识篇 第一节】中文 分组 颜色 按钮 条件_哔哩哔哩_bilibili</a></p>
<h2 id="uitoolkit" tabindex="-1">UIToolkit <a class="header-anchor" href="#uitoolkit" aria-label="Permalink to &quot;UIToolkit&quot;">&ZeroWidthSpace;</a></h2>
<hr>
<h2 id="资源和热更" tabindex="-1">资源和热更 <a class="header-anchor" href="#资源和热更" aria-label="Permalink to &quot;资源和热更&quot;">&ZeroWidthSpace;</a></h2>
<p>热更新实际上是无感下载，不重新安装APP的情况下更新内容，重启程序虚拟机或者重启游戏才生效，而不是正在运行着就把内存中的资源替换掉了。一般也不会让Rsource加载一半老的一半新的，这样就乱了。</p>
<ul>
<li>Resources不能热更，对资源的更新需要重新打包</li>
<li>AB可以热更，不需要对整个游戏重新打包，一般是对非代码资源的热更</li>
<li>HybridCLR或者LUA是对代码的热更</li>
</ul>
<h3 id="assetbundle" tabindex="-1">AssetBundle <a class="header-anchor" href="#assetbundle" aria-label="Permalink to &quot;AssetBundle&quot;">&ZeroWidthSpace;</a></h3>
<p><a href="https://blog.csdn.net/qq_39377889/article/details/137780681" target="_blank" rel="noreferrer">Unity笔记热更Part1：关于AB包与热更</a><br/>
<a href="https://blog.csdn.net/qq_39377889/category_12564389.html" target="_blank" rel="noreferrer">这个人</a>写的都不错。
手游或者需要联网热更的游戏一般不使用Resouce.Load，AB包就是干这个的，AB包不仅可以在本地还可以在网络上远程加载。<a href="https://docs.unity3d.com/cn/2022.3/Manual/AssetBundles-Workflow.html" target="_blank" rel="noreferrer">文档可以花小半天先看一遍</a>，更好理解在干什么虽然感觉翻译的有点依托。<br>
目前已经不在维护官方建议用Addressables替代，但是公司还在用所以要学。安装看<a href="https://github.com/Unity-Technologies/AssetBundles-Browser.git" target="_blank" rel="noreferrer">git repo</a>版本太高报错就把里面的Test删掉。</p>
<p>没东西打包会报错，在资源的Inspector-&gt;底部AssetBundle,第一个是打指定包的包名，第二个是拓展名别动。三个页签栏<br>
Configure: 查看所有待打包的文件,Inspect可以查看打好的文件的基本信息。<br>
Build:</p>
<ul>
<li>ClearFolder这次就会把上次打包的清了不清会攒垃圾但是能增量，CpoyToStreamingAssets就会把<strong>打好的包</strong>复制一份到StreamingAssets</li>
<li>Compress: 不压缩解压快体积大；LZMA体积最小解压最慢使用包中的一个资源会把这个包解压出来；LZ4用什么解压什么。</li>
<li>StrictMode：报错了就不打了</li>
</ul>
<p>Build好的东西会放到<code>AssetBundle(Assets同级)/{指定plantform文件夹}</code>下，打包好的格式是 二进制文件+元信息文件(Assets.manifest)，同时会生成一个<strong>文件夹同名的主包</strong><br>
<mark>同一AB包不能重复加载</mark> 否则报错，AB包异步加载完资源后会在下一帧渲染，卸载的时候如果选择不卸载资源，则只会卸载ab包但是已经实例化的资源仍旧会占内存<br>
包间的依赖，某个包内的资源引用其他资源，他们都会被自动打包进这个包里。 <mark>如果手动指定了不同包，引用不到了会报错</mark>  需要把依赖的ab包先加载了或者把他俩移动到同一个ab包里。<br>
利用主包可以获取包间依赖，挨个加载就是了，他没法获得某个资源依赖了几个包，只能从包级别获取，并且会<strong>自动递归返回完整的依赖列表</strong>，不需要手动处理多层包引用。<br>
但是 <mark>注意AB包不会自动处理循环依赖！</mark> A依赖了B，B依赖了C，AC在ab1中，B在ab2中；这样就循环依赖了会报错</p>
<div class="tip custom-block"><p class="custom-block-title">[💡Tip]</p>
<p>在打AB包的时候<strong>不能</strong>把场景和非场景资源打在同一个AssetBundle里，会报警告。<br/>
最佳实践场景单独一个包，其他资源随便分包</p>
</div>
<details class="details custom-block"><summary>AssetBundle基本使用</summary>
<p>ssetBundle基本使用</p>
<div class="language-Csharp vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">Csharp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> AssetBundleTest</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> : </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">MonoBehaviour</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    private</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> AssetBundle</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> ab</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Start</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {        </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        //  同步加载  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        ab </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> AssetBundle.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">LoadFromFile</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(Application.streamingAssetsPath</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"/"</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"testab"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        AudioClip</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> musica</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> ab.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">LoadAsset</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">AudioClip</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"伍佰 &#x26; China Blue - 你是我的花朵"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 使用泛型加载，如果使用名字加载可能会出现同名不同类型的冲突  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        musica </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> ab.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">LoadAsset</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"伍佰 &#x26; China Blue - 你是我的花朵"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">typeof</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">AudioClip</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">as</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> AudioClip</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 使用反射加载，用于在lua中不支持泛型的时候使用  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        AudioSource</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> aus</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> this</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetComponent</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">AudioSource</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>();  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        aus.clip </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> musica;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        aus.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Play</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        //  异步加载  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        StartCoroutine</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">LoadABAsync</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"testabasync"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Cube"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">));  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        // 包间依赖处理</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        GameObject</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> sph</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> ab.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">LoadAsset</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GameObject</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Sphere"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        //  使用主包获取依赖先加载，不然就会丢失材质洋红色</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        AssetBundle</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> abMain</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> AssetBundle.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">LoadFromFile</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(Application.streamingAssetsPath</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"/"</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"PC"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 加载主包</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        AssetBundleManifest</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> abManifest</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> abMain.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">LoadAsset</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">AssetBundleManifest</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"AssetBundleManifest"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        string</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[] </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">strs</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> abManifest.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetAllDependencies</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"testab"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">int</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> i</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x3C;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> strs.Length; i</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">++</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            AssetBundle.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">LoadFromFile</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(Application.streamingAssetsPath</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"/"</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">strs[i]);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        GameObject.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Instantiate</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(sph); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 这样应该就不是红色的</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    IEnumerator</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> LoadABAsync</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">string</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> abname</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">string</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> resname</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {        </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        // 异步加载包  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        AssetBundleCreateRequest</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> abcr</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> AssetBundle.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">LoadFromFileAsync</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(Application.streamingAssetsPath </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "/"</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> +</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> abname);  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        yield</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> abcr;  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        AssetBundleRequest</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> abq</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> abcr.assetBundle.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">LoadAssetAsync</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(resname,</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">typeof</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GameObject</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 加载资源，我估计后面正式用类型也得一块传进来  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        yield</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> abq;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        GameObject.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Instantiate</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(abq.asset </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">as</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> GameObject</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  把这东西拿出来  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    IEnumerator</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> UnloadAB</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">AssetBundle</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> ab_</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {        </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Debug.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"卸载此包"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        ab_.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Unload</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  卸载指定的ab包  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        AssetBundle.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">UnloadAllAssetBundles</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 参数是卸载的时候是否把当前使用的资产也卸掉  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        yield</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> break</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Update</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {        </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (Input.anyKeyDown)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        {            </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            Debug.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"检测键盘"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">            StartCoroutine</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">UnloadAB</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(ab));    </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        }  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br><span class="line-number">50</span><br><span class="line-number">51</span><br><span class="line-number">52</span><br><span class="line-number">53</span><br></div></div></details>
<h3 id="ab包热更新" tabindex="-1">AB包热更新 <a class="header-anchor" href="#ab包热更新" aria-label="Permalink to &quot;AB包热更新&quot;">&ZeroWidthSpace;</a></h3>
<div class="language-mermaid vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">mermaid</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">sequenceDiagram</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    participant UE as Unity编辑器</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    participant SRV as 资源服务器&#x3C;br/>(FTP/HTTP)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    participant GAME as 游戏客户端</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    UE->>SRV: 上传AB包和资源对比文件</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    GAME->>SRV: 下载资源对比文件</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    GAME->>GAME: 与本地文件对比&#x3C;br/>记录需要更新的AB包</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    loop 更新过程</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        GAME->>SRV: 下载需要更新的AB包</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        GAME->>GAME: 应用更新</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    end</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    GAME->>SRV: 下载更新资源对比文件为最新和远端保持一致</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    GAME->>GAME: 更新完成&#x3C;br/>进入游戏</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br></div></div><p>客户端的AB包都放在两个路径，一个是streamingAssetsPath中的默认AB包资源(移动端只读)，persistentDataPath有最新的(可读写)。在第一版发布的时候，会把AB包都打包进StreamingAssets，后续我可能在服务器上发布新资源，然后每次游戏启动检查对比。（我怎么感觉treamingAssetsPath和persistentDataPath设计的有点🦈臂</p>
<ul>
<li>不可能纯从streamingAssetsPath中读取，因为这样没法更新。</li>
<li>可以只从persistentDataPath中读取，这样首次启动需要把streamingAssetsPath<strong>转存</strong>到persistentDataPath一次，浪费空间。</li>
<li>优先读取persistentDataPath没有再找streamingAssetsPath，复杂但是不浪费。但是streamingAssetsPath中的AB包也落后的话那就会一直冗余在那。</li>
</ul>
<p>之后再整理一下，现在先放这，看希佬的代码，争取的是把长风的AB支持热更新</p>
<p>其实是个数据下载对比的活。
#todo 获取文件MD5 生成资源描述文件 名字 大小 md5。上传服务器，下载描述文件，对比本地，是否转存，哪些删除哪些需要下载哪些不需要下载，注意persistentDataPath和streamingAssetsPath</p>
<details class="details custom-block"><summary>AB包更新流程图</summary>
<p>B包更新流程图</p>
<div class="language-mermaid vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">mermaid</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">flowchart TD</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">A[开始] --> B{本地有&#x3C;br/>该AB包吗?}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">B --> C{本地有&#x3C;br/>该AB包吗?}</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">C -- 否 --> D[加入下载列表]</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">D --> E[使用TMP&#x3C;br/>后缀下载AB包]</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">E --> F[下载完成,&#x3C;br/>覆盖原文件]</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">C -- 是 --> G{MD5是否相同?}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">G -- 否 --> H[加入下载列表]</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">H --> E</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">G -- 是 --> I[无需更新]</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">B --> J{本地AB包&#x3C;br/>是否在&#x3C;br/>远程字典中?}</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">J -- 否 --> K[删除本地AB包]</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">J -- 是 --> L[保留本地AB包]</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">F --> M[处理下一个AB包]</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">I --> M</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">K --> M</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">L --> M</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">M --> B</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">B --> N[结束]</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br></div></div></details>
<h3 id="ab包框架设计" tabindex="-1">AB包框架设计 <a class="header-anchor" href="#ab包框架设计" aria-label="Permalink to &quot;AB包框架设计&quot;">&ZeroWidthSpace;</a></h3>
<p>跟着长风学的，这设计真的有点东西。 #todo 把代码梳理出来，加载配置，资源划分，处理，写入二进制。加载AB，GC 资源管理 调用</p>
<h3 id="addressables" tabindex="-1">Addressables <a class="header-anchor" href="#addressables" aria-label="Permalink to &quot;Addressables&quot;">&ZeroWidthSpace;</a></h3>
<p>基于AB包做的热更进一步封装，建议别跳过AB包因为公司用啥我用啥。</p>
<h3 id="yooasset-hybridclr" tabindex="-1">YooAsset+HybridCLR <a class="header-anchor" href="#yooasset-hybridclr" aria-label="Permalink to &quot;YooAsset+HybridCLR&quot;">&ZeroWidthSpace;</a></h3>
<p>很流行的一个资源热更的插件，多看文档<a href="https://www.yooasset.com/docs/Introduce" target="_blank" rel="noreferrer">YooAsset</a>超级详细。<br>
都是TuYoo搞出来的，东西很好用。这里只跟进一个SpaceShooter的Case先把三板斧流程搞通。<br>
在使用之前确保项目是ProjectSetting-&gt;Player-&gt;OtherSettings-&gt;Configuration : IL2CPP+NetFramework  <code>.NET Standard</code> 一些反射、动态特性不完全支持 HybridCLR 的补丁机制；AllowHttp也要打开，否则可能出现下载资源不成功。。</p>
<h4 id="yooasset必要背景" tabindex="-1">YooAsset必要背景 <a class="header-anchor" href="#yooasset必要背景" aria-label="Permalink to &quot;YooAsset必要背景&quot;">&ZeroWidthSpace;</a></h4>
<p>YooAsset使用前需要添加openupm的源，然后在PackageManager中搜索安装，顺便导入SpaceShooter示例。YooAsset依赖于ScriptableBuildPipeline而不是自带的AB包打包管线，不从PackageManager里安装的话不会自己安装。第一次启动可能会莫名报错，重启编辑器就好了</p>
<p>此时在Editor上面就多了一个YooAsset的菜单选项。 AssetArt Scanner/Reporter 用来扫描美术资产生成引用报告，包含依赖检测孤立资源依赖冲突公共引用等（用到再整理具体用法<br>
示例Boot中提供了四种模式</p>
<ul>
<li>编辑器下的模拟模式，不用打包只要引用正确可以在编辑器里运行</li>
<li>离线运行模式，打出包来没联网也可以本地StreamingAssets使用资源运行，把AB放到热更指定的文件夹里就可以</li>
<li>联机运行模式，必须联网从远程加载资源运行，需要填入网络地址</li>
<li>WebGL运行模式+自定义运行模式,暂时没用到</li>
</ul>
<h4 id="分包" tabindex="-1">分包 <a class="header-anchor" href="#分包" aria-label="Permalink to &quot;分包&quot;">&ZeroWidthSpace;</a></h4>
<p>YooAsset是把包和Object的GUID打在一块了，而不是单纯的路径，所以当Miss的时候可以Fix一下<br>
包层级分为Package/Group/Collectors，每个Collector会被打包成一个AB，它的<code>PackRule</code>可以决定按照类型资源目录等规则打成一个AB包。<br>
AutoCollectShaders可以自动收集Shaders到单独的一个包里，上来基本都默认就行。
使用EnableAddress可以分名字打包，不开启默认是分类型打包</p>
<h4 id="打包" tabindex="-1">打包 <a class="header-anchor" href="#打包" aria-label="Permalink to &quot;打包&quot;">&ZeroWidthSpace;</a></h4>
<p>打包之前需要创建一个全局默认配置，右键可以直接创建，可以规定资源文件夹是什么几乎所有的参数都在文档上有。此时包已经被打好了，先打到<code>Project/yoo</code>下并且在<code>StreamingAssets</code>下有一份。</p>
<ul>
<li>在每个包下（默认只有DefaultPackages）有以包名命名的文件里面记录了版本用来对比并更新资源</li>
<li>BuildinCatalog.json可以看到资源和GUID的绑定关系</li>
<li>如果是手动构建包放到远程，需要在本地做额外设置在这个文档底下有<a href="https://www.yooasset.com/docs/guide-editor/AssetBundleBuilder" target="_blank" rel="noreferrer">YooAsset资源构建</a> 本地需要保留<code>Pcakage Package_version.bytes</code>这两个文件，通过文档的代码生成 Catalog相关的俩文件，然后才能使用host模式更新
<ul>
<li>#todo 如果是自动生成打包为什么不用生成这俩东西？</li>
<li>选择的根目录要和全局默认配置里设置的一样，比如默认的就要是<code>StreamingAssets/yoo</code>在这里放Pcakage的俩文件生成Catalog，才能用。</li>
<li>编辑器下的AB包会下载到<code>Project/setting规定的目录</code>，打包之后的包下载到<code>persistentDataPath</code>对应的app文件夹
#todo space shooter代码再看吧，弄完了他会给带注释的工程</li>
</ul>
</li>
</ul>
<h4 id="hybirdclr必要背景" tabindex="-1">HybirdCLR必要背景 <a class="header-anchor" href="#hybirdclr必要背景" aria-label="Permalink to &quot;HybirdCLR必要背景&quot;">&ZeroWidthSpace;</a></h4>
<p>HybridCLR是做代码热更新的 多看官网文档<a href="https://www.hybridclr.cn/docs/intro" target="_blank" rel="noreferrer">HybridCLR</a>虽然很多也很详细。原先是涂游FocusGame团队开源的huatuo，后来涂游把这个名字收回了，<a href="https://code-philosophy.com/" target="_blank" rel="noreferrer">代码哲学</a>就吸取旧框架的经验，重新实现一版出来叫wolong。看这个热更新需要了解Unity的跨平台实现C#的AOT，HybirdCLR使用的是IL2CPP补充元数据的技术，可以自动生成Link.xml。</p>
<p>要求必须安装Mac/Win平台的IL2CPP Support，win需要安装VS2019+，mac要求MacOS版本 &gt;= 12 xcode版本 &gt;= 13。<br>
记得切换PlayerSetting，版本低于v4.0.0还要取消use internal GC。C++Configuration选择Debug方便调试，最后上线之前切换为Release。<br>
按照官网安装就好了，PackageManager安装好包之后此时在Editor上面就多了一个HybridCLR的菜单选项，第一次需要使用Installer安装il2cpp_plus+hybirdclr，他都帮你在ProjectSetting中配好了，安装就可以。<br>
此时项目目录下多了一个HybridCLRData文件夹，里面有帮你下载的2个包和把这两个包拼装起来符合你平台Editor的包。<br>
如果没有对热更新代码进行混淆，经过ILSpy之类的反编译工具，可以轻易还原近乎源码的C#代码，目前的开源代码混淆工具中，只有<a href="https://github.com/focus-creative-games/obfuz" target="_blank" rel="noreferrer">Obfuz</a>与Unity深度集成，并且完整支持HybridCLR。</p>
<h4 id="简单使用" tabindex="-1">简单使用 <a class="header-anchor" href="#简单使用" aria-label="Permalink to &quot;简单使用&quot;">&ZeroWidthSpace;</a></h4>
<ol>
<li>创建这样的目录结构，手动创建的热更程序集记得把<code>AutoReferenced</code>取消勾选，否则会被剔除报错。</li>
</ol>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>.</span></span>
<span class="line"><span>├── ConsoleToScreen.cs # 官网给的示例脚本内容，主要是接管打印日志</span></span>
<span class="line"><span>├── LoadDLL.cs # 用来加载DLL</span></span>
<span class="line"><span>├── MainScene.unity</span></span>
<span class="line"><span>└── hotreload_assmebly # 热更程序集文件夹</span></span>
<span class="line"><span>    ├── Hello.cs # 打印并初始化一个GameObject</span></span>
<span class="line"><span>    ├── Print.cs # 打印GameObject的名字</span></span>
<span class="line"><span>    └── hotreload.asmdef # 热更程序集</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br></div></div><ol start="2">
<li>在ProjectSettings-&gt;HybridCLRSettings-&gt;HotUpdateAssemblyDefinitions中添加你的热更Assmebly</li>
<li>在菜单-&gt;HybirdCLR-&gt;Generate-&gt;All，会在Assets下创建HybridCLRGenerate文件夹存放link.xml和AOTGenericReferences.cs
<ul>
<li>还在HybridCLRData文件夹下生成了HotUpdateDlls,找到你对应平台，里面有一堆DLL</li>
</ul>
</li>
<li>在菜单-&gt;HybirdCLR-&gt;CompileDll-&gt;ActivateBuildTarget构建此次的DLL编译完之后在<code>Project/HybridCLRData/HotUpdateDlls/TargetPlantform</code>下找到你定义的热更Assmebly的DLL</li>
<li>后缀名额外添加.bytes以便识别为二进制文件，然后通过加载脚本加载程序集反射是获取并执行入口函数</li>
<li>此时如果需要热更新代码，更改代码之后只需要重新GenerateAll+CompileDll，替换打包出来的DLL就完成热更了</li>
<li>挂载热更新脚本的资源（场景或prefab）必须打包成ab否则会丢失，在实例化资源前先加载热更新dll即可</li>
</ol>
<p><a href="https://www.bilibili.com/video/BV1Rz4y1n7JX/" target="_blank" rel="noreferrer">Unity大厂面试题xLua ILRuntime HybirdCLR热更方案比较</a><br/>
<a href="https://www.bilibili.com/video/BV1sQ4nzpEin" target="_blank" rel="noreferrer">有个案例逮空做一做</a></p>
<h3 id="xlua" tabindex="-1">Xlua <a class="header-anchor" href="#xlua" aria-label="Permalink to &quot;Xlua&quot;">&ZeroWidthSpace;</a></h3>
<p>lua热更就是三点 <a href="https://chenanbao.github.io/2018/07/30/Lua%E7%83%AD%E6%9B%B4%E6%96%B0%E6%A1%86%E6%9E%B6%E5%B7%AE%E5%BC%82/" target="_blank" rel="noreferrer">几个Lua热更新框架差异 - Bob的博客</a></p>
<ol>
<li>C# 与 Lua 的互相调用机制</li>
<li>Lua 文件的打包</li>
<li>网络传输校验
据说新立项的都在用hybirdclr。</li>
</ol>
<p>如果是已有项目使用xlua，把官方Assets里面<code>Plugins XLua</code>两个文件夹粘贴进项目里，如果需要热补丁还需要<code>Tools</code>文件夹，纯lua项目不需要<br>
github把官方项目复制下来，我使用的是M1的macos，需要编译出bundle文件，替换掉Plugins下面的xlua.bundle。</p>
<p>这是初始化XLua项目需要的目录，找时间看懂牢唐是怎么做的</p>
<div class="language-C vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">C</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Assets</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">├── Lua</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">│   ├── JsonUtility.lua # 封装的JSON序列化工具</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">│   ├── Main.lua # 入口文件</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">│   ├── Object.lua # 封装的OOP</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">│   └── SplitTools.lua # 字符串切分方法</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">└── Scripts</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    ├── Main.cs # 游戏主入口</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    └── ProjectBase</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        ├── ABMgr.cs # AB包管理器</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        ├── Base</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        │   ├── BaseManager.cs # </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        │   ├── SingletonAutoMono.cs</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        │   └── SingletonMono.cs</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        └── LuaMgr.cs</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br></div></div><div class="warning custom-block"><p class="custom-block-title">[⚠️Warning]</p>
<p>Xlua和AB打包有冲突，需要先清Xlua的ClearGenerateCode再打包</p>
</div>
<p>交互和交互细节
luabehavior
哪些地方用点哪些地方用冒号调用是有说法的。
lua用起来有点阴间的</p>
<p><a href="https://github.com/Tencent/xLua/blob/master/Assets/XLua/Doc/XLua%E6%95%99%E7%A8%8B.md" target="_blank" rel="noreferrer">xLua/Assets/XLua/Doc/XLua教程.md at master · Tencent/xLua · GitHub</a><br/>
<a href="https://github.com/Tencent/xLua/blob/master/Assets/XLua/Doc/configure.md" target="_blank" rel="noreferrer">xLua/Assets/XLua/Doc/configure.md at master · Tencent/xLua · GitHub</a></p>
<hr>
<h2 id="网络基础" tabindex="-1">网络基础 <a class="header-anchor" href="#网络基础" aria-label="Permalink to &quot;网络基础&quot;">&ZeroWidthSpace;</a></h2>
<p>看一眼最基本的使用收发请求判断响应等。
<a href="https://www.cnblogs.com/CatSevenMillion/p/17559799.html" target="_blank" rel="noreferrer">Unity 事件详解 - CatSevenMillion - 博客园</a><br/>
<a href="https://icongbao.com/2024/03/21/blog_articles/Unity%E4%B9%A6%E7%B1%8D/%E3%80%8AUnity3D%E7%BD%91%E7%BB%9C%E6%B8%B8%E6%88%8F%E5%AE%9E%E6%88%98%E3%80%8B/" target="_blank" rel="noreferrer">【Unity技术栈】《Unity3D网络游戏实战》笔记 | 聪头之家</a></p>
<p>唐老师网络19-40 61-68 网络实践1-8</p>
<hr>
<h2 id="基础架设" tabindex="-1">基础架设 <a class="header-anchor" href="#基础架设" aria-label="Permalink to &quot;基础架设&quot;">&ZeroWidthSpace;</a></h2>
<h3 id="对象池" tabindex="-1">对象池 <a class="header-anchor" href="#对象池" aria-label="Permalink to &quot;对象池&quot;">&ZeroWidthSpace;</a></h3>
<h3 id="fsm状态机" tabindex="-1">FSM状态机 <a class="header-anchor" href="#fsm状态机" aria-label="Permalink to &quot;FSM状态机&quot;">&ZeroWidthSpace;</a></h3>
<p>实际上也可以算一种设计模式，我在设计模式里面实现过，这里以<a href="https://github.com/gmhevinci/UniFramework" target="_blank" rel="noreferrer">gmhevinci/UniFramework</a>里面的状态机为例解析一下。</p>
<h3 id="单例模式" tabindex="-1">单例模式 <a class="header-anchor" href="#单例模式" aria-label="Permalink to &quot;单例模式&quot;">&ZeroWidthSpace;</a></h3>
<p>一般的单例模式可以直接<code>public static Airplane Instance = new Airplane();</code> 但Unity中的单例模式不行，在资源或者全局的管理等情况下，一般初始化动作放在awake中做，而不是start，如果把这些逻辑放在 <code>Start</code> 中，可能会导致其他脚本在 <code>Start</code> 中访问 <code>BGMusic.Instance</code> 时，<code>instance</code> 还没有被赋值，从而引发空引用异常。在MonoBehaviour的子类中不能直接new，先声明变量在Awake的时候<code>instance=this</code>
如果想让他游戏运行自动挂载，那就在Instance获得的时候检查是不是空的，如果是的话创建一个空的GameObject然后挂上去，这样就不用自己在场景上创建对象了<br>
过场景的时候单例MonoBehaviour的静态变量也是不会销毁的，在OnDestroy的时候赋值<code>instance = null;</code>销毁</p>
<p>在Unity游戏开发中滥用单例
单例之间互相依赖，耦合性过强，初始化顺序不可控容易爆炸，跨模块调用</p>
<ul>
<li>使用VContainer等DI注入代码，放RootSpace中减少单例</li>
<li>通过EvenetSystem解耦，会导致调用复杂可以权衡一下</li>
<li>全局共享的超级单例管理器，manager of managers</li>
</ul>
<p><a href="https://www.bilibili.com/video/BV1MfCRBCEq9/?t=11" target="_blank" rel="noreferrer">（中文语音）Unity中的更好单例模式_哔哩哔哩_bilibili</a></p>
<h3 id="常见项目结构" tabindex="-1">常见项目结构 <a class="header-anchor" href="#常见项目结构" aria-label="Permalink to &quot;常见项目结构&quot;">&ZeroWidthSpace;</a></h3>
<h4 id="mvc" tabindex="-1">MVC <a class="header-anchor" href="#mvc" aria-label="Permalink to &quot;MVC&quot;">&ZeroWidthSpace;</a></h4>
<p>Model：负责增删查改获取界面上需要的数据<br>
View：负责获取控件，更新控件信息，挂载到场景上<br>
Controller：负责业务逻辑处理。 界面事件监听，触发数据更新，触发界面更新<br>
MVC有几个变种，基本上M和V是一定要有的，中间的事件控制解耦可以用不同的方式去做。</p>
<h4 id="mvp" tabindex="-1">MVP <a class="header-anchor" href="#mvp" aria-label="Permalink to &quot;MVP&quot;">&ZeroWidthSpace;</a></h4>
<p>MVC还是会把data传递到View里面，MVP会切断View和Model的耦合，让Presenter处理一切。</p>
<h4 id="mvvm" tabindex="-1">MVVM <a class="header-anchor" href="#mvvm" aria-label="Permalink to &quot;MVVM&quot;">&ZeroWidthSpace;</a></h4>
<p>类似于前端的双向绑定，让ViewModel和V进行双向数据绑定，更新VM等同于更新V。
umvvm 和 <a href="https://github.com/vovgou/loxodon-framework" target="_blank" rel="noreferrer">GitHub - vovgou/loxodon-framework: An MVVM &amp; Databinding framework that can use C# and Lua to develop games</a></p>
<h4 id="mve" tabindex="-1">MVE <a class="header-anchor" href="#mve" aria-label="Permalink to &quot;MVE&quot;">&ZeroWidthSpace;</a></h4>
<p>用EventCenter事件中心来分发消息</p>
<h4 id="puremvc" tabindex="-1">PureMVC <a class="header-anchor" href="#puremvc" aria-label="Permalink to &quot;PureMVC&quot;">&ZeroWidthSpace;</a></h4>
<h3 id="vcontainer依赖注入" tabindex="-1">VContainer依赖注入 <a class="header-anchor" href="#vcontainer依赖注入" aria-label="Permalink to &quot;VContainer依赖注入&quot;">&ZeroWidthSpace;</a></h3>
<p>看石匠的<a href="https://github.com/hadashiA/VContainer" target="_blank" rel="noreferrer">GitHub - hadashiA/VContainer</a>
从官网安装<a href="https://vcontainer.hadashikick.jp/getting-started/installation" target="_blank" rel="noreferrer">VContainer</a>，</p>
<h3 id="messagepipe事件总线" tabindex="-1">MessagePipe事件总线 <a class="header-anchor" href="#messagepipe事件总线" aria-label="Permalink to &quot;MessagePipe事件总线&quot;">&ZeroWidthSpace;</a></h3>
<p>事件总线发布订阅框架，必须配合DI使用，Cysharp的三件套是可以一块配套使用的。</p>
<h3 id="gc基础" tabindex="-1">GC基础 <a class="header-anchor" href="#gc基础" aria-label="Permalink to &quot;GC基础&quot;">&ZeroWidthSpace;</a></h3>
<p>2019年<a href="https://www.bilibili.com/video/BV1aJ411t7N6/" target="_blank" rel="noreferrer">UUG高川-浅谈Unity内存管理</a> 也可以直接搜标题看文字版<br>
c与cpp
lua
c#
unity
<a href="https://www.bilibili.com/video/BV1r44y1z7X3/?p=2" target="_blank" rel="noreferrer">高川_哔哩哔哩_bilibili</a></p>
<h3 id="性能监控" tabindex="-1">性能监控 <a class="header-anchor" href="#性能监控" aria-label="Permalink to &quot;性能监控&quot;">&ZeroWidthSpace;</a></h3>
<p>这里只有工具的基本使用。
UnityProfiler
ProfileAnalyzer
MemoryProfiler
FrameDebugger</p>
<h3 id="日志" tabindex="-1">日志 <a class="header-anchor" href="#日志" aria-label="Permalink to &quot;日志&quot;">&ZeroWidthSpace;</a></h3>
<p>最佳实践<br>
根据环境调整日志级别：</p>
<div class="language-Csharp vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">Csharp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">#</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">if</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> DEVELOPMENT_BUILD</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> ||</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> UNITY_EDITOR</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    .MinimumLevel.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Debug</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">#</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">else</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    .MinimumLevel.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Warning</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">#</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">endif</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br></div></div><p>在重要流程中添加日志点：</p>
<ul>
<li>游戏启动和关闭</li>
<li>场景加载</li>
<li>玩家重要操作</li>
<li>网络请求和响应</li>
<li>资源加载和卸载</li>
</ul>
<p>上不上报，性能影响等</p>
<h3 id="单元测试" tabindex="-1">单元测试 <a class="header-anchor" href="#单元测试" aria-label="Permalink to &quot;单元测试&quot;">&ZeroWidthSpace;</a></h3>
<h2 id="牢唐小框架" tabindex="-1">牢唐小框架 <a class="header-anchor" href="#牢唐小框架" aria-label="Permalink to &quot;牢唐小框架&quot;">&ZeroWidthSpace;</a></h2>
<p>做独立游戏够用了，看的是某咩的plus版，唐门！</p>
<h2 id="打包与跨平台" tabindex="-1">打包与跨平台 <a class="header-anchor" href="#打包与跨平台" aria-label="Permalink to &quot;打包与跨平台&quot;">&ZeroWidthSpace;</a></h2>
<p>跨平台打包和SDK接入</p>
<h2 id="小型本地化" tabindex="-1">小型本地化 <a class="header-anchor" href="#小型本地化" aria-label="Permalink to &quot;小型本地化&quot;">&ZeroWidthSpace;</a></h2>
<h2 id="游戏算法" tabindex="-1">游戏算法 <a class="header-anchor" href="#游戏算法" aria-label="Permalink to &quot;游戏算法&quot;">&ZeroWidthSpace;</a></h2>
<p>非一般的算法，是游戏领域常见的算法，有些是引擎组件的原理有些是特殊的功能，除非瓶颈一般自己不手搓。</p>
<h3 id="kd树" tabindex="-1">KD树 <a class="header-anchor" href="#kd树" aria-label="Permalink to &quot;KD树&quot;">&ZeroWidthSpace;</a></h3>
<p>最近邻</p>
<h3 id="四叉树" tabindex="-1">四叉树 <a class="header-anchor" href="#四叉树" aria-label="Permalink to &quot;四叉树&quot;">&ZeroWidthSpace;</a></h3>
<p>碰撞检测</p>
<h3 id="八叉树" tabindex="-1">八叉树 <a class="header-anchor" href="#八叉树" aria-label="Permalink to &quot;八叉树&quot;">&ZeroWidthSpace;</a></h3>
<p>服务端地图推送性能优化</p>
<h3 id="a星寻路" tabindex="-1">A星寻路 <a class="header-anchor" href="#a星寻路" aria-label="Permalink to &quot;A星寻路&quot;">&ZeroWidthSpace;</a></h3>
<p>此为Unity内置的寻路的算法原理</p>
<h3 id="boids算法" tabindex="-1">boids算法 <a class="header-anchor" href="#boids算法" aria-label="Permalink to &quot;boids算法&quot;">&ZeroWidthSpace;</a></h3>
<p>生物集群模拟</p>
<h3 id="堆排序排行榜" tabindex="-1">堆排序排行榜 <a class="header-anchor" href="#堆排序排行榜" aria-label="Permalink to &quot;堆排序排行榜&quot;">&ZeroWidthSpace;</a></h3>
<hr>
<h2 id="常用插件" tabindex="-1">常用插件 <a class="header-anchor" href="#常用插件" aria-label="Permalink to &quot;常用插件&quot;">&ZeroWidthSpace;</a></h2>
<div class="tip custom-block"><p class="custom-block-title">[💡Tip] 系统自带的字体</p>
<p>统自带的字体
Win: <code>C:\Windows\Fonts</code><br>
Mac: 系统内置只读字体 <code>/System/Library/Fonts</code> 系统用户共享字体<code>/Library/Fonts</code> 用户字体<code>~/Library/Fonts</code><br>
Unity支持<strong>ttf</strong>和<strong>otf</strong>(TrueType字体和OpenType字体)</p>
</div>
<h3 id="tmp" tabindex="-1">TMP <a class="header-anchor" href="#tmp" aria-label="Permalink to &quot;TMP&quot;">&ZeroWidthSpace;</a></h3>
<p><a href="https://docs.unity3d.com/Packages/com.unity.textmeshpro@4.0/manual/index.html" target="_blank" rel="noreferrer">文档</a> Window-&gt;TextMeshPro-&gt;ImportTextMeshProEssentialResources中可手动导入。
默认改字体很蠢，需要在软件里面改<code>Editor\Data\Resources\PackageManager\BuiltInPackages\com.unity.ugui\Runtime\UI\Core\Text.cs</code>找代码改。<br>
使用TMP设置系统默认字体Edit-&gt;ProjectSettings-&gt;TextMeshPro-&gt;Settings-&gt;DefaultFontAsset选中你生成的字体这样全局就会有字体了</p>
<p>静态字符集，在Window-TextMeshPro-&gt;FontAssestCreater。用到静态字符集里没有的字会直接显示框。<br>
使用动态字符集右键-&gt;TextMeshPro-&gt;CreateFontAssest，用到啥他自己会找，但是动态的性能会差一些。<br>
TextMeshPro 的动态字体是通过图集的方式实现的，而它默认生成的图集是一张1024x1024的图， 集满了之后把没有的放到一个MissingCharacterList里，然后用方框代替。<br>
找到生成的Font资产-&gt;Inspector-&gt;GenerationSettings-&gt;MultiAtlasTextures勾上他自己会使用多张图集。</p>
<p>使用静态字符集+设置Fallback为动态字体，在性能和字符之间找到一个平衡。</p>
<h3 id="位图字体" tabindex="-1">位图字体 <a class="header-anchor" href="#位图字体" aria-label="Permalink to &quot;位图字体&quot;">&ZeroWidthSpace;</a></h3>
<p><a href="https://blog.csdn.net/qq_42296238/article/details/144661542" target="_blank" rel="noreferrer">【保姆级教学】Unity TextMeshPro 位图字体（位图字体使用建议）_unity 位图字体-CSDN博客</a></p>
<h3 id="文字动画" tabindex="-1">文字动画 <a class="header-anchor" href="#文字动画" aria-label="Permalink to &quot;文字动画&quot;">&ZeroWidthSpace;</a></h3>
<p><a href="https://flowus.cn/enjoygameclub/share/fa2ac259-3498-4282-8200-3caeef47caef?code=GQSAM5" target="_blank" rel="noreferrer">TextLife</a><br/>
<a href="https://www.bilibili.com/video/BV1phh9zSEAu/" target="_blank" rel="noreferrer">【Unity】精灵资产——轻松实现文字中插图片_哔哩哔哩_bilibili</a></p>
<h3 id="dotween" tabindex="-1">DoTween <a class="header-anchor" href="#dotween" aria-label="Permalink to &quot;DoTween&quot;">&ZeroWidthSpace;</a></h3>
<div class="tip custom-block"><p class="custom-block-title">[💡Tip] 补间动画</p>
<p>间动画
冷知识: UI 动画里常说的 补间动画(tween animation)其实是&quot;tween&quot;的直译<br/>
在传统动画里，动画师会先画好关键帧（Keyframe），比如第 1 帧和第 20 帧。但中间的 2~19 帧不可能都由主动画师亲自画，于是交给助理画“过渡帧”，这些过渡帧就叫 in-between frames，简称 tween。<br/>
中文翻译过来就是 补间（补充关键帧之间的内容）</p>
</div>
<p>UI动画插件,在UnityStore搜索Dotween，添加到我的资源；然后在Window-&gt;PackageManager-&gt;MyAsset-&gt;搜索Dotween，安装引入。
<a href="https://www.bilibili.com/video/BV1VX4y1i7vn/" target="_blank" rel="noreferrer">【Unity教程搬运】使用Unity UniTask异步等待实现流畅的硬币收集动画DOTween_哔哩哔哩_bilibili</a></p>
<p>Tools-&gt;Demigiant-&gt;DoTweenUtilityPanel-&gt;</p>
<h3 id="nodecanvas" tabindex="-1">NodeCanvas <a class="header-anchor" href="#nodecanvas" aria-label="Permalink to &quot;NodeCanvas&quot;">&ZeroWidthSpace;</a></h3>
<p>可视化状态机</p>
<h3 id="easysave" tabindex="-1">EasySave <a class="header-anchor" href="#easysave" aria-label="Permalink to &quot;EasySave&quot;">&ZeroWidthSpace;</a></h3>
<p>用于更方便持久话数据的插件，配合牢唐的持久化的几个封装好的使用很不错。<br>
依旧是安装找<a href="https://moodkie.com/easy-save-unity/" target="_blank" rel="noreferrer">官网</a>，先用学习版。从Window-&gt;EasySave3打开，Settings绝大部分需要改的你都能看懂，Types是支持保存的类型。AutoSave是挂载脚本到想要保存的物体上+<strong>场景单例</strong><code>ES3AutoSaveMgr</code>管理，他会保存脚本组件和其他所有的属性。一般<code>OnApplicationQuit</code>里写保存<code>Awake/Start</code>的里写加载。
能够保存大多数的可序列化对象，自定义类型需要加<code>Serializable</code>。保存时同文件内键不允许重复，保存Object类型的时候必须要有<code>EasySave3Manager</code><br>
有了管理器我们就可以保存一些包含引用的对象，Load的时候实际上是先加载然后把这个GameObject赋值给引用，而不是赋值给现有的引用对象，所以可能引用现在持有的对象会被顶掉，如果找不到就会重新创建这个对象放上去。<br>
如果想在原来的对象上加载数据应用更改，使用LoadInto方法。<br>
场景上的对象和持久化的对象引用关系是<code>EasySave3Manager</code>保存的，所以切换场景的时候可能会丢失</p>
<div class="warning custom-block"><p class="custom-block-title">[⚠️Warning]</p>
<p>游戏内的GameObject以及材质等，要慎用Load，一般是保存数据然后LoadInto到新对象上。对复杂对象只保存路径或 ID，不保存直接引用，运行时再实例化<br/>
每个UnityEngine.Object在保存时会分配一个内部引用ID，这个refID用来标识这个对象在内存中的唯一性。如果这个Key从A保存，上次加载的时候是加载到B身上，那么再次加载这个Key不显式传递被加载的引用，那么数据就会跑到B身上而不是A。<br/>
如果已经引用乱了找<code>EasySave3Manager</code>清空对应的引用</p>
</div>
<p><strong>AutoSave用法</strong><br>
为指定游戏对象添加<code>ES3AutoSave</code>脚本，在面板上勾选想要保存的数据，<code>EasySave3Manager</code>会自动保存你勾选的东西。自动保存支持的种类很多。<br>
自己规定的字段必须要声明序列化支持，想被Unity序列化但是不想被ES3序列化的使用<code>ES3NonSerializable</code>，想被ES3序列化但是不想被Unity序列化的使用<code>[ES3Serializable]</code>。<br>
在ES3窗口的AutoSave页中可以规定自动保存的全局设置，下面勾选自动保存的对象数据，不用一个一个挂载添加了。在一个Prefab上右键-&gt;EasySave3-&gt;EnableEasySaveForPrefabs这样对这个prefab的autosave操作就会应用到他所有的实例化对象上<br>
先在AutoSave中把Save和Load设置为None不自动触发，代码中使用<code>ES3AutoSaveMgr.Current.Save();</code>（Load）控制全局的保存和加载。<br>
利用这个我们可以做玩家自定义键盘位置的功能，对每个键盘点Transform进行AutoSave，下次打开加载。<br>
Prefab的自动保存设置之后，子物体不能在Inspector中进行自己单独的配置，需要在AutoSave页的Scene中单独配置
<strong>Settings的行为</strong>：<br>
开启加密不会影响之前已经保存的文件，再次加载还是加载未加密的会报错。<br>
在static中声明全局的<code>ES3Settings</code>，可以更改的东西和面板上差不多一一对应。<br>
保存加载的时候可以传入Path参数，使用自己制定的ES3文件，这样就可以制作多存档了。<code>LoadInto(&quot;key0&quot;,&quot;my/path/es3save.es3&quot;,GameObject)</code>，不同文件相当于不同的命名空间了，Key可以重复了。<br>
操作文件夹的时候一般习惯推荐以<code>/</code>结尾<br>
<strong>Types页</strong>
如果发现有类型不支持保存，去Types看一眼是不是没有默认配置上，配置某类型实际上会自动生成一段支持类型的代码，等他重新编译完就好了</p>
<details class="details custom-block"><summary>ES3的基本API</summary>
<p>S3的基本API</p>
<div class="language-Csharp vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">Csharp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> ES3SettingTest</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> static</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> ES3Settings</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> es3setting</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> ES3Settings</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Serializable</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Skill</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    [</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">ES3NonSerializable</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> string</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> skill_name</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> int</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> skill_atk</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> TestES</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> : </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">MonoBehaviour</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> int</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> hp</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 10</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> List</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">int</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">> </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">idlist</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> List</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">int</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">> { </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">4</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">5</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">};</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Dictionary</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">string</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">int</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">> </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">id_res</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Dictionary</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">string</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">int</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>();</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> List</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Skill</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">> </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">skills</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> List</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Skill</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>();</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Start</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        ES3.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">DirectoryExists</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"my/path/"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 判断文件夹是不是存在</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        ES3.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">DeleteDirectory</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"my/path/"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 文件夹 文件 Key都能删除</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        ES3.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">FileExists</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"SaveFile.es3"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 判断整个存档是不是存在</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (ES3.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">KeyExists</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"hp"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">))</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 不传就是判断默认存档中的hp是不是存在</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            hp </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> ES3.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Load</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">int</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"hp"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,hp); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 泛型加载并给个默认值，非null和default的时候可以帮助省略泛型，直接推断</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">            //  也可以加载之后as强转</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        ES3AutoSaveMgr.Current.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Save</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        ES3SettingTest.es3setting.encryptionType </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> ES3.EncryptionType.AES; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  和在面板上改一样,用的时候参数传递进去</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        ES3.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">CopyFile</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"SaveFile.es3"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"backup/SaveFile.es3"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 也支持CopyDirectory，用来备份存档</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> OnApplicationQuit</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        ES3.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Save</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"hp"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">this</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.hp); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 任意类型都可以Save(key,object)，很强</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br></div></div></details>
<h3 id="zlinq" tabindex="-1">Zlinq <a class="header-anchor" href="#zlinq" aria-label="Permalink to &quot;Zlinq&quot;">&ZeroWidthSpace;</a></h3>
<p>Cysharp开发的0内存分配代替Linq的库，不触发GC适合unity使用。</p>
<h3 id="cinemachine" tabindex="-1">Cinemachine <a class="header-anchor" href="#cinemachine" aria-label="Permalink to &quot;Cinemachine&quot;">&ZeroWidthSpace;</a></h3>
<p>摄像机运动的插件</p>
<h3 id="timeline" tabindex="-1">TimeLine <a class="header-anchor" href="#timeline" aria-label="Permalink to &quot;TimeLine&quot;">&ZeroWidthSpace;</a></h3>
<p>流畅的过场动画，Unity内置的插件。</p>
<h4 id="源码简单解析-1" tabindex="-1">源码简单解析 <a class="header-anchor" href="#源码简单解析-1" aria-label="Permalink to &quot;源码简单解析&quot;">&ZeroWidthSpace;</a></h4>
<h3 id="animncer" tabindex="-1">Animncer <a class="header-anchor" href="#animncer" aria-label="Permalink to &quot;Animncer&quot;">&ZeroWidthSpace;</a></h3>
<p>强化版的动画机插件
<a href="https://www.bilibili.com/video/BV1mM4y1v77o/" target="_blank" rel="noreferrer">【Lee哥】替换Unity内置动画！3D动画控制器 - Animancer Pro | Unity | 游戏开发 | 优秀工具_哔哩哔哩_bilibili</a></p>
<h3 id="嵌入网页" tabindex="-1">嵌入网页 <a class="header-anchor" href="#嵌入网页" aria-label="Permalink to &quot;嵌入网页&quot;">&ZeroWidthSpace;</a></h3>
<p>直接浏览器打开网页的话使用<code>Application.OpenURL(inputStr);</code> 。<br>
嵌入试了好几个插件，还是这个<code>3D WebView for Android™ (Web Browser)</code>好用<a href="https://assetstore.unity.com/packages/tools/gui/3d-webview-for-android-web-browser-137030" target="_blank" rel="noreferrer">AssetsStore</a>，说是for Android实际上都能用，本质上来说就是系统webview套壳。<br>
提供了Canvas和Image的的Prefab，支持交互支持全端，有示例场景，Prefab拖进去用就可以了，里面封好了一个RawImage。虽然资料不多但是不会的去翻文档问AI基本都能满足需求<br>
这东西实际上打包出来非常大，包了个Chrome进去多了三四百兆</p>
<details class="details custom-block"><summary>嵌入网页基础用法</summary>
<p>入网页基础用法</p>
<div class="language-Csharp vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">Csharp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> async</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> ShowPage</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">string</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> kw</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    string</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> url</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> $"https://www.baidu.com/s?wd=s{</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">kw</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">}"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    introWebViewPrefab.gameObject.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">SetActive</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 不知道为什么必须要有</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    await</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> introWebViewPrefab.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">WaitUntilInitialized</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//   必须await使用</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    introWebViewPrefab.WebView.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">LoadUrl</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(url);  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  直接加载，可以和正常浏览器一样</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br></div></div></details>
<h3 id="fmod" tabindex="-1">FMOD <a class="header-anchor" href="#fmod" aria-label="Permalink to &quot;FMOD&quot;">&ZeroWidthSpace;</a></h3>
<p>Unity的音频不支持热加载</p>
<h3 id="wwise" tabindex="-1">wwise <a class="header-anchor" href="#wwise" aria-label="Permalink to &quot;wwise&quot;">&ZeroWidthSpace;</a></h3>
<p>音频插件，可以做类似于雨大小这种精细一些的音效控制</p>
<h2 id="基础逆向与反作弊" tabindex="-1">基础逆向与反作弊 <a class="header-anchor" href="#基础逆向与反作弊" aria-label="Permalink to &quot;基础逆向与反作弊&quot;">&ZeroWidthSpace;</a></h2>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[AI和自动化暂存]]></title>
            <link>http://ooowl.fun/blogs/AI%E5%92%8C%E8%87%AA%E5%8A%A8%E5%8C%96/AI%E5%92%8C%E8%87%AA%E5%8A%A8%E5%8C%96%E6%9A%82%E5%AD%98.html</link>
            <guid isPermaLink="false">http://ooowl.fun/blogs/AI%E5%92%8C%E8%87%AA%E5%8A%A8%E5%8C%96/AI%E5%92%8C%E8%87%AA%E5%8A%A8%E5%8C%96%E6%9A%82%E5%AD%98.html</guid>
            <pubDate>Tue, 01 Oct 2024 00:00:00 GMT</pubDate>
            <content:encoded><![CDATA[<h1 id="ai和自动化暂存" tabindex="-1">AI和自动化暂存 <a class="header-anchor" href="#ai和自动化暂存" aria-label="Permalink to &quot;AI和自动化暂存&quot;">&ZeroWidthSpace;</a></h1><p class="article-meta">创建于 2024年10月1日 08:00:00 · 约52字</p>
<p>轻连 n8n 钉钉连接器 dify Ollama
【6.6K Star、220K 下载！这款开源 AI 神器迎来一大波功能更新！】 <a href="https://www.bilibili.com/video/BV1fyJhzHEb7/" target="_blank" rel="noreferrer">https://www.bilibili.com/video/BV1fyJhzHEb7/</a></p>
<p>测试测试123</p>
<p>搞出自己的工程的Prompt</p>
<p><a href="https://mp.weixin.qq.com/s/GjPUDjjx2XmZX-G5qDC6eA" target="_blank" rel="noreferrer">微信公众平台</a></p>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[项目管理]]></title>
            <link>http://ooowl.fun/blogs/%E4%BB%A3%E7%A0%81%E4%B9%8B%E5%A4%96/%E9%A1%B9%E7%9B%AE%E7%AE%A1%E7%90%86.html</link>
            <guid isPermaLink="false">http://ooowl.fun/blogs/%E4%BB%A3%E7%A0%81%E4%B9%8B%E5%A4%96/%E9%A1%B9%E7%9B%AE%E7%AE%A1%E7%90%86.html</guid>
            <pubDate>Sun, 29 Sep 2024 11:15:21 GMT</pubDate>
            <description><![CDATA[千里之堤，溃于蚁穴。项目管理不是单纯的技术问题，是自己或团队不同环节配合起来的规范，个人主要从做事配合效率的角度出发整理能想到的。]]></description>
            <content:encoded><![CDATA[<h1 id="项目管理" tabindex="-1">项目管理 <a class="header-anchor" href="#项目管理" aria-label="Permalink to &quot;项目管理&quot;">&ZeroWidthSpace;</a></h1><p class="article-meta">创建于 2024年9月29日 19:15:21 · 约536字</p>
<p>千里之堤，溃于蚁穴。项目管理不是单纯的技术问题，是自己或团队不同环节配合起来的规范，个人主要从做事配合效率的角度出发整理能想到的。</p>
<h2 id="技术编码规范" tabindex="-1">技术编码规范 <a class="header-anchor" href="#技术编码规范" aria-label="Permalink to &quot;技术编码规范&quot;">&ZeroWidthSpace;</a></h2>
<p>异常处理的最佳实践是只捕获自己能处理的异常，其它的都让它抛出去
模块之间的依赖应该为树状的而不是图，控制好边界
关注编程环境，刻意创造出允许高效试错的“代码乐园”
做一个项目需要注意的是什么:
各个组件和中间件的要版本固定和记录
系统版本要兼容一致
框架版本
依赖的包版本</p>
<p>写代码看代码时多想想，think twice，code once。</p>
<ul>
<li>编码标准</li>
<li>命名约定</li>
<li>设计模式</li>
<li>注释</li>
<li>用到的测试脚本和测试用例等</li>
<li>为什么使用特定的设计模式？</li>
<li>为什么使用特定的语言？</li>
<li>缺点是什么？它可以与你的代码一起使用吗？</li>
<li>这些代码是否易于维护？</li>
</ul>
<p>工具层面能解决的安全问题，不要写到手册里。</p>
<p>如果有使用字符串匹配的地方大小写一定要校验 ，比如兑换码可能出现多次兑换的情况
<a href="https://github.com/itchaox/annotree?tab=readme-ov-file" target="_blank" rel="noreferrer">GitHub - itchaox/annotree: Generate folder directory annotation tree | 生成文件夹目录注释树</a></p>
<h2 id="命名" tabindex="-1">命名 <a class="header-anchor" href="#命名" aria-label="Permalink to &quot;命名&quot;">&ZeroWidthSpace;</a></h2>
<p>这种事情最好交给强迫症来做</p>
<table tabindex="0">
<thead>
<tr>
<th>常见</th>
<th>示例</th>
<th>常见用途(不同语言可能不一样)</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>PascalCase</strong> 大驼峰</td>
<td><code>UserProfile</code>, <code>GetUserInfo</code></td>
<td>类名、结构体、枚举、公共方法</td>
</tr>
<tr>
<td><strong>camelCase</strong>小驼峰</td>
<td><code>userProfile</code>, <code>getUserInfo</code></td>
<td>变量名、函数参数、方法名</td>
</tr>
<tr>
<td><strong>snake_case</strong>蛇形</td>
<td><code>user_profile</code>, <code>get_user_info</code></td>
<td>Python 变量/函数、数据库字段名</td>
</tr>
<tr>
<td><strong>MACRO_CASE</strong>常量命名法</td>
<td><code>MAX_SIZE</code>, <code>DEFAULT_TIMEOUT</code></td>
<td>常量、宏定义（C/C++）、环境变量</td>
</tr>
</tbody>
</table>
<h2 id="codereview" tabindex="-1">CodeReview <a class="header-anchor" href="#codereview" aria-label="Permalink to &quot;CodeReview&quot;">&ZeroWidthSpace;</a></h2>
<p><a href="https://www.cnblogs.com/CodeBlogMan/p/18278962" target="_blank" rel="noreferrer">【团队建设】如何做好团队开发中的 CodeReview（代码评审）？ - CodeBlogMan - 博客园</a>
#todo 这个人的博客也挺有意思，多看看其他文章也有好处</p>
<h2 id="游戏项目规范" tabindex="-1">游戏项目规范 <a class="header-anchor" href="#游戏项目规范" aria-label="Permalink to &quot;游戏项目规范&quot;">&ZeroWidthSpace;</a></h2>
<details class="details custom-block"><summary>给起名困难症用的</summary>
<p>起名困难症用的</p>
<table tabindex="0">
<thead>
<tr>
<th>动作分类</th>
<th>用途</th>
<th>示例</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>创建/销毁</strong></td>
<td></td>
<td></td>
</tr>
<tr>
<td>Create</td>
<td>创建实例，常用于实例化方法和工厂方法的命名</td>
<td>CreateInstance</td>
</tr>
<tr>
<td>Initialize</td>
<td>初始化实例的属性和设置，也可作为类方法初始化</td>
<td>InitializeInstance, Initialize</td>
</tr>
<tr>
<td>Load</td>
<td>加载配置，根据配置创建内容</td>
<td>LoadFromConfig</td>
</tr>
<tr>
<td>Destroy</td>
<td>销毁实例，常用于析构方法</td>
<td>DestroyInstance</td>
</tr>
<tr>
<td>Uninitialize</td>
<td>清理实例的属性和设置，通常与 Initialize 对应</td>
<td>UninitializeInstance, Uninitialize</td>
</tr>
<tr>
<td><strong>获取/设置</strong></td>
<td></td>
<td></td>
</tr>
<tr>
<td>Get</td>
<td>取属性或通用获取</td>
<td>GetStartTime</td>
</tr>
<tr>
<td>Fetch</td>
<td>通过网络请求获取内容</td>
<td>FetchAllUsers</td>
</tr>
<tr>
<td>Calculate</td>
<td>通过计算获取内容</td>
<td>CalculateTotalAmount</td>
</tr>
<tr>
<td>Read</td>
<td>读取（多用于文件、配置等）</td>
<td>ReadFile, ReadConfig</td>
</tr>
<tr>
<td>Query</td>
<td>查询</td>
<td>QueryRemainingAmount</td>
</tr>
<tr>
<td>Find</td>
<td>查找（多用于数据库、集合等），与 search 相似</td>
<td>FindOrder</td>
</tr>
<tr>
<td>Receive</td>
<td>接收（多用于文件、消息等）</td>
<td>ReceiveNewMessage</td>
</tr>
<tr>
<td>Pull</td>
<td>拉取</td>
<td>PullLastestSourceCode</td>
</tr>
<tr>
<td>Set</td>
<td>设置属性或通用设置</td>
<td>SetStartTime</td>
</tr>
<tr>
<td>Write</td>
<td>写入（文件/配置等）</td>
<td>WriteFile, WriteConfig</td>
</tr>
<tr>
<td>Put</td>
<td>放入</td>
<td>PutUserWithId</td>
</tr>
<tr>
<td>Push</td>
<td>存入，推送（通知）</td>
<td>PushNotification</td>
</tr>
<tr>
<td><strong>更新</strong></td>
<td></td>
<td></td>
</tr>
<tr>
<td>Reset</td>
<td>强调重置（标记、状态）</td>
<td>ResetTimer</td>
</tr>
<tr>
<td>Refresh</td>
<td>刷新（多用于页面、缓存等）</td>
<td>RefreshCurrentPage</td>
</tr>
<tr>
<td>Update</td>
<td>更新（多用于配置、状态等）</td>
<td>UpdateUserSetting</td>
</tr>
<tr>
<td><strong>添加/移除</strong></td>
<td></td>
<td></td>
</tr>
<tr>
<td>Add</td>
<td>通用添加方法命名</td>
<td>AddNewStudent</td>
</tr>
<tr>
<td>Append</td>
<td>强调在尾部添加（追加）</td>
<td>AppendCharacter</td>
</tr>
<tr>
<td>Insert</td>
<td>强调插入（可在任意位置）</td>
<td>InsertCharacter</td>
</tr>
<tr>
<td>Delete</td>
<td>表示删除，与 Remove 相近</td>
<td>DeleteDirectory</td>
</tr>
<tr>
<td>Remove</td>
<td>表示移除，与 Delete 相近</td>
<td>RemoveInvalidDeals</td>
</tr>
<tr>
<td><strong>启动/停止</strong></td>
<td></td>
<td></td>
</tr>
<tr>
<td>Open</td>
<td>开启（多用于开启状态、打开文件等）</td>
<td>OpenEnhanceMode</td>
</tr>
<tr>
<td>Start</td>
<td>开始（强调开始某个流程）</td>
<td>StartPortListening</td>
</tr>
<tr>
<td>Launch</td>
<td>发动/启动（多用于启动程序、服务）</td>
<td>LaunchAssistService</td>
</tr>
<tr>
<td>Close</td>
<td>关闭（多用于关闭状态、关闭文件等）</td>
<td>CloseEnhanceMode</td>
</tr>
<tr>
<td>Stop</td>
<td>停止（强调流程的终止）</td>
<td>StopPortListening</td>
</tr>
<tr>
<td>Pause</td>
<td>暂停（强调流程暂停，可能后续继续）</td>
<td>PausePageLoading</td>
</tr>
<tr>
<td>Finish</td>
<td>完成（强调流程的完成）</td>
<td>FinishRequesting</td>
</tr>
<tr>
<td><strong>集合处理</strong></td>
<td></td>
<td></td>
</tr>
<tr>
<td>Filter</td>
<td>过滤、筛选（按条件）</td>
<td>FilterByName</td>
</tr>
<tr>
<td>Merge</td>
<td>合并（有时带合并规则）</td>
<td>MergeTwoConfig</td>
</tr>
<tr>
<td>Concat</td>
<td>拼接（直接在结尾添加）</td>
<td>ConcatToArray</td>
</tr>
<tr>
<td>Split</td>
<td>分割</td>
<td>SplitInput</td>
</tr>
<tr>
<td>Deduplicate</td>
<td>去重（去除完全相同的项）</td>
<td>DeduplicateList</td>
</tr>
<tr>
<td>Reverse</td>
<td>颠倒、反向排列</td>
<td>ReverseRecord</td>
</tr>
<tr>
<td>Sort</td>
<td>排序（有时带排序规则）</td>
<td>SortDealsByAmount</td>
</tr>
<tr>
<td>Fill</td>
<td>填充（一般会覆盖）</td>
<td>FillAmountList</td>
</tr>
<tr>
<td><strong>业务处理</strong></td>
<td></td>
<td></td>
</tr>
<tr>
<td>Parse</td>
<td>解析（成格式或提取内容）</td>
<td>ParseFromJson, ParseResult</td>
</tr>
<tr>
<td>Analyse</td>
<td>分析（不能简单获取）</td>
<td>AnalyseLocation</td>
</tr>
<tr>
<td>Convert</td>
<td>类型转换（一种类型转另一种）</td>
<td>ConvertToString</td>
</tr>
<tr>
<td>Format</td>
<td>格式化数据</td>
<td>FormatToLocaleString</td>
</tr>
<tr>
<td>Validate</td>
<td>合法性/有效性校验</td>
<td>ValidateUserInputs</td>
</tr>
<tr>
<td>Ensure</td>
<td>期待值的校验</td>
<td>EnsureUserAge</td>
</tr>
<tr>
<td>Compose</td>
<td>组成（多项内容组成一个结果）</td>
<td>ComposeMessage</td>
</tr>
<tr>
<td>Encode</td>
<td>编码（依赖约定格式）</td>
<td>EncodeUrl</td>
</tr>
<tr>
<td>Decode</td>
<td>解码（依赖约定格式）</td>
<td>DecodeUrl</td>
</tr>
<tr>
<td>Encrypt</td>
<td>数据加密（依赖约定算法）</td>
<td>EncryptContent</td>
</tr>
<tr>
<td>Decrypt</td>
<td>数据解密（依赖约定算法）</td>
<td>DecryptContent</td>
</tr>
<tr>
<td>Backup</td>
<td>备份（注意拷贝方式，避免误导）</td>
<td>BackupUserSettings</td>
</tr>
<tr>
<td>Restore</td>
<td>恢复</td>
<td>RestoreUserSettings</td>
</tr>
<tr>
<td>Import</td>
<td>导入（按特定格式文件转换）</td>
<td>ImportFromFile</td>
</tr>
<tr>
<td>Export</td>
<td>导出（转换成特定格式文件）</td>
<td>ExportToFile</td>
</tr>
<tr>
<td>Compress</td>
<td>压缩（依赖约定算法）</td>
<td>CompressOversizedFile</td>
</tr>
<tr>
<td>Decompress</td>
<td>解压缩（依赖约定算法）</td>
<td>DecompressOversizedFile</td>
</tr>
</tbody>
</table>
</details>
<p><a href="https://github.com/gscheartA/Improve-your-code" target="_blank" rel="noreferrer">GitHub - gscheartA/Improve-your-code: 《改善丑陋的代码》——红桃A士视频分享系列</a></p>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[基本硬件知识]]></title>
            <link>http://ooowl.fun/blogs/%E4%BB%A3%E7%A0%81%E4%B9%8B%E5%A4%96/%E5%9F%BA%E6%9C%AC%E7%A1%AC%E4%BB%B6%E7%9F%A5%E8%AF%86.html</link>
            <guid isPermaLink="false">http://ooowl.fun/blogs/%E4%BB%A3%E7%A0%81%E4%B9%8B%E5%A4%96/%E5%9F%BA%E6%9C%AC%E7%A1%AC%E4%BB%B6%E7%9F%A5%E8%AF%86.html</guid>
            <pubDate>Sun, 29 Sep 2024 00:06:11 GMT</pubDate>
            <description><![CDATA[独家整理：学习服务器必须掌握的PCIE知识点你都了解吗_哔哩哔哩_bilibili]]></description>
            <content:encoded><![CDATA[<h1 id="基本硬件知识" tabindex="-1">基本硬件知识 <a class="header-anchor" href="#基本硬件知识" aria-label="Permalink to &quot;基本硬件知识&quot;">&ZeroWidthSpace;</a></h1><p class="article-meta">创建于 2024年9月29日 08:06:11 · 约488字</p>
<p><a href="https://www.bilibili.com/video/BV18X4y1o7mp" target="_blank" rel="noreferrer">独家整理：学习服务器必须掌握的PCIE知识点你都了解吗_哔哩哔哩_bilibili</a></p>
<h2 id="cheatsheet速查" tabindex="-1">CheatSheet速查 <a class="header-anchor" href="#cheatsheet速查" aria-label="Permalink to &quot;CheatSheet速查&quot;">&ZeroWidthSpace;</a></h2>
<table tabindex="0">
<thead>
<tr>
<th>组装机主板</th>
<th></th>
<th>品牌笔记本</th>
<th></th>
<th>品牌台式机</th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td>主板品牌</td>
<td>启动按键</td>
<td>笔记本品牌</td>
<td>启动按键</td>
<td>台式机品牌</td>
<td>启动按键</td>
</tr>
<tr>
<td>华硕主板</td>
<td>F8</td>
<td>联想笔记本</td>
<td>F12</td>
<td>联想台式机</td>
<td>F12</td>
</tr>
<tr>
<td>技嘉主板</td>
<td>F12</td>
<td>宏基笔记本</td>
<td>F12</td>
<td>惠普台式机</td>
<td>F12</td>
</tr>
<tr>
<td>微星主板</td>
<td>F11&amp;Del</td>
<td>华硕笔记本</td>
<td>ESC</td>
<td>宏基台式机</td>
<td>F12</td>
</tr>
<tr>
<td>映泰主板</td>
<td>F9</td>
<td>惠普笔记本</td>
<td>F9</td>
<td>戴尔台式机</td>
<td>ESC</td>
</tr>
<tr>
<td>梅捷主板</td>
<td>ESC或F12</td>
<td>联想Thinkpad</td>
<td>F12</td>
<td>神舟台式机</td>
<td>F12</td>
</tr>
<tr>
<td>七彩虹主板</td>
<td>ESC或F11</td>
<td>戴尔笔记本</td>
<td>F12/F2</td>
<td>华硕台式机</td>
<td>F8</td>
</tr>
<tr>
<td>华擎主板</td>
<td>F11</td>
<td>神舟笔记本</td>
<td>F12</td>
<td>方正台式机</td>
<td>F12</td>
</tr>
<tr>
<td>斯巴达克主板</td>
<td>ESC</td>
<td>东芝笔记本</td>
<td>F12</td>
<td>清华同方台式机</td>
<td>F12</td>
</tr>
<tr>
<td>昂达主板</td>
<td>F11</td>
<td>三星笔记本</td>
<td>F12</td>
<td>海尔台式机</td>
<td>F12</td>
</tr>
<tr>
<td>双敏主板</td>
<td>ESC</td>
<td>IBM笔记本</td>
<td>F12</td>
<td>明基台式机</td>
<td>F8</td>
</tr>
<tr>
<td>翔升主板</td>
<td>F10</td>
<td>富士通笔记本</td>
<td>F12</td>
<td></td>
<td></td>
</tr>
<tr>
<td>精英主板</td>
<td>ESC或F11</td>
<td>海尔笔记本</td>
<td>F12</td>
<td></td>
<td></td>
</tr>
<tr>
<td>冠盟主板</td>
<td>F11或F12</td>
<td>方正笔记本</td>
<td>F12</td>
<td></td>
<td></td>
</tr>
<tr>
<td>富士康主板</td>
<td>ESC或F12</td>
<td>清华同方笔记本</td>
<td>F12</td>
<td></td>
<td></td>
</tr>
<tr>
<td>顶星主板</td>
<td>F11或F12</td>
<td>微星笔记本</td>
<td>F11</td>
<td></td>
<td></td>
</tr>
<tr>
<td>铭瑄主板</td>
<td>ESC或F11</td>
<td>明基笔记本</td>
<td>F9</td>
<td></td>
<td></td>
</tr>
<tr>
<td>盈通主板</td>
<td>F8</td>
<td>技嘉笔记本</td>
<td>F12</td>
<td></td>
<td></td>
</tr>
<tr>
<td>捷波主板</td>
<td>ESC</td>
<td>Gateways笔记本</td>
<td>F12</td>
<td></td>
<td></td>
</tr>
<tr>
<td>Intel主板</td>
<td>F12</td>
<td>eMachines笔记本</td>
<td>F12</td>
<td></td>
<td></td>
</tr>
<tr>
<td>杰微主板</td>
<td>ESC或F8</td>
<td>索尼笔记本</td>
<td>ESC</td>
<td></td>
<td></td>
</tr>
<tr>
<td>致铭主板</td>
<td>F12</td>
<td>苹果笔记本</td>
<td>开机长按'option'</td>
<td></td>
<td></td>
</tr>
<tr>
<td>磐英主板</td>
<td>ESC</td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>磐正主板</td>
<td>ESC</td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>冠铭主板</td>
<td>F9</td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
<p>酷睿</p>
<table tabindex="0">
<thead>
<tr>
<th>X</th>
<th>极致性能版</th>
<th>H/HQ/R</th>
<th>高性能/四核/封装</th>
</tr>
</thead>
<tbody>
<tr>
<td>U</td>
<td>低压版</td>
<td>K</td>
<td>不锁倍频</td>
</tr>
<tr>
<td>P</td>
<td>无核显</td>
<td>MQ/QM</td>
<td>四核移动版</td>
</tr>
<tr>
<td>S</td>
<td>低功耗</td>
<td>MX</td>
<td>极致性能移动版</td>
</tr>
<tr>
<td>C</td>
<td>不锁倍频核显加强</td>
<td>M</td>
<td>移动版标压</td>
</tr>
<tr>
<td>T</td>
<td>超低功耗（阉割）</td>
<td>Y</td>
<td>极致低压</td>
</tr>
<tr>
<td>R</td>
<td>高性能核显移植</td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[PG-ep1]]></title>
            <link>http://ooowl.fun/blogs/Web%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/%E5%AD%98%E5%82%A8%E6%8A%80%E6%9C%AF/PG-ep1.html</link>
            <guid isPermaLink="false">http://ooowl.fun/blogs/Web%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/%E5%AD%98%E5%82%A8%E6%8A%80%E6%9C%AF/PG-ep1.html</guid>
            <pubDate>Thu, 19 Sep 2024 14:47:00 GMT</pubDate>
            <content:encoded><![CDATA[<h1 id="pg-ep1" tabindex="-1">PG-ep1 <a class="header-anchor" href="#pg-ep1" aria-label="Permalink to &quot;PG-ep1&quot;">&ZeroWidthSpace;</a></h1><p class="article-meta">创建于 2024年9月19日 22:47:00 · 约180字</p>
<h2 id="常用的sql语句" tabindex="-1">常用的SQL语句 <a class="header-anchor" href="#常用的sql语句" aria-label="Permalink to &quot;常用的SQL语句&quot;">&ZeroWidthSpace;</a></h2>
<p>重置主键</p>
<div class="language-sql vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">sql</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">select</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> setval(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'schema.table_id_seq'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">max</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(id)) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> schema</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">table</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p>不能直接对联接（join）后的结果进行更新。原因是更新操作需要明确的目标表，而联接通常涉及多个表。<br>
对于sql的select查询fetch的时候必须要限制数量，直接select所有容易爆内存<br>
sqlalchemy防止注入基本都做好了不用自己担心<br>
where 的问题，大表的in小集合，是没有问题的，大表in大集合不行<br>
不要对大表进行update,分布式MPP数据库的优势在于查询，而不是写入</p>
<p><a href="https://www.cnblogs.com/lovezhr/p/15002342.html" target="_blank" rel="noreferrer">pg vacuum的弊与利 之弊 - 章怀柔 - 博客园</a></p>
<h2 id="踩坑" tabindex="-1">踩坑 <a class="header-anchor" href="#踩坑" aria-label="Permalink to &quot;踩坑&quot;">&ZeroWidthSpace;</a></h2>
<h3 id="大表联查优化" tabindex="-1">大表联查优化 <a class="header-anchor" href="#大表联查优化" aria-label="Permalink to &quot;大表联查优化&quot;">&ZeroWidthSpace;</a></h3>
<p>硬件配置:
CPU: arm64
内存: 250GB</p>
<div class="language-yaml vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">yaml</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">cda-postgres-master</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">  image</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"bitnami/postgresql:15"</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">  hostname</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">cda-postgres</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">  restart</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">always</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">  ports</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    - </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"25432:5432"</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">  volumes</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    - </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">./data/pg:/bitnami/postgresql</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    - </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">./data/pg-tmp:/tmp</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">  environment</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">    POSTGRESQL_TIMEZONE</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">Asia/Shanghai</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">    POSTGRESQL_USERNAME</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">${CDA_USERNAME}</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">    POSTGRESQL_PASSWORD</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">${CDA_PASSWORD}</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">    POSTGRESQL_DATABASE</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">postgres</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">    POSTGRESQL_POSTGRES_CONNECTION_LIMIT</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">100000</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">    POSTGRESQL_MAX_PARALLEL_WORKERS_PER_GATHER</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">16</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">    POSTGRESQL_MAX_PARALLEL_WORKERS</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">32</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">    POSTGRESQL_MAX_WORKER_PROCESSES</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">32</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">    POSTGRESQL_SHARED_BUFFERS</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">8GB</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">    POSTGRESQL_MAX_CONNECTIONS</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1000</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">    POSTGRESQL_WORK_MEM</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">256MB</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">    POSTGRESQL_WAL_BUFFERS</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">64MB</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">    POSTGRESQL_MAINTENANCE_WORK_MEM</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">1GB</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">    POSTGRESQL_EFFECTIVE_CACHE_SIZE</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">16GB</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">  shm_size</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">4g</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br></div></div><p>CloudNativePG</p>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[一次性搞懂]]></title>
            <link>http://ooowl.fun/blogs/%E4%BB%A3%E7%A0%81%E4%B9%8B%E5%A4%96/%E4%B8%80%E6%AC%A1%E6%80%A7%E6%90%9E%E6%87%82.html</link>
            <guid isPermaLink="false">http://ooowl.fun/blogs/%E4%BB%A3%E7%A0%81%E4%B9%8B%E5%A4%96/%E4%B8%80%E6%AC%A1%E6%80%A7%E6%90%9E%E6%87%82.html</guid>
            <pubDate>Tue, 10 Sep 2024 15:12:18 GMT</pubDate>
            <description><![CDATA[HTTP]]></description>
            <content:encoded><![CDATA[<h1 id="一次性搞懂" tabindex="-1">一次性搞懂 <a class="header-anchor" href="#一次性搞懂" aria-label="Permalink to &quot;一次性搞懂&quot;">&ZeroWidthSpace;</a></h1><p class="article-meta">创建于 2024年9月10日 23:12:18 · 约3,429字</p>
<h2 id="常见web请求方式" tabindex="-1">常见Web请求方式 <a class="header-anchor" href="#常见web请求方式" aria-label="Permalink to &quot;常见Web请求方式&quot;">&ZeroWidthSpace;</a></h2>
<p>HTTP</p>
<table tabindex="0">
<thead>
<tr>
<th>浏览器支持最大HTTP并发</th>
<th>HTTP / 1.1</th>
<th>HTTP / 1.0</th>
</tr>
</thead>
<tbody>
<tr>
<td>IE 11</td>
<td>6</td>
<td>6</td>
</tr>
<tr>
<td>IE 10</td>
<td>6</td>
<td>6</td>
</tr>
<tr>
<td>IE 9</td>
<td>10</td>
<td>10</td>
</tr>
<tr>
<td>IE 8</td>
<td>6</td>
<td>6</td>
</tr>
<tr>
<td>IE 6,7</td>
<td>2</td>
<td>4</td>
</tr>
<tr>
<td>火狐</td>
<td>6</td>
<td>6</td>
</tr>
<tr>
<td>Safari 3,4</td>
<td>4</td>
<td>4</td>
</tr>
<tr>
<td>Chrome 4+</td>
<td>6</td>
<td>6</td>
</tr>
<tr>
<td>Opera9.63,10.00alpha</td>
<td>4</td>
<td>4</td>
</tr>
<tr>
<td>Opera 10.51+</td>
<td>8</td>
<td>？</td>
</tr>
<tr>
<td>iPhone 2</td>
<td>4</td>
<td>？</td>
</tr>
<tr>
<td>iPhone 3</td>
<td>6</td>
<td>？</td>
</tr>
<tr>
<td>iPhone 4</td>
<td>4</td>
<td>？</td>
</tr>
<tr>
<td>iphone 5</td>
<td>6</td>
<td>？</td>
</tr>
</tbody>
</table>
<p>CROS跨域</p>
<p>FunctionCall
SSE
长连接
websocket
HTTP长连接
短连接
HTTP/1.1、HTTP/2、HTTP/3、WebSocket、TLS
RPC
GraphQL
SOAP
MQTT
WebRTC</p>
<h2 id="文本传输协议" tabindex="-1">文本传输协议 <a class="header-anchor" href="#文本传输协议" aria-label="Permalink to &quot;文本传输协议&quot;">&ZeroWidthSpace;</a></h2>
<h3 id="大小端问题" tabindex="-1">大小端问题 <a class="header-anchor" href="#大小端问题" aria-label="Permalink to &quot;大小端问题&quot;">&ZeroWidthSpace;</a></h3>
<p>传的是 字符串（JSON、XML、Protobuf-Text 等文本协议）不会遇到大小端问题，因为文本就是按字符流处理的，只有在直接把数字的“内存二进制”丢到字节流里发送时，才会遇到大小端问题。<br>
messagepack协议层面已经做了大小端的处理了，protobuf也做了</p>
<table tabindex="0">
<thead>
<tr>
<th>语言</th>
<th>内存字节序（取决于CPU）</th>
<th>网络/序列化默认字节序</th>
<th>备注</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>C#</strong></td>
<td>小端（x86/x64 常见）</td>
<td>无统一默认，需要开发者指定</td>
<td><code>BitConverter.IsLittleEndian</code> 可检测</td>
</tr>
<tr>
<td><strong>Java</strong></td>
<td>跟随CPU，但常用API用大端</td>
<td><code>ByteBuffer</code>、<code>DataInputStream</code> 默认大端</td>
<td>为了符合 <strong>网络字节序</strong>（big endian）</td>
</tr>
<tr>
<td><strong>Erlang</strong></td>
<td>跟随CPU</td>
<td>二进制模式/网络通信默认大端</td>
<td>与 Java 类似，强调网络字节序</td>
</tr>
<tr>
<td><strong>AS3</strong></td>
<td>跟随CPU</td>
<td><code>ByteArray.endian</code> 默认大端</td>
<td>可切换为 <code>Endian.LITTLE_ENDIAN</code></td>
</tr>
<tr>
<td><strong>C++</strong></td>
<td>跟随CPU</td>
<td>无固定，需开发者控制</td>
<td>常用 <code>&lt;arpa/inet.h&gt;</code> 转换函数处理</td>
</tr>
<tr>
<td><strong>Python</strong></td>
<td>跟随CPU</td>
<td><code>struct</code>/<code>socket</code> 默认大端</td>
<td><code>struct.pack('&lt;I',x)</code> 小端，<code>'&gt;I'</code> 大端</td>
</tr>
</tbody>
</table>
<h3 id="xml" tabindex="-1">XML <a class="header-anchor" href="#xml" aria-label="Permalink to &quot;XML&quot;">&ZeroWidthSpace;</a></h3>
<p><s>该入土的老东西早该爆金币了（</s><br>
凑活看<a href="https://developer.mozilla.org/zh-CN/docs/Web/XML/XML_introduction" target="_blank" rel="noreferrer">mozilla的文档</a>吧，下面有其他文档的引用。 <a href="https://www.runoob.com/xml/xml-tree.html" target="_blank" rel="noreferrer">XML 树结构 | 菜鸟教程</a>
有且仅有一个根节点，大小写敏感，第一行必是版本和编码，保证严格有序，元素可以重名解析的时候视为列表，xml以LF存储换行。<br>
特殊符号<code>&lt; &amp;lt</code>   <code>&gt; &amp;gt</code>   <code> &amp; &amp;amp</code>   <code>' &amp;apos</code>   <code>&quot; &amp;quot</code> 代替<br>
<strong>所有的节点名，InnerText，Attributes都是字符串类型，IO时的类型转换都由程序来做。</strong><br>
虽然格式很自由但是建议所有人用一个风格。</p>
<div class="language-xml vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">xml</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;?</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">xml</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> version</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"1.0"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> encoding</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"UTF-8"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">?> </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">&#x3C;!-- 第一行固定必须写 --></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">message</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    &#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">Friend</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> name</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"小明"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> age</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'8'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>我的朋友&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">Friend</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">&#x3C;!-- 节点可以带属性 --></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    &#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">Fater</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> name</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"爸爸"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> age</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"50"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> /></span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">&#x3C;!-- 没有子节点可以和html一样关闭 --></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    &#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">warning</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">         Hello World</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    &#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">warning</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">message</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br></div></div><details class="details custom-block"><summary>神秘古老且恶心的CDATA;XSD;DTD;SOAP</summary>
<p>秘古老且恶心的CDATA;XSD;DTD;SOAP
<strong>CDATA(CharacterData)</strong>：被这东西包裹的内容不会被转义，会被原样读取出来</p>
<div class="language-xml vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">xml</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">query</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">&#x3C;![CDATA[</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">SELECT * FROM user WHERE age > 18;</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">]]]]><![CDATA[></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">惺惺相惜&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">query</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">&#x3C;!--可以和一般的混着用--></span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br></div></div><p><strong>XSD(XMLSchemaDefinition)</strong>：新生代用来替代DTD校验XML的东西，纯规则没有数据。</p>
<div class="language-txt vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">txt</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>&#x3C;?xml version="1.0"?></span></span>
<span class="line"><span>&#x3C;!-- 根元素：声明这是一个 XML Schema 文件 --></span></span>
<span class="line"><span>&#x3C;xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"></span></span>
<span class="line"><span></span></span>
<span class="line"><span>  &#x3C;!-- xs:element：定义一个元素 --></span></span>
<span class="line"><span>  &#x3C;xs:element name="user"></span></span>
<span class="line"><span></span></span>
<span class="line"><span>    &#x3C;!-- xs:complexType：复杂类型，元素可以有子元素或属性 --></span></span>
<span class="line"><span>    &#x3C;xs:complexType></span></span>
<span class="line"><span></span></span>
<span class="line"><span>      &#x3C;!-- xs:sequence：子元素必须按顺序出现 --></span></span>
<span class="line"><span>      &#x3C;xs:sequence></span></span>
<span class="line"><span></span></span>
<span class="line"><span>        &#x3C;!-- 普通元素，直接指定类型 --></span></span>
<span class="line"><span>        &#x3C;xs:element name="name" type="xs:string"/></span></span>
<span class="line"><span></span></span>
<span class="line"><span>        &#x3C;!-- 元素内部定义简单类型限制 --></span></span>
<span class="line"><span>        &#x3C;xs:element name="age"></span></span>
<span class="line"><span></span></span>
<span class="line"><span>          &#x3C;!-- xs:simpleType：简单类型，可以在里面加 restriction 限制 --></span></span>
<span class="line"><span>          &#x3C;xs:simpleType></span></span>
<span class="line"><span></span></span>
<span class="line"><span>            &#x3C;!-- xs:restriction：对基础类型加限制 --></span></span>
<span class="line"><span>            &#x3C;xs:restriction base="xs:int"></span></span>
<span class="line"><span></span></span>
<span class="line"><span>              &#x3C;!-- xs:minInclusive / xs:maxInclusive：最小/最大值 --></span></span>
<span class="line"><span>              &#x3C;xs:minInclusive value="0"/></span></span>
<span class="line"><span>              &#x3C;xs:maxInclusive value="120"/></span></span>
<span class="line"><span>            &#x3C;/xs:restriction></span></span>
<span class="line"><span>          &#x3C;/xs:simpleType></span></span>
<span class="line"><span>        &#x3C;/xs:element></span></span>
<span class="line"><span></span></span>
<span class="line"><span>        &#x3C;xs:element name="gender"></span></span>
<span class="line"><span>          &#x3C;xs:simpleType></span></span>
<span class="line"><span>            &#x3C;xs:restriction base="xs:string"></span></span>
<span class="line"><span></span></span>
<span class="line"><span>              &#x3C;!-- xs:enumeration：指定可选枚举值 --></span></span>
<span class="line"><span>              &#x3C;xs:enumeration value="男"/></span></span>
<span class="line"><span>              &#x3C;xs:enumeration value="女"/></span></span>
<span class="line"><span>              &#x3C;xs:enumeration value="未知"/></span></span>
<span class="line"><span>            &#x3C;/xs:restriction></span></span>
<span class="line"><span>          &#x3C;/xs:simpleType></span></span>
<span class="line"><span>        &#x3C;/xs:element></span></span>
<span class="line"><span></span></span>
<span class="line"><span>      &#x3C;/xs:sequence></span></span>
<span class="line"><span></span></span>
<span class="line"><span>      &#x3C;!-- xs:attribute：为元素添加属性 --></span></span>
<span class="line"><span>      &#x3C;xs:attribute name="id" type="xs:int" use="required"/></span></span>
<span class="line"><span></span></span>
<span class="line"><span>    &#x3C;/xs:complexType></span></span>
<span class="line"><span>  &#x3C;/xs:element></span></span>
<span class="line"><span></span></span>
<span class="line"><span>&#x3C;/xs:schema></span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br><span class="line-number">50</span><br><span class="line-number">51</span><br><span class="line-number">52</span><br><span class="line-number">53</span><br></div></div><p><strong>DTD(DocumentTypeDefinition)</strong>: 上世纪80-90留下的历史债，规定了数据的格式类型顺序等等，不仅是规则还混合了一些数据。比较恶心用的也很少了，形式类似于这种<code>&lt;!ELEMENT user (name, age)&gt; &lt;!ATTLIST user id ID #REQUIRED&gt;</code>（看不懂就对了。<br>
<strong>SOAP(SimpleObjectAccessProtocol)</strong>： 使用纯XML通信的web协议，格式类似于下面这种，有时候还会在header中带东西，也比较古老且恶心。</p>
<div class="language-txt vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">txt</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>&#x3C;s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"></span></span>
<span class="line"><span>   &#x3C;s:Body></span></span>
<span class="line"><span>      ...</span></span>
<span class="line"><span>   &#x3C;/s:Body></span></span>
<span class="line"><span>&#x3C;/s:Envelope></span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br></div></div></details>
<h3 id="json" tabindex="-1">JSON <a class="header-anchor" href="#json" aria-label="Permalink to &quot;JSON&quot;">&ZeroWidthSpace;</a></h3>
<p>文档在<a href="https://www.json.org/json-zh.html" target="_blank" rel="noreferrer">这里</a> json标准东西不多<br>
json的类型支持 字符串（<em>string</em>）、数值(number)、<code>true</code>、<code>false</code>、 <code>null</code>、字典（object）或者数组（array）。这些结构可以嵌套。<br>
在 JSON 传输过程中，<strong>列表是有序的</strong>，但<strong>字典（对象）不是有序的</strong>。JSON本身没有明确的长度限制，但是也不会写的巨长，序列化的时候一般会放内存容易崩</p>
<h3 id="protobuf" tabindex="-1">Protobuf <a class="header-anchor" href="#protobuf" aria-label="Permalink to &quot;Protobuf&quot;">&ZeroWidthSpace;</a></h3>
<p><a href="https://protobuf.com.cn/overview/" target="_blank" rel="noreferrer">中文</a>翻译文档和<a href="https://protobuf.dev/" target="_blank" rel="noreferrer">英文原版</a>文档。<br>
<a href="https://www.luozhiyun.com/archives/800" target="_blank" rel="noreferrer">这个博客</a>不错，给出了最佳实践和必要的编码原理
google开发的，和json相比体积小速度快，适合IM这种延迟敏感型应用，proto文件是跨语言的，定义好之后可以用(谷歌提供的)工具反向生成各种语言的代码，再结合proto的包去使用，所以说一开始格式就已经被确定了。</p>
<div class="info custom-block"><p class="custom-block-title">[📝Note]</p>
<p>proto有2和3两个版本是不兼容的，现在绝大部分用的是proto3，如果碰到奇怪的文件请注意proto版本的可能性<br>
注意文档中的协议特性和不适用的地方!!!!!<br>
1 ~ 15：单字节编码，16 ~ 2047：双字节编码，使用频率高的变量最好设置为1~15，编号一旦指定不能修改，所以为了扩展保留一些 1~15 的 编号</p>
</div>
<p>Protobuf在消息大小上没有明确限制，但通常建议保持小于2MB(就是不要太大，并不一定非得2MB)。Protobuf的字段顺序在定义时是固定的，但在序列化时不保证顺序<br>
C#代码中可以使用protogen，是针对C#的实现，大致看一眼，用到细节再去查。mac上<code>brew install protobuf</code> 安装，使用<code>protoc --version</code>查看版本，一般是3.</p>
<table tabindex="0">
<thead>
<tr>
<th>特性</th>
<th>protoc</th>
<th>protogen</th>
</tr>
</thead>
<tbody>
<tr>
<td>生成的代码</td>
<td>标准的 Protocol Buffers C# 类</td>
<td>生成的 C# 类更符合 .NET 的风格和最佳实践</td>
</tr>
<tr>
<td>gRPC 支持</td>
<td>支持 gRPC（通过 grpc_csharp_plugin）</td>
<td>提供更丰富的 gRPC 支持，优化了与 .NET 集成的方式</td>
</tr>
<tr>
<td>定制化能力</td>
<td>基本的 C# 类生成，较少定制化</td>
<td>提供更多的扩展点，允许开发者对代码进行自定义</td>
</tr>
<tr>
<td>.NET 特性</td>
<td>提供基础的 C# 支持</td>
<td>更好支持 .NET 特性，如依赖注入、日志系统等</td>
</tr>
<tr>
<td>集成工具</td>
<td>与原生 Protobuf 代码生成集成</td>
<td>与 .NET 工具链更深度集成，比如 MSBuild 插件</td>
</tr>
<tr>
<td>使用场景</td>
<td>适用于跨平台和多语言项目</td>
<td>更适合 .NET 核心或大型 C# 项目，尤其是 gRPC 服务</td>
</tr>
</tbody>
</table>
<details class="details custom-block"><summary>一个基本的protobuf文件的定义如下</summary>
<p>个基本的protobuf文件的定义如下</p>
<div class="language-protobuf vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">protobuf</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">syntax</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "proto3"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">package</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> example</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  包可以划分不同的命名空间</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// import "user.proto";</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> //  引入其他 proto 文件</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 定义一个用户类型的枚举</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">enum</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> UserType</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  UNKNOWN </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  ADMIN </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  MEMBER </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 地址信息消息</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">message</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Address</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">  string</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> street </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">  string</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> city </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">  string</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> state </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">  sint32</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> zip_code </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 4</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 适合表示带负数的</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 用户信息消息，嵌套 Address</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">message</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> User</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">  int32</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> id </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;                  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// int32 适合正数</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">  string</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> name </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">  string</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> email </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">  repeated</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> Address</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> addresses </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 4</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// repeated 表示数组</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">  UserType</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> type </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 5</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;              </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 使用枚举类型 UserType</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">  optional</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> string</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> phone </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 6</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;      </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// optional 可空字段</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">  map</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">string</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">string</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">> tags </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 7</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;   </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// map 键值对</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br></div></div></details>
<table tabindex="0">
<thead>
<tr>
<th>proto文件消息类型</th>
<th>C++ 类型</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>double</td>
<td>double</td>
<td>双精度浮点型</td>
</tr>
<tr>
<td>float</td>
<td>float</td>
<td>单精度浮点型</td>
</tr>
<tr>
<td>int32</td>
<td>int32</td>
<td>使用可变长编码方式，负数时不够高效，应该使用sint32</td>
</tr>
<tr>
<td>int64</td>
<td>int64</td>
<td>使用可变长编码方式，负数时不够高效，应该使用sint32</td>
</tr>
<tr>
<td>uint32</td>
<td>uint32</td>
<td>使用可变长编码方式</td>
</tr>
<tr>
<td>uint64</td>
<td>uint64</td>
<td>使用可变长编码方式</td>
</tr>
<tr>
<td>sint32</td>
<td>int32</td>
<td>使用可变长编码方式，有符号的整型值，负数编码时比通常的int32高效</td>
</tr>
<tr>
<td>sint64</td>
<td>sint64</td>
<td>使用可变长编码方式，有符号的整型值，负数编码时比通常的int64高效</td>
</tr>
<tr>
<td>fixed32</td>
<td>uint32</td>
<td>总是4个字节，如果数值总是比2^28大的话，这个类型会比uint32高效</td>
</tr>
<tr>
<td>fixed64</td>
<td>uint64</td>
<td>总是8个字节，如果数值总是比2^56大的话，这个类型会比uint64高效</td>
</tr>
<tr>
<td>sfixed32</td>
<td>int32</td>
<td>总是4个字节</td>
</tr>
<tr>
<td>sfixed64</td>
<td>int64</td>
<td>总是8个字节</td>
</tr>
<tr>
<td>bool</td>
<td>bool</td>
<td>布尔类型</td>
</tr>
<tr>
<td>string</td>
<td>string</td>
<td>一个字符串必须是utf-8编码或者7-bit的ascii编码的文本</td>
</tr>
<tr>
<td>bytes</td>
<td>string</td>
<td>可能包含任意顺序的字节数据，不是C#中的字节数组</td>
</tr>
</tbody>
</table>
<ul>
<li><code>reserved</code>是保留关键字，用来做更改字段时兼容性用的</li>
<li><code>message</code> 类型字段默认就是可空的</li>
<li>protoc生成的命名风格一般都是定好的，虽然可以强行改，但不太好改。命名转换不会影响字段实际存储或序列化的键值，只是适配语言使用</li>
<li>map关键字的key只允许使用int和string相关的类型。</li>
<li>嵌套性<code>map&lt;string, repeated int32&gt;</code> 是可以的<code>repeated map</code>不行，可以把Map放到一个Message中套一层就可以了。repeat和map自己套自己也是需要包一层</li>
<li>map内部是哈希表不保证顺序，repeated是保证顺序的</li>
<li>人类习惯大端字节序读取，计算机是小端字节序读取，开发中怎么约定是自定义的
<ul>
<li>TCPIP中规定了网络字节序都是大端模式，前后端语言不同的时候使用大小端不一样，可能要进行转换</li>
<li>使用Bit相关的API判断是大端还是小端，然后拿到byte数组后reverse一下</li>
<li>proto已经封装了大小端转换的问题了，一般是前端多做处理减轻后端压力</li>
</ul>
</li>
</ul>
<h3 id="messagepack" tabindex="-1">MessagePack <a class="header-anchor" href="#messagepack" aria-label="Permalink to &quot;MessagePack&quot;">&ZeroWidthSpace;</a></h3>
<p>跨语言，定义自带类型，支持动态解析，比json快很多，纯2进制传输，相比protobuf稍大但灵活，速度比proto慢一点。<br>
常用于对延迟和体积有要求的地方比如rpc等，感觉需要速度的时候都可以被proto替代，不需要速度的时候被json替代。可能碰到恰好的场景才会发挥作用。</p>
<ul>
<li>key不能重复或者跳号，可以用字符串当key但是体积大；</li>
<li>字段增加用新的 Key，旧 Key 保留或废弃，否则重用可能导致历史数据错误；</li>
<li>兼容了特殊字符；</li>
<li>反序列化的时候可能报错要注意处理</li>
<li>对引用类型可以兼容null，值类型必须标记可空才行否则报错</li>
</ul>
<p>用到的时候再去搞细节吧，C#世界里有MemoryPack上位替代</p>
<details class="details custom-block"><summary>在C#中的示例</summary>
<p>C#中的示例</p>
<div class="language-Csharp vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">Csharp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">MessagePackObject</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> User</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    [</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Key</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)] </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> int</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">? </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Id</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> { </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">get</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">set</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; } </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 值类型可空标记</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    [</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Key</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)] </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> string</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Name</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> { </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">get</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">set</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    [</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Key</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)] </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> string</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Email</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> { </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">get</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">set</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    [</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Key</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)] </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Animal</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Pet</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> { </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">get</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">set</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; } </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 使用继承类的时候一定要注意</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Union</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">typeof</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Dog</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">))]</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Union</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">typeof</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Cat</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">))]</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">MessagePackObject</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> abstract</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Animal</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{ [</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Key</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)] </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> string</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Name</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> { </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">get</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">set</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; } }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">MessagePackObject</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Dog</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> : </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Animal</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{ [</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Key</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)] </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> bool</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> HasTail</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> { </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">get</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">set</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; } }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">MessagePackObject</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Cat</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> : </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Animal</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{ [</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Key</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)] </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> int</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Lives</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> { </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">get</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">set</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; } }</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Program</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    static</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Main</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">string</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[] </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">args</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        User</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> user</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> User</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> { Id </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1001</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, Name </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "Jack"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, Email </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "jack@example.com"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> ,Pet </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Dog</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> { Name </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "Buddy"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, HasTail </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> }}; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 创建对象，注意看是怎么多态指定Pat的类型</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        // 序列化到字节数组</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        byte</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[] </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">bytes</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> MessagePackSerializer.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Serialize</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(user);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">WriteLine</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"序列化字节长度: "</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> +</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> bytes.Length);</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        // 反序列化</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        User</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> deserializedUser</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> MessagePackSerializer.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Deserialize</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">User</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>(bytes);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">WriteLine</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">$"反序列化结果: Id={</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">deserializedUser</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Id</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">}, Name={</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">deserializedUser</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Name</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">}, Email={</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">deserializedUser</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Email</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">}"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        // 序列化到文件</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        string</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> filePath</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "user.dat"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        File.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">WriteAllBytes</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(filePath, bytes);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">WriteLine</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"已写入文件: "</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> +</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> filePath);</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        // 从文件读取并反序列化</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        byte</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[] </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">readBytes</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> File.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">ReadAllBytes</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(filePath);</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        User</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> userFromFile</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> MessagePackSerializer.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Deserialize</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">User</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>(readBytes);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">WriteLine</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">$"从文件读取: Id={</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">userFromFile</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Id</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">}, Name={</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">userFromFile</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Name</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">}, Email={</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">userFromFile</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Email</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">}"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br></div></div></details>
<h2 id="编码的发展" tabindex="-1">编码的发展 <a class="header-anchor" href="#编码的发展" aria-label="Permalink to &quot;编码的发展&quot;">&ZeroWidthSpace;</a></h2>
<p>有时间再整理。
<a href="https://jishuin.proginn.com/p/763bfbd3281a" target="_blank" rel="noreferrer">彻底摆脱乱码的困惑-技术圈</a><br/>
<a href="https://blog.csdn.net/evasnowind/article/details/115735854" target="_blank" rel="noreferrer">乱码对照表_evasnowind的博客-CSDN博客_乱码对照表</a><br/>
<a href="https://www.asciitable.com/" target="_blank" rel="noreferrer">ASCII Table - ASCII Character Codes, HTML, Octal, Hex, Decimal</a><br/>
<a href="https://www.liaoxuefeng.com/wiki/1016959663602400/1017075323632896" target="_blank" rel="noreferrer">字符串和编码 - 廖雪峰的官方网站</a></p>
<h3 id="一个汉字占多少" tabindex="-1">一个汉字占多少 <a class="header-anchor" href="#一个汉字占多少" aria-label="Permalink to &quot;一个汉字占多少&quot;">&ZeroWidthSpace;</a></h3>
<p>ASCII 要记住什么</p>
<h3 id="unicode中文乱码表" tabindex="-1">Unicode中文乱码表 <a class="header-anchor" href="#unicode中文乱码表" aria-label="Permalink to &quot;Unicode中文乱码表&quot;">&ZeroWidthSpace;</a></h3>
<table tabindex="0">
<thead>
<tr>
<th>乱码</th>
<th>示例</th>
<th>特点</th>
<th>产生原因</th>
</tr>
</thead>
<tbody>
<tr>
<td>古文码</td>
<td>鐢辨湀瑕佸ソ濂藉涔犲ぉ澶╁悜涓?</td>
<td>大都为不认识的古文，并加杂日韩文</td>
<td>以 GBK 方式读取 UTF-8 编码的中文</td>
</tr>
<tr>
<td>口字码</td>
<td>����Ҫ�¨2�ѧϰ������</td>
<td>大部分字符为小方块</td>
<td>以 UTF-8 的方式读取 GBK 编码的中文</td>
</tr>
<tr>
<td>符号码</td>
<td>ç”±æœˆè|å￥½å￥½å-|ä1 å¤©å¤©å‘ä¸Š</td>
<td>大部分字符为各种符号</td>
<td>以 ISO8859-1 方式读取 UTF-8 编码的中文</td>
</tr>
<tr>
<td>拼音码</td>
<td>óéÔÂòaoÃoÃÑ§Ï°ììììÏòéÏ</td>
<td>大部分字符为头顶带有各种类似声调符号的字母</td>
<td>以 ISO8859-1 方式读取 GBK 编码的中文</td>
</tr>
<tr>
<td>问句码</td>
<td>由月要好好学习天天向??</td>
<td>字符串长度为偶数时正确，长度为奇数时最后的字符变为问号</td>
<td>以 GBK 方式读取 UTF-8 编码的中文，然后又用 UTF-8 的格式再次读取</td>
</tr>
<tr>
<td>锟拷码</td>
<td>锟斤拷锟斤拷要锟矫猴拷学习锟斤拷锟斤拷锟斤拷</td>
<td>全中文字符，且大部分字符为“锟斤拷”这几个字符</td>
<td>以 UTF-8 方式读取 GBK 编码的中文，然后又用 GBK 的格式再次读取</td>
</tr>
<tr>
<td>烫烫烫</td>
<td>烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫</td>
<td>字符显示为“烫烫烫”这几个字符</td>
<td>VC Debug 模式下，栈内存未初始化</td>
</tr>
<tr>
<td>屯屯屯</td>
<td>屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯</td>
<td>字符显示为“屯屯屯”这几个字符</td>
<td>VC Debug 模式下，堆内存未初始化</td>
</tr>
</tbody>
</table>
<p>推荐插件 File Encoding Converter 安装完之后右键直接转换好使的一笔。
#TODO <a href="https://www.bilibili.com/video/BV1xD4y1y7yc/" target="_blank" rel="noreferrer">字符集</a></p>
<h2 id="时间格式和时区" tabindex="-1">时间格式和时区 <a class="header-anchor" href="#时间格式和时区" aria-label="Permalink to &quot;时间格式和时区&quot;">&ZeroWidthSpace;</a></h2>
<h2 id="常见文件格式-存储方式-下载方式" tabindex="-1">常见文件格式 存储方式 下载方式 <a class="header-anchor" href="#常见文件格式-存储方式-下载方式" aria-label="Permalink to &quot;常见文件格式 存储方式 下载方式&quot;">&ZeroWidthSpace;</a></h2>
<p>比较零碎，到时候在这里整理整理。</p>
<p>HTTP server的存储
FTP和SFTP
SMB
WebDAV</p>
<p>短链接服务</p>
<p>rsync
NFS
scp</p>
<p>BT和P2P</p>
<p>常见压缩算法
7z
zip
tar
bzip</p>
<p>一般文件分发的加密和安全性
到时候整理一下</p>
<p>视频文件格式</p>
<h3 id="rss协议" tabindex="-1">RSS协议 <a class="header-anchor" href="#rss协议" aria-label="Permalink to &quot;RSS协议&quot;">&ZeroWidthSpace;</a></h3>
<p>RSS的的主体是一个文件，每次发布者更新文件，订阅者打开阅读器的时候，拉取文件然后对比获取哪些是新信息。先上标准示例</p>
<details class="details custom-block"><summary>一个够用的符合RSS2.0标准的订阅源</summary>
<p>个够用的符合RSS2.0标准的订阅源</p>
<div class="language-xml vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">xml</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;?</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">xml</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> version</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"1.0"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> encoding</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"UTF-8"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">?> </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">&#x3C;!-- XML声明：指定XML版本和字符编码 --></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">rss</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> version</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"2.0"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> xmlns:atom</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"http://www.w3.org/2005/Atom"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> xmlns:content</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"http://purl.org/rss/1.0/modules/content/"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> xmlns:dc</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"http://purl.org/dc/elements/1.1/"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">> </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">&#x3C;!-- version指定RSS版本，xmlns定义命名空间 --></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  &#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">channel</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">> </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">&#x3C;!-- 包含订阅源的所有信息 --></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    &#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">atom:link</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> href</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"https://example.com/rss.xml"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> rel</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"self"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> type</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"application/rss+xml"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">/> </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">&#x3C;!-- 指向RSS文件本身的链接，用于自引用 --></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    &#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">atom:logo</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>https://yoursite.com/logo.png&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">atom:logo</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">&#x3C;!-- 订阅源的Logo [^1] --></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    &#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">title</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>示例订阅源&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">title</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">> </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">&#x3C;!-- 订阅源的标题名称 --></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    &#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">link</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>https://example.com/&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">link</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">> </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">&#x3C;!-- 订阅源对应的网站主页链接 --></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    &#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">description</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>这是一个示例订阅源&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">description</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">> </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">&#x3C;!-- 订阅源的描述信息 --></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    &#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">generator</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>vuepress-plugin-feed2&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">generator</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">> </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">&#x3C;!-- 生成此RSS的软件或工具名称 --></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    &#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">docs</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>https://support.google.com/merchants/answer/14987622?hl=zh-Hans&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">docs</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">> </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">&#x3C;!-- 指向RSS规范文档的链接（可选） --></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    &#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">category</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>示例分类1&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">category</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">> </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">&#x3C;!-- 订阅源的分类标签可以有多个，非必需一般给搜索引擎用 --></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    &#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">category</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>示例分类2&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">category</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    &#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">language</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>zh-CN&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">language</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">> </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">&#x3C;!-- 订阅源使用的语言 --></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    &#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">pubDate</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>Mon, 01 Jan 2024 12:00:00 GMT&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">pubDate</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">> </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">&#x3C;!-- 订阅源的创建日期 [^2]--></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    &#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">lastBuildDate</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>Mon, 01 Jan 2024 12:00:00 GMT&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">lastBuildDate</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">> </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">&#x3C;!-- 订阅源最近更新的日期，这个时间比上次检查时更新，阅读器就知道需要重新获取内容 [^3]--></span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    &#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">item</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">> </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">&#x3C;!-- 表示订阅源中的一篇文章或条目 --></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      &#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">title</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>示例文章1&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">title</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">> </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">&#x3C;!-- 文章的标题 --></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      &#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">link</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>https://example.com/article1&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">link</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">> </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">&#x3C;!-- 文章的完整URL链接，用户点击跳转的就是这个 [^4]--></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      &#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">guid</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>https://example.com/article1&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">guid</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">> </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">&#x3C;!-- 文章的全局唯一标识符，推荐使用URL，Rss阅读器通常用这个去重 [^5]--></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      &#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">description</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>这是第1篇示例文章的描述&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">description</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">> </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">&#x3C;!-- 文章的简短描述或摘要 --></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      &#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">pubDate</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>Mon, 01 Jan 2024 12:00:00 GMT&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">pubDate</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">> </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">&#x3C;!-- 文章的发布日期和时间 [^6]--></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      &#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">atom:updated</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>Mon, 01 Jan 2024 12:00:00 GMT&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">atom:updated</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">> </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">&#x3C;!-- 文章的最后更新时间 [^7]--></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      &#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">content:encoded</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">&#x3C;![CDATA[&#x3C;p>示例内容1&#x3C;/p>]]></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">content:encoded</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">> </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">&#x3C;!-- 文章的完整HTML内容，使用CDATA包裹 --></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    &#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">item</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    &#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">item</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">> </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">&#x3C;!-- 第二篇文章 --></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      &#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">title</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>示例文章2&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">title</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      &#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">link</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>https://example.com/article2&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">link</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      &#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">guid</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>https://example.com/article2&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">guid</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      &#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">description</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>这是第2篇示例文章的描述&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">description</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      &#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">pubDate</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>Mon, 01 Jan 2024 11:00:00 GMT&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">pubDate</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      &#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">atom:updated</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>Mon, 01 Jan 2024 11:00:00 GMT&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">atom:updated</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      &#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">content:encoded</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">&#x3C;![CDATA[&#x3C;p>示例内容2&#x3C;/p>]]></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">content:encoded</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    &#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">item</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  &#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">channel</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">rss</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br></div></div></details>
<p>注意事项在示例中标注了</p>
<ol>
<li>大多数现代RSS阅读器会自动检测并使用网站的favicon.ico作为订阅源图标，无需在RSS中明确指定。</li>
<li>订阅源的创建日期一般是不变的
<ul>
<li><strong>时间格式</strong>必须遵循 <strong>RFC 822</strong> 标准格式<code>Wed, 16 Sep 2025 10:30:00 +0800</code></li>
</ul>
</li>
<li>订阅源最近更新的日期，这个时间比上次检查时更新，阅读器就知道需要重新获取内容，每次生成的时候变更就行</li>
<li>文章的完整URL链接，用户点击文章跳转的就是这个</li>
<li>文章的全局唯一标识符，推荐使用URL，Rss阅读器通常用这个去重
<ul>
<li>guid不影响点击跳转，可以用这个让RSS以为是新文章</li>
<li>即使 <code>&lt;pubDate&gt;</code> 和 <code>&lt;atom:updated&gt;</code> 时间很老，只要GUID是新的，就会被识别为新文章，检查优先级高</li>
</ul>
</li>
<li>文章的发布日期和时间，理论上也是一次性的，大部分旧的阅读器按照这个排序
<ul>
<li>你可以每次更新发布日期让阅读器以为这是新文章，从而让你有新内容的旧文章每次被当作新文章被拉取</li>
</ul>
</li>
<li>文章的最后更新时间，每次更新，这个是atom空间定义的，很多阅读器不用这个字段
<ul>
<li>如果支持阅读器文章的最后更新时间那就直接用这个，不用整花活了</li>
<li>实际上主要的排序还得看阅读器的行为</li>
<li>好像是AtomRss的标准RSS2.0不能用</li>
</ul>
</li>
<li>阅读器可能有缓存或者定期刷新，有可能加上后过一会用户才能收到</li>
</ol>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[后端常见安全措施]]></title>
            <link>http://ooowl.fun/blogs/Web%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/%E5%B8%B8%E8%A7%81%E5%AE%89%E5%85%A8/%E5%90%8E%E7%AB%AF%E5%B8%B8%E8%A7%81%E5%AE%89%E5%85%A8%E6%8E%AA%E6%96%BD.html</link>
            <guid isPermaLink="false">http://ooowl.fun/blogs/Web%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/%E5%B8%B8%E8%A7%81%E5%AE%89%E5%85%A8/%E5%90%8E%E7%AB%AF%E5%B8%B8%E8%A7%81%E5%AE%89%E5%85%A8%E6%8E%AA%E6%96%BD.html</guid>
            <pubDate>Mon, 27 May 2024 17:32:22 GMT</pubDate>
            <content:encoded><![CDATA[<h1 id="后端常见安全措施" tabindex="-1">后端常见安全措施 <a class="header-anchor" href="#后端常见安全措施" aria-label="Permalink to &quot;后端常见安全措施&quot;">&ZeroWidthSpace;</a></h1><p class="article-meta">创建于 2024年5月28日 01:32:22 · 约429字</p>
<p>这里并不是专门做安全的专业的，而是作为一个开发人员应该了解的安全方面。</p>
<h2 id="服务器安全" tabindex="-1">服务器安全 <a class="header-anchor" href="#服务器安全" aria-label="Permalink to &quot;服务器安全&quot;">&ZeroWidthSpace;</a></h2>
<p><a href="https://mp.weixin.qq.com/s/dtnrbg_BSJ_JHeliQTBj4w" target="_blank" rel="noreferrer">POST 为什么会发送两次请求</a>
同源策略以及规避</p>
<p><a href="https://github.com/jtesta/ssh-audit" target="_blank" rel="noreferrer">SSH审计工具jtesta/ssh-audit</a> 可以看主机的SSH安全策略和漏洞</p>
<h3 id="小团队vpn和防火墙选型" tabindex="-1">小团队VPN和防火墙选型 <a class="header-anchor" href="#小团队vpn和防火墙选型" aria-label="Permalink to &quot;小团队VPN和防火墙选型&quot;">&ZeroWidthSpace;</a></h3>
<p>#todo 几人的小团队使用的软件VPN和防火墙，原则是持久不过期，能一直用，安全性够用就行。还有防火墙的软硬件区别</p>
<h2 id="后端常用加密解密" tabindex="-1">后端常用加密解密 <a class="header-anchor" href="#后端常用加密解密" aria-label="Permalink to &quot;后端常用加密解密&quot;">&ZeroWidthSpace;</a></h2>
<p>#todo 关于常见的加密解密，非安全开发者应该知道的方法，性能，安全性，哪些部分可公开
常用的整个表格</p>
<p>AES加密解密，和通用公司对接的时候要求用户名和密码都加密传输，所以前端需要从可信服务器搞密钥，然后进行加密传后端之后解密</p>
<h3 id="使用xor" tabindex="-1">使用XOR <a class="header-anchor" href="#使用xor" aria-label="Permalink to &quot;使用XOR&quot;">&ZeroWidthSpace;</a></h3>
<p>这是一种简单的加密方式，加密出来也不会太长，适合加密身份证等有点重要但是又没那么重要的，前面显示的是密文，后端拿到手动解密出来。几乎不会性能造成瓶颈。<br>
以后写详细的东西，先把代码放出来。</p>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># -*- coding: utf-8 -*-  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> binascii  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># XOR加密函数，返回十六进制字符串  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> xor_encrypt</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(data: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">str</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, key: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">str</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) -> </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">str</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    key_bytes </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> key.encode(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'utf-8'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    encrypted_data </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> bytearray</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    # XOR操作  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> i, char </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> enumerate</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(data):  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        encrypted_data.append(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">ord</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(char) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">^</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> key_bytes[i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">%</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> len</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(key_bytes)])  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    # 将加密数据转换为十六进制字符串  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> binascii.hexlify(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">bytes</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(encrypted_data)).decode(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'utf-8'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># XOR解密函数，接受十六进制字符串  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> xor_decrypt</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(encrypted_data: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">str</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, key: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">str</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) -> </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">str</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    encrypted_data_bytes </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> binascii.unhexlify(encrypted_data)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    key_bytes </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> key.encode(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'utf-8'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    decrypted_data </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> ""</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    # XOR解密操作  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> i, byte </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> enumerate</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(encrypted_data_bytes):  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        decrypted_data </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> chr</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(byte </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">^</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> key_bytes[i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">%</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> len</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(key_bytes)])  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> decrypted_data  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 加密身份证号的函数  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> encrypt_idnum</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(idnum: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">str</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, key: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">str</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) -> </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">str</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    if</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> len</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(idnum) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">!=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 18</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        raise</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> ValueError</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"身份证号码必须为18位"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    # 获取第7到第18位  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    idcard_to_encrypt </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> idnum[</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">6</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">18</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    # 加密第7到第18位  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    encrypted_part </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> xor_encrypt(idcard_to_encrypt, key)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    # 返回加密后的身份证号码 (前6位 + 加密部分 + 后4位)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    encrypted_idcard </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> idnum[:</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">6</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">] </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> encrypted_part </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> idnum[</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">18</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:]  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> encrypted_idcard  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 解密身份证号的函数  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> decrypt_idnum</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(encrypted_idnum: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">str</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, key: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">str</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) -> </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">str</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    if</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> len</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(encrypted_idnum) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x3C;</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 18</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        raise</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> ValueError</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"加密后的身份证号码长度不正确"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    # 获取加密部分的长度  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    encrypted_part_length </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">len</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(encrypted_idnum) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 6</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 4是后4位身份证号（年份等）  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    # 获取加密后的部分  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    encrypted_part </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> encrypted_idnum[</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">6</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">6</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> +</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> encrypted_part_length]  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    # 解密加密部分  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    decrypted_part </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> xor_decrypt(encrypted_part, key)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    # 返回解密后的身份证号码（前6位 + 解密部分 + 后4位）  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    decrypted_idcard </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> encrypted_idnum[:</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">6</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">] </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> decrypted_part  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> decrypted_idcard  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># # 示例使用  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># idcard = "123456199012345678"  # 身份证号  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">idnum_secret_key </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "rL?viM3^zqp+Er!k~2"</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  # 密钥  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># # 加密  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># encrypted_idcard = encrypt_idnum(idcard, idnum_secret_key)  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># print(f"Encrypted IDCard: {encrypted_idcard}")  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># # 解密  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># decrypted_idcard = decrypt_idnum(encrypted_idcard, idnum_secret_key)  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># print(f"Decrypted IDCard: {decrypted_idcard}")</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br><span class="line-number">50</span><br><span class="line-number">51</span><br><span class="line-number">52</span><br><span class="line-number">53</span><br><span class="line-number">54</span><br><span class="line-number">55</span><br><span class="line-number">56</span><br><span class="line-number">57</span><br><span class="line-number">58</span><br><span class="line-number">59</span><br><span class="line-number">60</span><br><span class="line-number">61</span><br><span class="line-number">62</span><br><span class="line-number">63</span><br><span class="line-number">64</span><br><span class="line-number">65</span><br><span class="line-number">66</span><br><span class="line-number">67</span><br><span class="line-number">68</span><br><span class="line-number">69</span><br><span class="line-number">70</span><br><span class="line-number">71</span><br><span class="line-number">72</span><br><span class="line-number">73</span><br><span class="line-number">74</span><br><span class="line-number">75</span><br></div></div><ul>
<li>crypto是老的GPG加解密库已于2016年停更，<code>python-gnupg</code>库是目前最主流的GPG加解密库</li>
<li>PyCrypto是前主流加解密库已停更。<code>PyCryptodome</code>是当前最主流的Python加解密库，代码中有import Crypto等就需要用这个库</li>
<li><code>cryptography</code> 是 PyCA (Python Cryptographic Authority)维护的库，默认就使用行业标准方案维护频率高强调安全</li>
</ul>
<p>SSH</p>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[测试与性能指标评估]]></title>
            <link>http://ooowl.fun/blogs/Web%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/%E6%B5%8B%E8%AF%95%E8%BF%90%E7%BB%B4/%E6%B5%8B%E8%AF%95%E4%B8%8E%E6%80%A7%E8%83%BD%E6%8C%87%E6%A0%87%E8%AF%84%E4%BC%B0.html</link>
            <guid isPermaLink="false">http://ooowl.fun/blogs/Web%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/%E6%B5%8B%E8%AF%95%E8%BF%90%E7%BB%B4/%E6%B5%8B%E8%AF%95%E4%B8%8E%E6%80%A7%E8%83%BD%E6%8C%87%E6%A0%87%E8%AF%84%E4%BC%B0.html</guid>
            <pubDate>Mon, 27 May 2024 17:32:22 GMT</pubDate>
            <content:encoded><![CDATA[<h1 id="测试与性能指标评估" tabindex="-1">测试与性能指标评估 <a class="header-anchor" href="#测试与性能指标评估" aria-label="Permalink to &quot;测试与性能指标评估&quot;">&ZeroWidthSpace;</a></h1><p class="article-meta">创建于 2024年5月28日 01:32:22 · 约273字</p>
<h3 id="延迟" tabindex="-1">延迟 <a class="header-anchor" href="#延迟" aria-label="Permalink to &quot;延迟&quot;">&ZeroWidthSpace;</a></h3>
<p>可观测性</p>
<p><a href="https://www.bilibili.com/video/BV1yXR9YBE52/" target="_blank" rel="noreferrer">程序员必须了解的系统延迟📌_哔哩哔哩_bilibili</a></p>
<p>系统整体性能指标</p>
<ul>
<li><strong>TPS (Transactions Per Second)</strong>：每秒事务处理数</li>
<li><strong>QPS (Queries Per Second)</strong>：每秒查询数</li>
<li><strong>RPS (Requests Per Second)</strong>：每秒请求数（常用于 Web/API 服务）</li>
<li><strong>吞吐量 (Throughput)</strong>：单位时间内处理的数据量/请求数</li>
<li><strong>并发数 (Concurrency)</strong>：同时处理的请求数</li>
<li><strong>响应时间 (Response Time, RT)</strong>：从发起请求到收到响应的时间</li>
<li><strong>延迟 (Latency)</strong>：处理某个操作的耗时</li>
<li><strong>P95/P99 响应时间</strong>：95%/99% 请求的响应时间小于该值（长尾性能衡量）</li>
<li><strong>可用率 (Availability/Uptime)</strong>：系统正常运行时间占比
DB相关的指标</li>
<li><strong>TPS / QPS</strong>（数据库特有）</li>
<li><strong>Connections</strong>：当前活跃连接数</li>
<li><strong>Connection Pool Usage</strong>：连接池使用率</li>
<li><strong>Slow Queries</strong>：慢查询数量</li>
<li><strong>Cache Hit Ratio</strong>：缓存命中率
运维需要关心的指标</li>
<li>CPU 利用率</li>
<li>内存使用率</li>
<li>磁盘 I/O (IOPS, Read/Write Latency)</li>
<li>网络 I/O (吞吐量, 延迟, 丢包率)</li>
<li>GC 时间/频率（JVM/.NET 等运行时系统）</li>
</ul>
<h2 id="metersphere" tabindex="-1">Metersphere <a class="header-anchor" href="#metersphere" aria-label="Permalink to &quot;Metersphere&quot;">&ZeroWidthSpace;</a></h2>
<p>有社区版 <a href="https://metersphere.io/docs/v3.x/system_arch/" target="_blank" rel="noreferrer">MeterSphere 文档</a></p>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[软件工程]]></title>
            <link>http://ooowl.fun/blogs/Web%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/%E8%BD%AF%E4%BB%B6%E5%B7%A5%E7%A8%8B.html</link>
            <guid isPermaLink="false">http://ooowl.fun/blogs/Web%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/%E8%BD%AF%E4%BB%B6%E5%B7%A5%E7%A8%8B.html</guid>
            <pubDate>Tue, 07 May 2024 23:04:19 GMT</pubDate>
            <content:encoded><![CDATA[<h1 id="软件工程" tabindex="-1">软件工程 <a class="header-anchor" href="#软件工程" aria-label="Permalink to &quot;软件工程&quot;">&ZeroWidthSpace;</a></h1><p class="article-meta">创建于 2024年5月8日 07:04:19 · 约379字</p>
<p>常见的软件工程中的设计原则包括：</p>
<ol>
<li><strong>单一职责原则（Single Responsibility Principle）</strong> ：一个类只做一件事</li>
<li><strong>开闭原则（Open-Closed Principle）</strong> ：最好通过扩展增加新代码来实现新功能而不是改动老代码</li>
<li><strong>里氏替换原则（Liskov Substitution Principle）</strong>：子类必须能够替换其基类而不影响程序的正确性。即父类引用装子类。</li>
<li><strong>依赖倒置原则（Dependency Inversion Principle）</strong>：高层模块不应该依赖于低层模块，两者都应该依赖于抽象。抽象不应该依赖于细节，细节应该依赖于抽象。这一原则通常通过依赖注入DI来实现。</li>
<li><strong>接口隔离原则（Interface Segregation Principle）</strong>：不应该强迫客户端依赖于它们不使用的接口。类不应该被强迫实现它们不需要的接口。相反，应该根据客户端的需求将接口细分为更小的、更具体的接口。</li>
<li><strong>最少知识原则（Law of Demeter，迪米特法则）</strong>：对象应该对其他对象有尽可能少的了解，不要直接调用其它对象的方法，而应该通过自己的方法或者委托给其他对象来实现。</li>
</ol>
<p>这些原则通常被称为SOLID原则，它们共同构成了面向对象设计和编程的基石，有助于编写可维护、可扩展和易于理解的代码。</p>
<p>可拓展 可维护 高性能 可迭代 一致性</p>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[EP2-创建型模式]]></title>
            <link>http://ooowl.fun/blogs/Web%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/EP2-%E5%88%9B%E5%BB%BA%E5%9E%8B%E6%A8%A1%E5%BC%8F.html</link>
            <guid isPermaLink="false">http://ooowl.fun/blogs/Web%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/EP2-%E5%88%9B%E5%BB%BA%E5%9E%8B%E6%A8%A1%E5%BC%8F.html</guid>
            <pubDate>Mon, 06 May 2024 20:52:54 GMT</pubDate>
            <description><![CDATA[简单工厂和工厂一块放这里。 简单工厂在创建对象的时候通过工厂统一的创建对象，创建的时候指明要创建什么对象，这样可以在不用更改调用方，只更改创建方和创建行为就可以了。]]></description>
            <content:encoded><![CDATA[<h1 id="ep2-创建型模式" tabindex="-1">EP2-创建型模式 <a class="header-anchor" href="#ep2-创建型模式" aria-label="Permalink to &quot;EP2-创建型模式&quot;">&ZeroWidthSpace;</a></h1><p class="article-meta">创建于 2024年5月7日 04:52:54 · 约1,023字</p>
<h2 id="工厂方法模式" tabindex="-1">工厂方法模式 <a class="header-anchor" href="#工厂方法模式" aria-label="Permalink to &quot;工厂方法模式&quot;">&ZeroWidthSpace;</a></h2>
<p>简单工厂和工厂一块放这里。
简单工厂在创建对象的时候通过工厂统一的创建对象，创建的时候指明要创建什么对象，这样可以在不用更改调用方，只更改创建方和创建行为就可以了。</p>
<details class="details custom-block"><summary>Click to see more</summary>
<div class="language-Csharp vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">Csharp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">namespace</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> DesignPatterns</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> enum</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> MouseType</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    None</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 回忆一下enum  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    HpMouse</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    LazerMouse</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> BaseMouse</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> // 基础的鼠标类  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> string</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Name</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> BaseMouse</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">string</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> name</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {        </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">this</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.Name </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> name;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> MousePrint</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {        Console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">WriteLine</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">$"{</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Name</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">} Printed!"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }}  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> HpMouse</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">BaseMouse</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> HpMouse</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">string</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> name</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) : </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">base</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(name)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {        Console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">WriteLine</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">$"Create a HpMouse {</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Name</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">}"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> LazerMouse</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">BaseMouse</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> LazerMouse</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">string</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> name</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) : </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">base</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(name)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {        Console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">WriteLine</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">$"Create a LazerMouse {</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Name</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">}"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> MouseSimpleFactory</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    private</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> BaseMouse</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> m</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> BaseMouse</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> GetMouse</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">string</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> name</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">MouseType</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> MT</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {        </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">switch</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (MT) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 每当多一个的时候就要多加一个，这是简单工厂  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        {  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            case</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">MouseType</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">None</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">):  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">                m </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> BaseMouse</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(name); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 赋值的时候发生了向上转型  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">                break</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            case</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">MouseType</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">HpMouse</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">):  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">                m </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> HpMouse</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(name);  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">                break</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            case</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">MouseType</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">LazerMouse</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">):  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">                m </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> LazerMouse</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(name);  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">                break</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            default</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">                throw</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Exception</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"输入的类型不合法"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">                break</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        }  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> m;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//-------Main中-----</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Program</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    static</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Main</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">string</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[] </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">args</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {        </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">WriteLine</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"-----------------简单工厂模式-----------------"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        MouseSimpleFactory</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> mf</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> MouseSimpleFactory</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        BaseMouse</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> bm</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">mf.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetMouse</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"新鼠标"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,MouseType.None); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 根据枚举(指定类型)返回指定的类型的子对象  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        bm.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">MousePrint</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        BaseMouse</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> hm</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">mf.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetMouse</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"新惠普鼠标"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,MouseType.HpMouse);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        hm.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">MousePrint</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br><span class="line-number">50</span><br><span class="line-number">51</span><br><span class="line-number">52</span><br><span class="line-number">53</span><br><span class="line-number">54</span><br><span class="line-number">55</span><br><span class="line-number">56</span><br><span class="line-number">57</span><br><span class="line-number">58</span><br><span class="line-number">59</span><br><span class="line-number">60</span><br><span class="line-number">61</span><br><span class="line-number">62</span><br><span class="line-number">63</span><br><span class="line-number">64</span><br><span class="line-number">65</span><br><span class="line-number">66</span><br><span class="line-number">67</span><br><span class="line-number">68</span><br><span class="line-number">69</span><br><span class="line-number">70</span><br><span class="line-number">71</span><br><span class="line-number">72</span><br><span class="line-number">73</span><br><span class="line-number">74</span><br></div></div><p>运行结果</p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>-----------------简单工厂模式-----------------</span></span>
<span class="line"><span>新鼠标 Printed!</span></span>
<span class="line"><span>Create a HpMouse 新惠普鼠标</span></span>
<span class="line"><span>新惠普鼠标 Printed!</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br></div></div></details>
<p>简单工厂模式违反了开闭原则，需要修改原有的创建工厂而不是新增，工厂模式把每一种子类都单独创建一个对应类型的工厂，新的代码使用的时候直接调用对应的工厂而不是指明统一的工厂(这不就是是接口抽象吗)</p>
<h2 id="抽象工厂模式" tabindex="-1">抽象工厂模式 <a class="header-anchor" href="#抽象工厂模式" aria-label="Permalink to &quot;抽象工厂模式&quot;">&ZeroWidthSpace;</a></h2>
<h2 id="生成器模式" tabindex="-1">生成器模式 <a class="header-anchor" href="#生成器模式" aria-label="Permalink to &quot;生成器模式&quot;">&ZeroWidthSpace;</a></h2>
<h2 id="原型模式" tabindex="-1">原型模式 <a class="header-anchor" href="#原型模式" aria-label="Permalink to &quot;原型模式&quot;">&ZeroWidthSpace;</a></h2>
<h2 id="单例模式" tabindex="-1">单例模式 <a class="header-anchor" href="#单例模式" aria-label="Permalink to &quot;单例模式&quot;">&ZeroWidthSpace;</a></h2>
<p><a href="https://refactoringguru.cn/design-patterns/singleton" target="_blank" rel="noreferrer">单例设计模式</a><br>
在unity中通常用在各种全局的 <code>管理器</code> 中，声音，唯一的角色管理器中，每次获得的都是这个东西，声音不会重复等。<br>
保证一个类只有一个实例， 并提供一个访问该实例的全局节点，注意在多线程多进程环境下使用的时候会不会一个程序空间创建一个导致多次创建。</p>
<ul>
<li>将默认构造函数设为私有， 防止其他对象使用单例类的 <code>new</code>运算符。</li>
<li>新建一个静态构建方法作为构造函数。 该函数会 “偷偷” 调用私有构造函数来创建对象， 并将其保存在一个静态成员变量中。 此后所有对于该函数的调用都将返回这一缓存对象。</li>
<li>该模式在多线程环境下需要进行特殊处理， 避免多个线程多次创建单例对象，饿汉式在类加载的时候就创建无所谓，懒汉式可能在首次创建的时候创建多个。但是如果实例的创建过程非常耗时或耗资源，且长时间未使用，可能会造成资源的浪费</li>
<li>建议不要在单例类中存储线程不安全的属性。这是因为单例对象是全局共享的，存储线程不安全的属性可能会引发并发问题
（虽然在.net中静态变量和构造函数的初始化也是懒汉式的触发，所以在调试器中并不能直接看到，而且调试器也不能直接看堆内容</li>
</ul>
<details class="details custom-block"><summary>Click to see more</summary>
<div class="language-Csharp vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">Csharp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">namespace</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> DesignPatterns</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> SingletonPrac</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    private</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> SingletonPrac</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {        Console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">WriteLine</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"create a SingletonPrac instance"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }    </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// static SingletonPrac instance = null;</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> // 实际上不在类里面，而在堆中  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    // 如果换成下面这行就是饿汉模式，类在堆初始化的时候就创建一次  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    static</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> SingletonPrac</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> instance</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> SingletonPrac</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> static</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> SingletonPrac</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> GetInstance</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {        </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (instance </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">==</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//懒汉模式  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        {  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            instance </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> SingletonPrac</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        }        </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> instance;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Show</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {        Console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">WriteLine</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">$"SingletonPrac intance id: {</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">this</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetHashCode</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">()}"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// GetHashCode就是返回对象的哈希码，对象在内存中唯一的哈希码  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//-------Main中-----</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Program</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    static</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Main</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">string</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[] </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">args</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {        </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">WriteLine</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"-----------------单例模式-----------------"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        SingletonPrac</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> s1</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> SingletonPrac.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetInstance</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        SingletonPrac</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> s2</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> SingletonPrac.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetInstance</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        SingletonPrac</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> s3</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> SingletonPrac.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetInstance</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        s1.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Show</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();s2.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Show</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();s3.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Show</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br></div></div><p>运行结果</p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>-----------------单例模式-----------------</span></span>
<span class="line"><span>create a SingletonPrac instance</span></span>
<span class="line"><span>SingletonPrac intance id: 32854180</span></span>
<span class="line"><span>SingletonPrac intance id: 32854180</span></span>
<span class="line"><span>SingletonPrac intance id: 32854180</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br></div></div></details>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[EP3-结构型模式]]></title>
            <link>http://ooowl.fun/blogs/Web%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/EP3-%E7%BB%93%E6%9E%84%E5%9E%8B%E6%A8%A1%E5%BC%8F.html</link>
            <guid isPermaLink="false">http://ooowl.fun/blogs/Web%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/EP3-%E7%BB%93%E6%9E%84%E5%9E%8B%E6%A8%A1%E5%BC%8F.html</guid>
            <pubDate>Mon, 06 May 2024 20:52:54 GMT</pubDate>
            <description><![CDATA[适配器设计模式（封装器模式） 其实就是封装统一调用，但是每次添加新的类型需要修改原先的适配器代码，但是只添加不修改。 如果这些类只是具有一些共同方法但是并不是完成同一功能的，那代码可能变的难以维护 适配器会让代码复杂度增加]]></description>
            <content:encoded><![CDATA[<h1 id="ep3-结构型模式" tabindex="-1">EP3-结构型模式 <a class="header-anchor" href="#ep3-结构型模式" aria-label="Permalink to &quot;EP3-结构型模式&quot;">&ZeroWidthSpace;</a></h1><p class="article-meta">创建于 2024年5月7日 04:52:54 · 约299字</p>
<h2 id="适配器模式" tabindex="-1">适配器模式 <a class="header-anchor" href="#适配器模式" aria-label="Permalink to &quot;适配器模式&quot;">&ZeroWidthSpace;</a></h2>
<p><a href="https://refactoringguru.cn/design-patterns/adapter" target="_blank" rel="noreferrer">适配器设计模式（封装器模式）</a>
其实就是封装统一调用，但是每次添加新的类型需要修改原先的适配器代码，但是只添加不修改。<br>
如果这些类只是具有一些共同方法但是并不是完成同一功能的，那代码可能变的难以维护<br>
适配器会让代码复杂度增加</p>
<details class="details custom-block"><summary>Click to see more</summary>
<div class="language-Csharp vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">Csharp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">namespace</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> DesignPatterns</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//适配器模式，就是把一个类的接口变成客户端所期待的另一种接口，从而使原本因接口不匹配而无法在一起工作的两个类能在一起工作  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> enum</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> ClientType</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    C1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    C2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Client1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Request1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {        </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">WriteLine</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Client 1 启动！"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Client2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Request2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {        </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">WriteLine</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Client 2 启动！"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Adaptor</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    private</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Client1</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> c1</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Client1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    private</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Client2</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> c2</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Client2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Request</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">ClientType</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> CT</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {        </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        switch</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (CT)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        {            </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            case</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">ClientType</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">C1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">):  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">                c1.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Request1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">                break</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            case</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">ClientType</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">C2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">):  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">                c2.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Request2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">                break</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            default</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">                throw</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Exception</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Unkonwn Type"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        }    </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//-------Main中-----</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Program</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    static</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Main</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">string</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[] </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">args</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {        </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">WriteLine</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"-----------------适配器模式-----------------"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        Adaptor</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> ad</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Adaptor</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        ad.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Request</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(ClientType.C1);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        ad.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Request</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(ClientType.C2);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br><span class="line-number">50</span><br><span class="line-number">51</span><br><span class="line-number">52</span><br><span class="line-number">53</span><br><span class="line-number">54</span><br><span class="line-number">55</span><br><span class="line-number">56</span><br><span class="line-number">57</span><br><span class="line-number">58</span><br><span class="line-number">59</span><br><span class="line-number">60</span><br><span class="line-number">61</span><br></div></div><p>运行结果</p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>-----------------适配器模式-----------------</span></span>
<span class="line"><span>Client 1 启动！</span></span>
<span class="line"><span>Client 2 启动！</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br></div></div></details>
<h2 id="桥接模式" tabindex="-1">桥接模式 <a class="header-anchor" href="#桥接模式" aria-label="Permalink to &quot;桥接模式&quot;">&ZeroWidthSpace;</a></h2>
<h2 id="组合模式" tabindex="-1">组合模式 <a class="header-anchor" href="#组合模式" aria-label="Permalink to &quot;组合模式&quot;">&ZeroWidthSpace;</a></h2>
<h2 id="装饰模式" tabindex="-1">装饰模式 <a class="header-anchor" href="#装饰模式" aria-label="Permalink to &quot;装饰模式&quot;">&ZeroWidthSpace;</a></h2>
<h2 id="外观模式" tabindex="-1">外观模式 <a class="header-anchor" href="#外观模式" aria-label="Permalink to &quot;外观模式&quot;">&ZeroWidthSpace;</a></h2>
<h2 id="享元模式" tabindex="-1">享元模式 <a class="header-anchor" href="#享元模式" aria-label="Permalink to &quot;享元模式&quot;">&ZeroWidthSpace;</a></h2>
<h2 id="代理模式" tabindex="-1">代理模式 <a class="header-anchor" href="#代理模式" aria-label="Permalink to &quot;代理模式&quot;">&ZeroWidthSpace;</a></h2>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[EP4-行为模式]]></title>
            <link>http://ooowl.fun/blogs/Web%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/EP4-%E8%A1%8C%E4%B8%BA%E6%A8%A1%E5%BC%8F.html</link>
            <guid isPermaLink="false">http://ooowl.fun/blogs/Web%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/EP4-%E8%A1%8C%E4%B8%BA%E6%A8%A1%E5%BC%8F.html</guid>
            <pubDate>Mon, 06 May 2024 20:52:54 GMT</pubDate>
            <description><![CDATA[责任链设计模式（职责链模式） 责任链是非常常用的模式，一般使用的是单向链条，即顺序处理。也有树形的责任链，根据条件判断但是总是有一条路径。责任链是动态组装的。 当程序需要使用不同方式处理不同种类请求， 而且请求类型和顺序预先未知时， 可以使用责任链模式。当必须按顺序执行多个处理者时， 可以使用该模式。如果所需处理者及其顺序必须在运行时进行改变， 可以使用责任链模式。 比如我要动态的计算优惠，每一种优惠活动的处理都需要计算下一个处理者是谁，这样就需要使用树或者图。Controler需要能够动态的计算链条的函数，但是这么复杂的我没写过，维护起来成本估计也不低。 见到过的责任链比如Nginx里面处理HTTP的handler，核心接到请求之后分别经过server 块选择 location 块选择 日志模块、代理模块等。Scrapy中框架处理结果也是使用责任链插入不同的数据库。Fastapi中中间件使用责任链处理请求 一个简易插入数据库的责任链（虽然做的我自己都不爱用]]></description>
            <content:encoded><![CDATA[<h1 id="ep4-行为模式" tabindex="-1">EP4-行为模式 <a class="header-anchor" href="#ep4-行为模式" aria-label="Permalink to &quot;EP4-行为模式&quot;">&ZeroWidthSpace;</a></h1><p class="article-meta">创建于 2024年5月7日 04:52:54 · 约1,929字</p>
<h2 id="责任链模式" tabindex="-1">责任链模式 <a class="header-anchor" href="#责任链模式" aria-label="Permalink to &quot;责任链模式&quot;">&ZeroWidthSpace;</a></h2>
<p><a href="https://refactoringguru.cn/design-patterns/chain-of-responsibility" target="_blank" rel="noreferrer">责任链设计模式（职责链模式）</a>
责任链是非常常用的模式，一般使用的是单向链条，即顺序处理。也有树形的责任链，根据条件判断但是总是有一条路径。责任链是动态组装的。
当程序需要使用不同方式处理不同种类请求， 而且请求类型和顺序预先未知时， 可以使用责任链模式。当必须按顺序执行多个处理者时， 可以使用该模式。如果所需处理者及其顺序必须在运行时进行改变， 可以使用责任链模式。
比如我要动态的计算优惠，每一种优惠活动的处理都需要计算下一个处理者是谁，这样就需要使用树或者图。Controler需要能够动态的计算链条的函数，但是这么复杂的我没写过，维护起来成本估计也不低。
见到过的责任链比如Nginx里面处理HTTP的handler，核心接到请求之后分别经过<strong>server 块选择 location 块选择 日志模块、代理模块</strong>等。Scrapy中框架处理结果也是使用责任链插入不同的数据库。Fastapi中中间件使用责任链处理请求<br>
一个简易插入数据库的责任链（虽然做的我自己都不爱用</p>
<details class="details custom-block"><summary>python</summary>
<p>ython</p>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> log_persister</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(cls):  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 使用元类注册  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    cls</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    if</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> '__decorators__'</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> not</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> in</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> cls</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">__dict__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        cls</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.__decorators__ </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> []  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    cls</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.__decorators__.append(log_persister)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> cls</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> ManualLogHandler</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    """处理手动打印的日志"""</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    chain </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> []  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __init__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self, level</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=-</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">):  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.level </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> level  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        ManualLogHandler.chain.append(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 添加pipline</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        ManualLogHandler.chain.sort(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">key</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=lambda</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> x: x.level, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">reverse</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">True</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 按照权重排序</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    @</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">classmethod</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> add_to_chain</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(cls, handler_instance):  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        cls</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.chain.append(handler_instance)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    @</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">classmethod</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> handle</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(cls, message):  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> handler </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> cls</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.chain:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            handler.process(message)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> process</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self, message):  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        pass</span></span>
<span class="line"></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">@log_persister</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> PGSysHandler</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">SystemLogHandler</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">):  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> process</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self, message):  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        db </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> SessionLocal_CDA()  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 这里可以用数据库连接池的</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        system_log </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> SystemLog(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">**</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">message)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        db.add(system_log)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        db.commit()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        db.close()</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">@log_persister</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  # 用这个装饰器装饰  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> ManualLogStdout</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">ManualLogHandler</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">):  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 继承Handler类  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __init__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self):  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        super</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">().</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">__init__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">99</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> process</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self, message):  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 实现处理函数  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        extra_data_j </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> jsonable_encoder(message[</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'extra_data'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">])  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        json_str </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> json.dumps(extra_data_j,</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">ensure_ascii</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">False</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        fmt </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> f</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">{</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">message[</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'request_id'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">}</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> | </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">{</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">message[</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'client_ipport'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">}</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> | </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">{</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">message[</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'logtype'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">}</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> | </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">{</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">message[</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'http_method'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">}</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> {</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">message[</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'req_path'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">}</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> |</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">\n</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> {</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">json_str</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">}</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> \n</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        logger.bind(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">system</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">).log(message[</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"level"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">], fmt)</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br></div></div><p>运行结果</p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span></span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div></details>
<details class="details custom-block"><summary>C#的官方示例</summary>
<p>#的官方示例</p>
<div class="language-Csharp vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">Csharp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">namespace</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> DesignPatterns</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> interface</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> IHandler</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    IHandler</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> SetNext</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">IHandler</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> handler</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    object</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Handle</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">object</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> request</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// The default chaining behavior can be implemented inside a base handler  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// class.  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">abstract</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> AbstractHandler</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> : </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">IHandler</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    private</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> IHandler</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> _nextHandler</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> IHandler</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> SetNext</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">IHandler</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> handler</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {        </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">this</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">._nextHandler </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> handler;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        // Returning a handler from here will let us link handlers in a  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        // convenient way like this:</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        // monkey.SetNext(squirrel).SetNext(dog);        return handler;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> virtual</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> object</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Handle</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">object</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> request</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {        </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">this</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">._nextHandler </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">!=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        {            </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> this</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">._nextHandler.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Handle</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(request);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        }        </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">else</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        {  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        }    }}  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> MonkeyHandler</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> : </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">AbstractHandler</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> override</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> object</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Handle</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">object</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> request</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {        </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> ((request </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">as</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> string</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">==</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "Banana"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        {            </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">return</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> $"Monkey: I'll eat the {</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">request</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">ToString</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">()}.</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">\n</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        }        </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">else</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        {  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> base</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Handle</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(request);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        }    }}  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> SquirrelHandler</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> : </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">AbstractHandler</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> override</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> object</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Handle</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">object</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> request</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {        </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (request.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">ToString</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">==</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "Nut"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        {            </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">return</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> $"Squirrel: I'll eat the {</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">request</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">ToString</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">()}.</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">\n</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        }        </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">else</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        {  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> base</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Handle</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(request);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        }    }}  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> DogHandler</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> : </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">AbstractHandler</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> override</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> object</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Handle</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">object</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> request</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {        </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (request.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">ToString</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">==</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "MeatBall"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        {            </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">return</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> $"Dog: I'll eat the {</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">request</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">ToString</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">()}.</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">\n</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        }        </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">else</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        {  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> base</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Handle</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(request);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        }    }}  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Client</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    //  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> static</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> ClientCode</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">AbstractHandler</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> handler</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {        </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">foreach</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">var</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> food</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> in</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> List</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">string</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">> { </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Nut"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Banana"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Cup of coffee"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> }) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 使用泛型的列表  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        {  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            Console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">WriteLine</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">$"Client: Who wants a {</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">food</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">}?"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            var</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> result</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> handler.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Handle</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(food);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (result </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">!=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            {                Console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Write</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">$"   {</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">result</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">}"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            }            </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">else</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            {  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">                Console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">WriteLine</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">$"   {</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">food</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">} was left untouched."</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            }        }    }}  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> ChainOfResponsibility</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Run</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {        </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 申请责任链  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        var</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> monkey</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> MonkeyHandler</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        var</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> squirrel</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> SquirrelHandler</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        var</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> dog</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> DogHandler</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        //组装责任链  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        monkey.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">SetNext</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(squirrel).</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">SetNext</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(dog); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 在这里组装起来，只是排序，甚至可以单独调用squirrel  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">WriteLine</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Chain: Monkey > Squirrel > Dog</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">\n</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Client.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">ClientCode</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(monkey);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">WriteLine</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">WriteLine</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Subchain: Squirrel > Dog</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">\n</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Client.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">ClientCode</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(squirrel);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br><span class="line-number">50</span><br><span class="line-number">51</span><br><span class="line-number">52</span><br><span class="line-number">53</span><br><span class="line-number">54</span><br><span class="line-number">55</span><br><span class="line-number">56</span><br><span class="line-number">57</span><br><span class="line-number">58</span><br><span class="line-number">59</span><br><span class="line-number">60</span><br><span class="line-number">61</span><br><span class="line-number">62</span><br><span class="line-number">63</span><br><span class="line-number">64</span><br><span class="line-number">65</span><br><span class="line-number">66</span><br><span class="line-number">67</span><br><span class="line-number">68</span><br><span class="line-number">69</span><br><span class="line-number">70</span><br><span class="line-number">71</span><br><span class="line-number">72</span><br><span class="line-number">73</span><br><span class="line-number">74</span><br><span class="line-number">75</span><br><span class="line-number">76</span><br><span class="line-number">77</span><br><span class="line-number">78</span><br><span class="line-number">79</span><br><span class="line-number">80</span><br><span class="line-number">81</span><br><span class="line-number">82</span><br><span class="line-number">83</span><br><span class="line-number">84</span><br><span class="line-number">85</span><br><span class="line-number">86</span><br><span class="line-number">87</span><br><span class="line-number">88</span><br><span class="line-number">89</span><br><span class="line-number">90</span><br><span class="line-number">91</span><br><span class="line-number">92</span><br><span class="line-number">93</span><br></div></div><p>运行结果</p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>Chain: Monkey > Squirrel > Dog</span></span>
<span class="line"><span></span></span>
<span class="line"><span>Client: Who wants a Nut?</span></span>
<span class="line"><span>   Squirrel: I'll eat the Nut.</span></span>
<span class="line"><span>Client: Who wants a Banana?</span></span>
<span class="line"><span>   Monkey: I'll eat the Banana.</span></span>
<span class="line"><span>Client: Who wants a Cup of coffee?</span></span>
<span class="line"><span>   Cup of coffee was left untouched.</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br></div></div></details>
<h2 id="命令模式" tabindex="-1">命令模式 <a class="header-anchor" href="#命令模式" aria-label="Permalink to &quot;命令模式&quot;">&ZeroWidthSpace;</a></h2>
<p><a href="https://refactoringguru.cn/design-patterns/command" target="_blank" rel="noreferrer">命令设计模式</a> 适用于请求 组合 参数化 顺序 撤回等操作。</p>
<details class="details custom-block"><summary>Click to see more</summary>
<div class="language-Csharp vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">Csharp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p>运行结果</p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span></span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div></details>
<p>与适配器模式异同：</p>
<ul>
<li><strong>应用场景不同</strong>：
<ul>
<li>命令模式适用于需要将操作请求封装为对象，并且需要支持操作的撤销和重做、请求排队和日志记录的场景。</li>
<li>适配器模式适用于需要使用一个已经存在的类，但其接口不符合当前需求的情况。</li>
</ul>
</li>
<li><strong>实现方式不同</strong>：
<ul>
<li>在命令模式中，命令对象包含执行操作的方法，调用者通过调用命令对象的方法来执行操作。</li>
<li>在适配器模式中，适配器类实现目标接口，通过调用被适配者的方法来实现目标接口的方法。</li>
</ul>
</li>
</ul>
<h2 id="迭代器模式" tabindex="-1">迭代器模式 <a class="header-anchor" href="#迭代器模式" aria-label="Permalink to &quot;迭代器模式&quot;">&ZeroWidthSpace;</a></h2>
<h2 id="中介者模式" tabindex="-1">中介者模式 <a class="header-anchor" href="#中介者模式" aria-label="Permalink to &quot;中介者模式&quot;">&ZeroWidthSpace;</a></h2>
<h2 id="备忘录模式" tabindex="-1">备忘录模式 <a class="header-anchor" href="#备忘录模式" aria-label="Permalink to &quot;备忘录模式&quot;">&ZeroWidthSpace;</a></h2>
<h2 id="观察者模式" tabindex="-1">观察者模式 <a class="header-anchor" href="#观察者模式" aria-label="Permalink to &quot;观察者模式&quot;">&ZeroWidthSpace;</a></h2>
<p>比较依赖C#中的委托，如果使用python这种，
就是实现了一个订阅机制， 可在对象事件发生时通知多个 “观察” 该对象的其他对象</p>
<ol>
<li>一个用于存储订阅者对象引用的列表成员变量；
<ul>
<li>订阅者需要实现统一的接收订阅的接口，接口中必须声明通知方法及其参数</li>
<li>tips：可使用C#的接口实现试试</li>
</ul>
</li>
<li>几个用于添加或删除该列表中订阅者的公有方法。
<ul>
<li>发布者必须仅通过订阅者接口与它们进行交互</li>
<li>将订阅逻辑放入一个独立的对象， 上下文也可以放进去，然后让所有实际订阅者使用该对象，而不是直接用发布者去操作订阅者
订阅者的通知顺序是随机的。C#中的委托执行顺序是绑定顺序，所以不要往订阅者传可变的引用对象，不安全。</li>
</ul>
</li>
</ol>
<details class="details custom-block"><summary>Click to see more</summary>
<div class="language-Csharp vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">Csharp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">namespace</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> DesignPatterns</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//教程给的是猫鼠  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Animal</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    protected</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> string</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Name</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Animal</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">string</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> name</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {        </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        this</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.Name </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> name;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Cat</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> : </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Animal</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> delegate</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Publisher</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 声明函数指针类型  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Publisher</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> come_publisher</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 声明函数指针变量  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Cat</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">string</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> name</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">):</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">base</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(name)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {        </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">WriteLine</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">$"Create a Cat {</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">name</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">}"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> ComeThere</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {        </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">WriteLine</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">$"{</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Name</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">} Cat come there"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        come_publisher</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">?</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Invoke</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Mouse</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> : </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Animal</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Mouse</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">string</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> name</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Cat</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> c</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">):</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">base</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(name)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {        </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">WriteLine</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">$"Create a Mouse {</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">name</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">}"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        c.come_publisher </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Run; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 在管理对象中注册  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Run</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {        Console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">WriteLine</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">$"{</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Name</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">} Mouse runing "</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }}</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Program</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    static</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Main</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">string</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[] </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">args</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {   </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">WriteLine</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"-----------------观察者模式-----------------"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        // 猫鼠模型  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        Cat</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> c</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Cat</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"好猫"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        Mouse</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> m1</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Mouse</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"鼠1"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,c);  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        Mouse</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> m2</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Mouse</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"鼠2"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,c);  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        Mouse</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> m3</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Mouse</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"鼠3"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,c);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        c.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">ComeThere</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br><span class="line-number">50</span><br><span class="line-number">51</span><br><span class="line-number">52</span><br><span class="line-number">53</span><br><span class="line-number">54</span><br><span class="line-number">55</span><br><span class="line-number">56</span><br><span class="line-number">57</span><br><span class="line-number">58</span><br></div></div><p>运行结果</p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>-----------------观察者模式-----------------</span></span>
<span class="line"><span>Create a Cat 好猫</span></span>
<span class="line"><span>Create a Mouse 鼠1</span></span>
<span class="line"><span>Create a Mouse 鼠2</span></span>
<span class="line"><span>Create a Mouse 鼠3</span></span>
<span class="line"><span>好猫 Cat come there</span></span>
<span class="line"><span>鼠1 Mouse runing </span></span>
<span class="line"><span>鼠2 Mouse runing </span></span>
<span class="line"><span>鼠3 Mouse runing</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br></div></div></details>
<h2 id="状态模式" tabindex="-1">状态模式 <a class="header-anchor" href="#状态模式" aria-label="Permalink to &quot;状态模式&quot;">&ZeroWidthSpace;</a></h2>
<h2 id="策略模式" tabindex="-1">策略模式 <a class="header-anchor" href="#策略模式" aria-label="Permalink to &quot;策略模式&quot;">&ZeroWidthSpace;</a></h2>
<p><a href="https://refactoringguru.cn/design-patterns/strategy" target="_blank" rel="noreferrer">策略设计模式</a>
策略模式是让代码更松耦合的方式，提前预判代码会比较复杂会有多种方式采取的策略。其实就是原先分各个函数会把一个类弄的过于复杂，就拆分多个工具类使用多态单独处理。策略使用接口和多态实现添加新的策略处理类的时候不需要动原先的代码，只需要传入新的策略类就可以了</p>
<details class="details custom-block"><summary>Click to see more</summary>
<div class="language-Csharp vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">Csharp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">namespace</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> DesignPatterns</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Context</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    private</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> IStrategy</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> _strategy</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Context</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    { }  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Context</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">IStrategy</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> strategy</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {        </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">this</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">._strategy </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> strategy;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> SetStrategy</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">IStrategy</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> strategy</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  设置策略处理类  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        this</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">._strategy </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> strategy;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> DoSomeBusinessLogic</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {        Console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">WriteLine</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Context: Sorting data using the strategy (not sure how it'll do it)"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        var</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> result</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> this</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">._strategy.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">DoAlgorithm</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> List</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">string</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">> { </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"a"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"b"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"c"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"d"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"e"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> }); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  添加新的策略的时候不需要更改此代码，此处同时也是多态的体现  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        string</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> resultStr</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> string</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.Empty;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        foreach</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">var</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> element</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> in</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> result </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">as</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> List</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">string</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        {            resultStr </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> element </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> ","</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        }  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">WriteLine</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(resultStr);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }}  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> interface</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> IStrategy</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> // 声明了接口  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    object</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> DoAlgorithm</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">object</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> data</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  声明接口函数  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> ConcreteStrategyA</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> : </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">IStrategy</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  //  继承接口  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> object</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> DoAlgorithm</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">object</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> data</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {        </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">var</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> list</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> data </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">as</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> List</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">string</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  转型一下  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        list.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Sort</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> list;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }}  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> ConcreteStrategyB</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> : </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">IStrategy</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> object</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> DoAlgorithm</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">object</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> data</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {        </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">var</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> list</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> data </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">as</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> List</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">string</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        list.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Sort</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        list.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Reverse</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> list;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }}  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> StrategyPatterns</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Run</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {        </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">var</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> context</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Context</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">WriteLine</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Client: Strategy is set to normal sorting."</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        context.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">SetStrategy</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> ConcreteStrategyA</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">());  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        context.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">DoSomeBusinessLogic</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">WriteLine</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">WriteLine</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Client: Strategy is set to reverse sorting."</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        context.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">SetStrategy</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> ConcreteStrategyB</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">());  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        context.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">DoSomeBusinessLogic</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br><span class="line-number">50</span><br><span class="line-number">51</span><br><span class="line-number">52</span><br><span class="line-number">53</span><br><span class="line-number">54</span><br><span class="line-number">55</span><br><span class="line-number">56</span><br><span class="line-number">57</span><br><span class="line-number">58</span><br><span class="line-number">59</span><br><span class="line-number">60</span><br><span class="line-number">61</span><br><span class="line-number">62</span><br><span class="line-number">63</span><br><span class="line-number">64</span><br><span class="line-number">65</span><br></div></div><p>运行结果</p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span></span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div></details>
<h2 id="模板方法模式" tabindex="-1">模板方法模式 <a class="header-anchor" href="#模板方法模式" aria-label="Permalink to &quot;模板方法模式&quot;">&ZeroWidthSpace;</a></h2>
<h2 id="访问者模式" tabindex="-1">访问者模式 <a class="header-anchor" href="#访问者模式" aria-label="Permalink to &quot;访问者模式&quot;">&ZeroWidthSpace;</a></h2>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[EP5-其他]]></title>
            <link>http://ooowl.fun/blogs/Web%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/EP5-%E5%85%B6%E4%BB%96.html</link>
            <guid isPermaLink="false">http://ooowl.fun/blogs/Web%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/EP5-%E5%85%B6%E4%BB%96.html</guid>
            <pubDate>Mon, 06 May 2024 20:52:54 GMT</pubDate>
            <content:encoded><![CDATA[<h1 id="ep5-其他" tabindex="-1">EP5-其他 <a class="header-anchor" href="#ep5-其他" aria-label="Permalink to &quot;EP5-其他&quot;">&ZeroWidthSpace;</a></h1><p class="article-meta">创建于 2024年5月7日 04:52:54 · 约16字</p>
<h2 id="状态机" tabindex="-1">状态机 <a class="header-anchor" href="#状态机" aria-label="Permalink to &quot;状态机&quot;">&ZeroWidthSpace;</a></h2>
<p>分为无限状态机和有限状态机</p>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[EP1-设计模式]]></title>
            <link>http://ooowl.fun/blogs/Web%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/EP1-%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F.html</link>
            <guid isPermaLink="false">http://ooowl.fun/blogs/Web%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/EP1-%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F.html</guid>
            <pubDate>Mon, 06 May 2024 20:45:43 GMT</pubDate>
            <content:encoded><![CDATA[<h1 id="ep1-设计模式" tabindex="-1">EP1-设计模式 <a class="header-anchor" href="#ep1-设计模式" aria-label="Permalink to &quot;EP1-设计模式&quot;">&ZeroWidthSpace;</a></h1><p class="article-meta">创建于 2024年5月7日 04:45:43 · 约380字</p>
<p>设计模式是为了代码的复用和扩展而进行提前的通用结构设计，详细的有23种甚至更多，但是实际用到的不会那么多。
在这里先罗列出来主流所有的模式和简略的应用场景，后续的EP把用到的常用的都实现一下(实现的会打勾)，剩下的用到了再实现。</p>
<ul>
<li>创建型模式
<ul>
<li>[x] 工厂方法模式9</li>
<li>[x] 抽象工厂模式</li>
<li>[ ] 生成器模式</li>
<li>[ ] 原型模式</li>
<li>[x] 单例模式</li>
</ul>
</li>
<li>结构型模式
<ul>
<li>[x] 适配器模式</li>
<li>[ ] 桥接模式</li>
<li>[ ] 组合模式</li>
<li>[ ] 装饰模式</li>
<li>[ ] 外观模式</li>
<li>[ ] 享元模式</li>
<li>[ ] 代理模式</li>
</ul>
</li>
<li>行为模式
<ul>
<li>[x] 责任链模式</li>
<li>[ ] 命令模式</li>
<li>[ ] 迭代器模式</li>
<li>[ ] 中介者模式</li>
<li>[ ] 备忘录模式</li>
<li>[x] 观察者模式</li>
<li>[ ] 状态模式</li>
<li>[ ] 策略模式</li>
<li>[ ] 模板方法模式</li>
<li>[ ] 访问者模式</li>
</ul>
</li>
<li>其他
<ul>
<li>[ ] 状态机</li>
</ul>
</li>
</ul>
<p>创建型模式提供创建对象的机制， 能够提升已有代码的灵活性和可复用性。<br>
结构型模式介绍如何将对象和类组装成较大的结构， 并同时保持结构的灵活和高效。<br>
行为模式负责对象间的高效沟通和职责委派。</p>
<p>之前在py中py太动态了，很多设计模式看的时候感觉卵用没有，因为可能就是个判断赋值的事，最多手动维护一下类型列表。<br>
静态语言才发现有这些夭蛾子</p>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Unity-基础知识]]></title>
            <link>http://ooowl.fun/blogs/Game/Unity/Unity-%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86.html</link>
            <guid isPermaLink="false">http://ooowl.fun/blogs/Game/Unity/Unity-%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86.html</guid>
            <pubDate>Sat, 02 Mar 2024 23:29:36 GMT</pubDate>
            <description><![CDATA[很多都是参数介绍，看的时候打开Unity对着面板看一眼 工程文件夹都是干什么的，以及需要版本管理的文件夹。初始化推送后，拷贝项目到新电脑并拉取即可同步。官方推荐的管理github/Unity.gitignore 在一个unity项目中，不要把 .sln / .csproj 加入 git，在任何电脑、任何平台，它们都会被 Unity 自动重新生成]]></description>
            <content:encoded><![CDATA[<h1 id="unity-基础知识" tabindex="-1">Unity-基础知识 <a class="header-anchor" href="#unity-基础知识" aria-label="Permalink to &quot;Unity-基础知识&quot;">&ZeroWidthSpace;</a></h1><p class="article-meta">创建于 2024年3月3日 07:29:36 · 约36,713字</p>
<h2 id="常识" tabindex="-1">常识 <a class="header-anchor" href="#常识" aria-label="Permalink to &quot;常识&quot;">&ZeroWidthSpace;</a></h2>
<p><strong>很多都是参数介绍，看的时候打开Unity对着面板看一眼</strong><br>
工程文件夹都是干什么的，以及需要版本管理的文件夹。初始化推送后，拷贝项目到新电脑并拉取即可同步。官方推荐的管理<a href="https://github.com/github/gitignore/blob/main/Unity.gitignore" target="_blank" rel="noreferrer">github/Unity.gitignore</a><br>
在一个unity项目中，不要把 .sln / .csproj 加入 git，在任何电脑、任何平台，它们都会被 Unity 自动重新生成</p>
<div class="language-C vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">C</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">├── Assets</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> // 美术脚本主要工程文件，只要它不丢，其余文件删除后打开Unity会自动重建，加入Git</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">│   ├── ArtRes</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> // 原始美术资源，可不加入Git！</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">│   ├── UsedArtRes</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> // 从ArtRes中拖出使用资源避免直接修改原始资源</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">│   └── other_folder...</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">├── Library</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> // 库文件夹PackageCache中的包为Unity自动下载，缺失时重新打开项目会自动恢复</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">├── Logs</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> // 日志文件夹，记录特殊运行信息</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">├── Packages</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> // 包配置信息，建议加入Git</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">├── ProjectSettings</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> // 工程设置信息，删后重建会丢失自定义配置，必须加入Git</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">├── Temp</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">├── UserSettings</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> // 用户设置，建议加入Git</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">├── AssetBundles</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">├── Assembly</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">CSharp</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Editor.csproj</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">├── Assembly</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">CSharp.csproj</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">├── Client.sln</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">└── Client.sln.DotSettings</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> // vscode的个人配置，有的话记得不要跟踪</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br></div></div><details class="details custom-block"><summary>示例.gitignore</summary>
<p>例.gitignore</p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>.idea/</span></span>
<span class="line"><span>.vscode/</span></span>
<span class="line"><span>.vs/</span></span>
<span class="line"><span>.DS_Store</span></span>
<span class="line"><span>Thumbs.db</span></span>
<span class="line"><span></span></span>
<span class="line"><span>Logs/</span></span>
<span class="line"><span>obj</span></span>
<span class="line"><span>Temp</span></span>
<span class="line"><span>Library</span></span>
<span class="line"><span>AssetsBundles</span></span>
<span class="line"><span>Assembly-CSharp.csproj</span></span>
<span class="line"><span>Assembly-CSharp-Editor.csproj</span></span>
<span class="line"><span>Client.sln</span></span>
<span class="line"><span>Client.sln.DotSettings</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br></div></div><p><code>.vscode/settings.json</code>配置</p>
<div class="language-json vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">json</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">"files.exclude"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: { </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">"**/*.meta"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div></details>
<p>重要的几个面板</p>
<ul>
<li>Hierachy所有游戏中对象的层级面板</li>
<li>Scene当前的游戏场景</li>
<li>Game当前游戏画面</li>
<li>Project项目中的所有资源</li>
<li>Inspector某一个对象/资源的属性</li>
<li>Window-&gt;Package Manager 管理安装的第三方包</li>
<li>给unity添加一些组件现在是在File-&gt;BuildSettings里面找到</li>
</ul>
<p>Scene中常用快捷键</p>
<ul>
<li>alt+滚轮缩放</li>
<li>alt长按可以围着视觉中心 转</li>
<li>鼠标右键+wasd移动(shift可以加速)</li>
<li>鼠标中键 原地不动360度拖动场景</li>
<li>ctrl+D快速复制</li>
<li>F2快速改名</li>
<li>ctrl+shift+F快速对焦摄像机到编辑模式视窗</li>
<li>按住V可以选择顶点吸附，<strong>双击鼠标中键或F键可以定位场景内的物体</strong></li>
</ul>
<h3 id="面板" tabindex="-1">面板 <a class="header-anchor" href="#面板" aria-label="Permalink to &quot;面板&quot;">&ZeroWidthSpace;</a></h3>
<p>Scene的工具栏中比较重要的几个<br>
shading mode，默认shader渲染，可以切换网格/混合渲染，后面的是2D视图 声 光 特效 辅助线开关，摄像机调整。<br>
Gizmos是用来设置Scene中不同类型的GameObject图标的, 一般这个工具栏的东西都不用特殊调整。<br>
轴向以屏幕为参照物:</p>
<ul>
<li>垂直屏幕向内为Z正方向</li>
<li>平行屏幕向右为X正方向</li>
<li>平行屏幕向上为Y正方向
操作物体工具栏的快捷键竟然是QWERTY（????<br>
可以切换操作物体的轴是以<strong>自己为准</strong>还是以<strong>世界坐标</strong>为准，按单位移动需要使用世界坐标，按住ctrl按单位移动的精细一些。<br>
使用Global的时候更改旋转座标始终不变看看是不是用错了Gizmo<br>
使用pivot或者center，可以切换transform是以对象组的<strong>根对象为中心</strong>还是<strong>对象组的中心</strong><br>
眼睛和手是是否可以看见和是否可选中</li>
</ul>
<p>Game界面⏯是<strong>逐帧播放</strong>，status是渲染详细信息<br>
project的更多选项(三个点)可以切换界面显示方式，可以选择两列显示,Asset alt缩放到最小按照行显示</p>
<p>Inspector面板，可以设置在场景设置中的图标，<strong>Layer系统和Tag系统可以给对象分类</strong>，可以在更多中设置Debug显示更多信息方便调试<br>
注意 <mark>Inspector设置的值会覆盖C#脚本的初始值</mark></p>
<p>顶栏菜单额外嘱咐的</p>
<ul>
<li>Edit-&gt;Selection: alt+ctrl+1 编队(save selection 1) shift+ctrl+1 选中编队(load selection 1) 在mac上是command</li>
<li>Edit-&gt;<strong>ProjectSetting</strong>设置保存到Asset同级的文件夹ProjectSetting</li>
<li>Edit-&gt;Preferences</li>
<li>Assets-&gt;import/export package</li>
<li>GameObject-&gt;ctrl+shift+F把对象(大部分时候是摄像机)视角和当前的Scene视角重合</li>
<li>Window-&gt;General上述几个窗口都在里面显示</li>
<li>Window-&gt;Analyze-&gt;Profiler 这是性能监控器</li>
</ul>
<p>对象关系<br>
transform是最基本的位置信息。物体拿到手transform先归零好判断位置，子对象的transform是针对父对象来说的，会根据父对象变化而变化。<br>
unity的基本单位是米，体积是基本单位就是立方米，质量的基本单位是kg
<a href="https://docs.unity.cn/cn/2022.3/Manual/CreatingDCCAssets.html" target="_blank" rel="noreferrer">在 Unity 外部创建模型规范 - Unity 手册</a></p>
<div class="warning custom-block"><p class="custom-block-title">[⚠️Warning]</p>
<p>游戏是数据的一种体现，利用程序把美术和数据组织起来<br/>
无论是美术还是自己拼模型，<strong>模型的正方向一定是Z轴的正方向，也就是垂直纸面向内。和开发者的目光齐平，缩放单位要注意！</strong><br/>
骨骼-非必须，有动作的模型才需要<br/>
网格面片-必须，决定了模型的轮廓<br/>
贴图-必须，决定了模型的颜色效果<br/>
官方推荐使用fbx格式的模型文件其它格式虽然支持，但是不推荐。<code>[.fbx .dae .3ds .dxf .obj]</code><br/>
导入完之后看看他有没有做好了预设体，别傻乎乎自己再去重复劳动<br/>
最好使用空物体作为总的父对象，容易控制缩放<br/>
美术给的资源最好不要直接改，拖一份复制到工作文件夹。<br/>
一般和模型搭配的武器等，会预留一个节点拖上去之后重置位置就应该是匹配好的<br/>
拼UI的时候，一般会给一张美术底图，垫在底下照着拼。</p>
</div>
<h2 id="基础操作" tabindex="-1">基础操作 <a class="header-anchor" href="#基础操作" aria-label="Permalink to &quot;基础操作&quot;">&ZeroWidthSpace;</a></h2>
<p>Unity利用<strong>反射</strong>获取 <strong>场景中(Scene.unity)</strong> 的所有自定义的 GameObject和挂载其上的脚本，所有的特征都是GameObject +Component呈现出来的<br>
场景的本质是记录了 GameObject和关联的信息存起来的文件，后缀是Scene.unity 把两个场景都拖到Hierachy中可以让场景叠加显示，一般只有互相copy的时候才这么干<br>
public的属性能在inspector上编辑，加上<code>[HideInspector]</code>就隐藏了；private的和protected不能被显示，加上<code>[SerializeField]</code>也可以被显示<br>
自定义的结构体和类对象使用<code>[System.Serializable]</code>就可以被显示了。<br>
已经挂到 GameObject修改了脚本的值对象上挂载的那个不会被更改，手动或者重挂，也可以运行过程中可以用Inspector-&gt;copy和paste脚本，但是一般不会这么做<br>
departure的方法如果硬要用会报错，但是传第二个参数为false就可以继续用虽然不推荐<br>
<a href="https://docs.unity3d.com/2022.3/Documentation/Manual/PlatformDependentCompilation.html" target="_blank" rel="noreferrer">untiy支持的宏</a>（可恶要变成宏孩儿了吗</p>
<div class="tip custom-block"><p class="custom-block-title">[💡Tip]</p>
<p>其实直接拖对象有点破坏面向对象思想，尤其是多人合作依赖关系容易变成一坨，而且从外边拖进来的你还没法从代码直接点过去<br>
代码Find之后再改效率不如拖高，因为不用查找(其实查找也查找不了几个最多在自己的子去查找)<br>
在Editor绑定的好处是程序做完了，给个毛坯给策划，让他们自己去精装，把体力活交给策划，程序只负责实现功能就行了。</p>
</div>
<details class="details custom-block"><summary>还有一些attributes不太重要的有个印象就行</summary>
<p>有一些attributes不太重要的有个印象就行</p>
<ol>
<li>为变量分组<code>[Header(&quot;分组说明&quot;)]</code><br/></li>
<li>为变量添加鼠标悬停说明<code>[Tooltip(&quot;说明内容&quot;)]</code><br/></li>
<li>让两个字段间出现一点间隔<code>[Space()]</code><br/></li>
<li>数值变为使用滑动条范围设置<code>[Range(最小值, 最大值)]</code><br/></li>
<li>显示框大一点，默认不写参数时显示3行，写参数则对应显示相应行数<code>[Multiline(4)]</code><br/></li>
<li>也是显示框默认不写参数时超过3行显示滚动条；可以指定最少和最多显示行数，超过最大行数则显示滚动条<code>[TextArea(3, 4)]</code><br/></li>
<li>右键变量的时候执行方法function(无返回值无参)<code>[ContextMenuItem(&quot;右键显示啥名&quot;, &quot;function&quot;)]</code><br/></li>
<li>为方法添加特性能够在Inspector中直接点更多去执行<code>[ContextMenu(&quot;测试函数&quot;)]</code><br/></li>
</ol>
</details>
<h3 id="perfab" tabindex="-1">Perfab <a class="header-anchor" href="#perfab" aria-label="Permalink to &quot;Perfab&quot;">&ZeroWidthSpace;</a></h3>
<p>Perfab的存储规则和Scene是一样的，C#脚本组件任何东西都一块保存。<br>
在Inspector面板中可以把当前选中的预设体的更改<strong>保存到预制体或者放弃更改</strong>，<strong>重新拖进Assets中是覆盖</strong>。如果删除或者修改已有预设体，那所有的预设体都会被修改<br>
在场景中直接unpack prefab然后编辑，再拖进Assets搞个新的。把未修改预设体拖回去是复制一个一模一样的预制体。如果预设体被删除但是场景中已经使用了，就会变红提示，不想要就直接unpack。<br>
prefab的unpack和unpack cmoplete是选择是否解开子物体的预制体(如果子物体是prefab的话)</p>
<h3 id="组件" tabindex="-1">组件 <a class="header-anchor" href="#组件" aria-label="Permalink to &quot;组件&quot;">&ZeroWidthSpace;</a></h3>
<div class="warning custom-block"><p class="custom-block-title">[⚠️Warning]</p>
<p>在Unity中类名和文件名必须一致，因为是通过反射字符串去获取类和自定义组件的</p>
</div>
<p>自己写的脚本实际上也是组件(Component)<strong>继承了MonoBehaviour的都是组件</strong>。 一个脚本可以挂在同一个对象多次，也就会创建多个脚本对象，可以脚本中开<code>[DisallowMultipleComponent]</code>特性就不能一挂多了。其实本质是拖过去的时候通过反射获取文件的名字，然后根据名字字符串拿到对应类<br>
MonoBehaviour的继承链是<code>MonoBehaviour &lt;- Behaviour &lt;- Component</code> ，继承Component的就是组件。当然可以继续继承<br>
集成了MonoBehaviour的类只能挂载不能new，不能自定构造函数。
在Inspector-&gt;ExecutionOrder中其实可以规定执行顺序的，默认顺序是不确定的，<code>Editor/Data/Resources/ScriptTemplates</code>可以修改默认脚本模板，这俩一般不用特意改。</p>
<h3 id="生命周期" tabindex="-1">生命周期 <a class="header-anchor" href="#生命周期" aria-label="Permalink to &quot;生命周期&quot;">&ZeroWidthSpace;</a></h3>
<p>人眼舒适放松时候看电影可视帧数是24fps而动态交互类的一般是60fps，游戏卡顿的原因就是一帧内的计算量过大没法处理完所有的游戏逻辑。<br>
生命周期函数(<strong>是按下面顺序执行的！！！！</strong>)：</p>
<ol>
<li><strong>Awake</strong>：首次被产生执行一次,再次启用就不会执行(如果生产对象是一开始inactivate的，那也不会执行)</li>
<li>OnEnable:  依附的GameObject每次activate时调用，可以用来Fetch资源</li>
<li><strong>Start</strong>：从自己被创建出来后，第一次帧更新之前调用只会调用一次</li>
<li>FixedUpdate: 固定时间(0.2)刷新一次，可在edit-&gt;project setting-&gt;time更改间隔</li>
<li><strong>Update</strong>: 每帧执行一次(注意性能
<ul>
<li><strong>Unity在这两个生命周期之间进行动画系统的更新</strong></li>
</ul>
</li>
<li>LateUptedate: 每帧后执行一次
<ul>
<li>所以为了渲染效果一般在这里更新摄像机的位移</li>
</ul>
</li>
<li>OnDisable： 依附的GameObject每次禁用activate事件执行，在OnDestroy时也会执行一次</li>
<li><strong>OnDestroy</strong>：销毁的时候执行</li>
</ol>
<p>生命周期函数是支持继承和多态的， 子类继承类之后进行override就可以。<br>
但是生命周期函数却不是从基类中override过来的<br>
如果生命周期无法满足需求那就需要使用任务调度，时间任务调度函数<code>Invoke</code> <code>InvokeRepeating</code> <code>CancelInvoke</code> (参数都简单易懂</p>
<details class="details custom-block"><summary>生命周期</summary>
<p>命周期</p>
<div class="language-Csharp vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">Csharp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">using</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> System</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">using</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> System</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Collections</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">using</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> System</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Collections</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Generic</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">using</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> UnityEngine</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> TestLifeCycle</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> : </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">MonoBehaviour</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Awake</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">() </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 首次被产生或者从不可见变为可见的前(核心就是首次启用)执行一次,再次启用就不会执行，例如查找资源用  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Debug.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"I'm awake"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    private</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> OnEnable</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">() </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  每次启用前的函数，可以用来Fetch资源  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Debug.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"I'm Ready!"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }    </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Start</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">() </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// GameObject加载完毕后所有的Awake执行完的第一帧执行一次  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Debug.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"I'm Start First Time!"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    private</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> float</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> timedelta</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 0.2f</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> FixedUpdate</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {        </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Debug.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">$"every {</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">timedelta</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">} second Update once"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }    </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// Update is called once per frame  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Update</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {        </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Debug.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"frame start"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> LateUpdate</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  每帧之后  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Debug.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"frame end"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> OnDisable</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {        </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Debug.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"I'm Disabled"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> OnDestroy</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {        </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Debug.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"I'm Destory"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br></div></div><p>运行结果</p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>[21:35:31] I'm awake</span></span>
<span class="line"><span>[21:35:31] I'm Ready!</span></span>
<span class="line"><span>[21:35:31] Object start successfully Complete</span></span>
<span class="line"><span>[21:35:44] every 0.2 second Update once</span></span>
<span class="line"><span>[21:35:44] frame start</span></span>
<span class="line"><span>[21:35:44] frame end</span></span>
<span class="line"><span>[21:35:40] be Invoked</span></span>
<span class="line"><span>[21:35:35] be Invoked Hello, World!</span></span>
<span class="line"><span>[21:35:42] Invoke is Canceled</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br></div></div></details>
<h3 id="获取组件" tabindex="-1">获取组件 <a class="header-anchor" href="#获取组件" aria-label="Permalink to &quot;获取组件&quot;">&ZeroWidthSpace;</a></h3>
<p>MonoBehaviour内置的重要变量，它能获得什么属性去IDE里看，稍微列一下最常用的，不赘述。this不是依附的GameObject<br>
Component中声明的(this.)<code>gameObject</code>可以直接使用，这个对象就是脚本挂载的对象。transform是获取位置信息<br>
如果要获得其他的GameObject挂载脚本的对象，声明一个对应类然后把对象拖过去就可以。获得GameObject上的其他的 Component有一系列方法，参考一下，最常用的是根据泛型获得</p>
<details class="details custom-block"><summary>如何获取GameObject身上的组件</summary>
<p>何获取GameObject身上的组件</p>
<div class="language-Csharp vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">Csharp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Start</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(gameObject.name);</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  挂载GameObject的名字  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">this</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.transform.position);</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  对象的位置  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">this</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.transform.eulerAngles);</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  旋转欧拉角  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">this</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.transform.lossyScale);</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  缩放  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">this</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.enabled);</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 脚本是否被启用  </span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    // 获得其他组件</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    GTest</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> g1</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> this</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetComponent</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"GTest"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">as</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> GTest</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  通过名字获得  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    GTest</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> g2</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> this</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetComponent</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">typeof</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GTest</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">as</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> GTest</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  通过类型获得  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    GTest</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> g3</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> this</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetComponent</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GTest</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>(); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  ⭐️通过泛型获得  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    GTest</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[] </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">g4</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> this</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetComponents</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GTest</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>(); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 获得多个，但是无法确定是哪一个  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    GTest</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[] </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">g5</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> GetComponentsInChildren</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GTest</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 递归查找所有子对象包括自己的组件,参数代表要不要查找未激活的对象的  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    GTest</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[] </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">g6</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> GetComponentsInParent</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GTest</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 递归查找所有父对象包括自己的组件,参数代表要不要查找未激活的对象的  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    GTest</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> gt</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    bool</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> exists</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> TryGetComponent</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GTest</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">out</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> gt); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 尝试获得，返回值是bool</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br></div></div></details>
<hr>
<h2 id="monobehaviour内置属性" tabindex="-1">MonoBehaviour内置属性 <a class="header-anchor" href="#monobehaviour内置属性" aria-label="Permalink to &quot;MonoBehaviour内置属性&quot;">&ZeroWidthSpace;</a></h2>
<div class="danger custom-block"><p class="custom-block-title">[🚨Danger] 变量的构造使用</p>
<p>量的构造使用
在MonoBehaviour的子类中，变量声明是早于所有的生命周期函数的，所以基本不会在变量声明里面赋值引用类型，因为有可能使用未声明的变量。<br/>
所以赋值都是放到声明周期函数中。<br/>
Unity中的脚本加载顺序是随机的，同时在场景上挂载两个你不能控制哪个先运行，所以如果有变量的依赖可以使用事件通知或者协程异步的方式去加载。</p>
</div>
<h3 id="gameobject" tabindex="-1">GameObject <a class="header-anchor" href="#gameobject" aria-label="Permalink to &quot;GameObject&quot;">&ZeroWidthSpace;</a></h3>
<p>GameObject的一些静态方法。<br>
可以直接申请一个对象然后拖进去(最常用的)，或者使用下面的方法查找<br>
常用的属性和查找对象是找不到incativate的对象的，如果场景中多个满足条件的对象，则无法确定是哪个<br>
动态创建对象，先拖过去获取 GameObject然后使用<code>GameObject.Instantiate(obj)</code>初始化新的，名字会带(Clone)<br>
<code>GameObject.Destory(obj)</code>可以动态删除对象甚至可以删除附加的脚本，实际上是下一帧移除的，立即从内存中移除需要使用<code>GameObject.DestroyImmediate(mycube);</code><br>
<code>DonotDestoryOnLoad(obj)</code>只能作用于根层级<br>
这俩函数实际上有很多重载方法。<br>
默认切换场景的时候之前的都被移除了，如果不想某对象换场景被移除，使用<code>GameObject.DontDestroyOnLoad(this.gameObject);</code>最常用的就是传自己</p>
<details class="details custom-block"><summary>GameObject的操作</summary>
<p>ameObject的操作</p>
<div class="language-Csharp vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">Csharp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> L4Script</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> : </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">MonoBehaviour</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    private</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> GameObject</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> mycube</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> GameObject</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> find</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> GameObject</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[] </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">finds</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> GameObject</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> dynamicObj</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> GameObject</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> dynamicObjClone</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Start</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {        </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Debug.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(gameObject.name);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Debug.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(gameObject.isStatic);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Debug.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(gameObject.activeSelf);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Debug.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(gameObject.layer); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 这返回的其实是个整数  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Debug.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(gameObject.tag);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Debug.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(gameObject.transform.position);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        mycube</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">GameObject.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">CreatePrimitive</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(PrimitiveType.Cube); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 和右键点击创建一样，也能创建其他类型  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        mycube.name </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "xx"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        mycube.tag </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "Monster"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        // 查找 是找不到失活对象，如果场景中多个满足条件的对象，则无法确定是哪个  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        find </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> GameObject.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Find</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"xx"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  需要遍历所有对象，运行效率比较低 一般不这么找  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        find </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> transform.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Find</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"xy"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 只寻找自己的子对象，在子对象和坐标那有详细的</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        find </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> GameObject.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">FindWithTag</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Monster"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  一样FindGameObjectWithTag  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        finds </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> GameObject.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">FindGameObjectsWithTag</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Monsters"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 只有通过tag查找能找到多个对象  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        L4Script</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> l4</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> FindObjectOfType</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">L4Script</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>(); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// UnityEngine.Object的查找更费劲，不仅遍历对象还遍历脚本  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        dynamicObjClone</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">GameObject.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Instantiate</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(dynamicObj); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 获取到对象然后初始化的方法  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        GameObject.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Destroy</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(dynamicObjClone,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">5</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 五秒后删除  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        GameObject.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Destroy</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">this</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  甚至可以删除附加的脚本  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        GameObject.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">DestroyImmediate</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(mycube);</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 立即从内存中移除，更可能会卡顿  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        GameObject.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">DontDestroyOnLoad</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">this</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.gameObject);</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 最常用的就是传自己  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br></div></div></details>
<p>当你new GameObject的时候实际上就创建了一个 空物体 甚至创建之后可以挂脚本。甚至脚本中套娃创建都能执行<br>
动态的为对象添加组件(脚本也是组件)，拿到组件就可以更改组件的属性，从而控制行为。</p>
<details class="details custom-block"><summary>动态创建GameObject</summary>
<p>态创建GameObject</p>
<div class="language-Csharp vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">Csharp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Start</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">() </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    GameObject</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> ng1</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> GameObject</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"我创建的新的空对象"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 创建了一个新的 空对象  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    ng1.name </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "我创建的新的空对象1"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    GameObject</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> ng2</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> GameObject</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"我创建的新的空对象"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">typeof</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GTest</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">));  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    GTest</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> gt1</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">ng1.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">AddComponent</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">typeof</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GTest</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">as</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> GTest</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 动态添加组件  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    GTest</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> gt2</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">ng1.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">AddComponent</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GTest</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>(); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 使用泛型动态添加组件更常用  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    Debug.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"success init"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (find.tag </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">==</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "Monster"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  标签比较  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        bool</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> TagEqual</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> find.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">CompareTag</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Monster"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 和上面的条件一样  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">$"Tag is Monster{</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">TagEqual</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">}"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    find.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">SetActive</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 激活函数不多说  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    find.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">SetActive</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br></div></div></details>
<div class="info custom-block"><p class="custom-block-title">[ℹ️Info] 不常用的报个菜名</p>
<p>常用的报个菜名
<code>this.gameObject.SendMessage(&quot;TestFun&quot;);</code>通过反射去动态调用这个 GameObject脚本上的函数<br/>
<code>this.gameobject.BroadcastMessage(&quot;func&quot;);</code>广播行为 让自己和自己的子对象执行<br/>
<code>this.gameobject.SendMessageupwards(&quot;func&quot;);</code>向父对象和自己发送消息并执行<br/></p>
</div>
<h4 id="tag和layer" tabindex="-1">tag和layer <a class="header-anchor" href="#tag和layer" aria-label="Permalink to &quot;tag和layer&quot;">&ZeroWidthSpace;</a></h4>
<p>每个GameObject都有这两个属性，可以在Inspector面板进行编辑，可以给Layer起名字。</p>
<div class="language-Csharp vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">Csharp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">obj.layer </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> LayerMask.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">NameToLayer</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"LayerA"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//给物体设置层</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">int</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> l</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">LayerMask.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">NameToLayer</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"UI"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// LayerToName</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Physics.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">OverlapBox</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(Vector3.zero,Vector3.one, Quaternion.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">AngleAxis</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">45</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,Vector3.up),   </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x3C;&#x3C;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">LayerMask.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">NameToLayer</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"UI"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">|</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x3C;&#x3C;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">LayerMask.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">NameToLayer</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Default"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 检测UI和Default层0000 0000 0000 0010 0001</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br></div></div><p>注意此处数字层的含义，这个int代表的是此层的二进制哪一位是1,unity一共32层，如果你要检测第五层和第1层，则需要如上述代码一样，将层数二进制左移对应数，然后两层进行或操作，这样用一个二进制就可以表示你想检测的所有层，unity内部会进行与操作再去检测</p>
<p><strong>SortingLayers</strong>相当于PS中层的概念，每个Object属于哪个层，最下面的从层最靠前</p>
<h3 id="time和mathf" tabindex="-1">Time和Mathf <a class="header-anchor" href="#time和mathf" aria-label="Permalink to &quot;Time和Mathf&quot;">&ZeroWidthSpace;</a></h3>
<p>在编辑模式下，是不限帧率的。Time用于游戏中参与位移、记时、时间暂停等，Mathf和Random都是Unity命名空间下的不是C#自带的<br>
<code>Random.Range(start,end)</code> 传浮点返浮点，传整数返整数；整数有头没尾，浮点有头有尾。</p>
<details class="details custom-block"><summary>Time的基本API用法</summary>
<p>ime的基本API用法</p>
<div class="language-Csharp vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">Csharp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Update</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    Time.timeScale </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1.0f</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 缩放倍数0的时候停止  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(Time.deltaTime); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 最近两帧间隔多长时间，稳定应该是 (1/帧率)S，主要是用来计算位移的 路程=时间*速度  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(Time.unscaledDeltaTime);</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 不受timeScale影响的帧间隔时间，如果希望游戏暂停了还跑的东西  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(Time.fixedTime);</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  两个FixedUpdate的间隔时间  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(Time.fixedDeltaTime); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 物理帧间隔，受scale影响  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(Time.fixedUnscaledDeltaTime); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 物理帧间隔，不受scale影响  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(Time.frameCount);</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 游戏到现在跑了多少帧了  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(Time.time);</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 游戏开始到现在过了多少时间  </span></span>
<span class="line"></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    // Random</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    Random.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Range</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(start,end)</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br></div></div></details>
<h4 id="mathf" tabindex="-1">Mathf <a class="header-anchor" href="#mathf" aria-label="Permalink to &quot;Mathf&quot;">&ZeroWidthSpace;</a></h4>
<p>Math是System中提供的数学<strong>类</strong>，而Mathf是unity提供的<strong>结构体</strong>，二次封装且多了一些游戏常用的，用他就行。<br>
取整数 直接类型转换 和 <code>Mathf.FloorToInt(9.6f)</code>是向下取整，而<code>CellToInt</code>是向上取整。</p>
<details class="details custom-block"><summary>数学库Mathf</summary>
<p>学库Mathf</p>
<div class="language-Csharp vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">Csharp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Mathf.PI  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Mathf.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Abs</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">10</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 取绝对值  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Mathf.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">CeilToInt</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1.00001f</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//向上取整 Mathf.FloorToInt(9.6f)//向下取整  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 钳制函数如果不超过区间就返回传入的数字，否则返回靠近的区间端点  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Mathf.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Clamp</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">10</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">11</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">20</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) Mathf.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Max</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Mathf.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Min</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1.1f</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0.4f</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Mathf.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Pow</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">4</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 一个数的n次幂  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Mathf.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">RoundToInt</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1.3f</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 四舍五入  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Mathf.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Sqrt</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">4</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 返回一个数的平方根  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Mathf.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">IsPowerOfTwo</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">4</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  判断一个数是否是2的n次方  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Mathf.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Sign</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  判断正负数</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 每帧改变start的值按照极限逼近lim </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">start </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Mathf.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Lerp</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(start, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">10</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, Time.deltaTime);</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  结果会线性跟随</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">time </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Time.deltaTime; </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">result </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Mathf.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Lerp</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(start, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">10</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, time);</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br></div></div></details>
<p>Lerp插值公式为<code>result = start + (end - start) * t;</code>其中t为速度系数，常用的两个调用方式取值如下两曲线，lim(每帧改变start)和线性(每帧改变t)<br/>
<img src="./static/Unity-基础知识_images_1.svg" alt="1100"></p>
<p>弧度rad即是<code>PI/180</code>，使用静态变量<code>Rad2Deg = 57.29578f;</code>，<code>Deg2Rad = 0.017453292f;</code>一乘即可和角度互相转换；<code>Mathf.Sin(r)</code>参数和返回值都是rad类型，可以传<code>30*Mathf.Deg2Rad</code></p>
<h3 id="transform" tabindex="-1">Transform <a class="header-anchor" href="#transform" aria-label="Permalink to &quot;Transform&quot;">&ZeroWidthSpace;</a></h3>
<p>Vector3是Unity内置的结构体，他不是类！默认值(0f,0f,0f)，初始化的时候传xy则z自动为0，默认的加减乘除就是对应坐标加减乘除，重载了哪些运算符点进去看。</p>
<h4 id="vector" tabindex="-1">Vector <a class="header-anchor" href="#vector" aria-label="Permalink to &quot;Vector&quot;">&ZeroWidthSpace;</a></h4>
<p>Vector是Unity中的结构体，可用的有Vector2 Vector3 Vector4。<br>
向量已经进行运算符的重载，使用B-A可以获得A指向B的向量，取反会三个方向都加负号，也就是指向反方向。<br>
使用<code>V.magnitude</code>直接获得向量的模长和<code>Vector3.Distance(Vector3.zero,V)</code>一样，也就是三维空间中的距离<code>Mathf.Sqrt(x^2+y^2+z^3)</code><br>
向量除自己的模长可以归一化为单位向量，使用<code>V.normalized</code>获得，和<code>V/V.magnitude</code>一样</p>
<details class="details custom-block"><summary>向量演示</summary>
<p>量演示</p>
<div class="language-Csharp vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">Csharp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Vector3.zero </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// (0, 0, 0) 零向量</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Vector3.right </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// (1, 0, 0)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Vector3.left </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// (-1, 0, 0)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Vector3.forward </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// (0, 0, 1)这是Unity的正方向</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Vector3.back </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// (0, 0, -1)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Vector3.up </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// (0, 1, 0)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Vector3.down </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// (0, -1, 0)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Vector3.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Distance</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(v1,v2)</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 计算两点之间的空间距离，和V.magnitude一样</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">V.normalized</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">==</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">V</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">/</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">V.magnitude </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  归一化 true</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">float</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> result</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Vector3.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Dot</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(A,B); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  A•B点乘的用法</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Vector3</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> V</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Vector3.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Cross</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(A,B) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// A*B叉乘的用法</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br></div></div></details>
<p><strong>点乘</strong> 获得的是对应坐标相乘再相加的一个标量，A•B的几何意义是B在A上的投影长度，因为AB是向量，所以可以用来判断AB的夹角&gt;0锐角=0直角&lt;0钝角。<br>
可以大致判断物体的方位，物体面朝向是A然后另一个物体的坐标是B，此时使用A•B就可以大致判断方位<br>
如果要做侦测是否在角度范围内,注意到<code>Cosβ=A•B</code>使用反三角函数直接算出来，但是其实可以调用<code>Vector3.Angle(A,B)</code>其实也使用点乘获得的<br>
<strong>叉乘</strong> 每个纬度原来的数值不会参与运算即<code>X=Ya​Zb​−Za​Yb​; Y=Za​Xb​−Xa​Zb​; Z=Xa​Yb​−Ya​Xb;</code>使用<code>Vector3 V=Vector3.Cross(A,B)</code>，新的向量V是AB的法向量，也是AB平面的法向量，<strong>若A在B的右侧 则法向量是垂直向上的反之则向下</strong><br>
假设向量 A 和 B 在 XZ 平面内，如果算出来Y&gt;0则说明向量 B 在向量 A 的右侧反之在左侧，那就可以结合点乘判断物体距离角度和左右侧。<br>
<strong>Lerp</strong> 插值运算，对两个坐标点进行插值运算，和Mathf的Lerp一样，只不过是三维的。</p>
<div class="warning custom-block"><p class="custom-block-title">[⚠️Warning] 注意线性插值瞬移问题</p>
<p>意线性插值瞬移问题
线性插值可以用来做一些摄像机的跟随移动这样的东西。<br/>
当线性插值t累加&gt;=1的时候（如果 t&gt;1它也会按 1.0计算），公式可以直接抵消，result=start+(end-start)*1 = end+O(t)，如果是向量Lerp则两个物体会直接重合起来没法分开了。<br/>
可以设置一些条件，让t和start位置重置一下避免这个问题。</p>
</div>
<p><strong>球形插值</strong> <code>Vector3.Slerp(A.position,B.position,Time.deltaTime);</code>不常用，可以让物体A呈弧线移动到位置B，比如模拟东升西落。</p>
<h4 id="transform-1" tabindex="-1">transform <a class="header-anchor" href="#transform-1" aria-label="Permalink to &quot;transform&quot;">&ZeroWidthSpace;</a></h4>
<p><code>transform.position</code>在是世界坐标的位置，而<code>transform.localPosition</code>是相对于父对象的坐标，也就是面板上的。虽然可以单独调用，修改的时候只能通过position属性不能单独改某个维度的坐标<br>
注意<code>transform.forward/up/right</code>这三个是 GameObject自身的正方向，使用<code>Vector3.forward/up/right</code>是世界坐标正方向。使用<code>transform.Translate()</code>封装好的API移动<br>
相对世界坐标角度<code>transform.eulerAngles</code>和相对父对象的角度(面板上是这个)<code>transform.localEulerAngles</code>角度的修改和坐标的修改差不多<br>
<code>transform.lossyScale</code>相对于世界坐标的缩放，不能修改(那为什么要提供？<code>transform.localScale</code>自己的缩放  没有提供API，只能自己慢慢每帧写<br>
<code>transform.LookAt(Vector3.zero)</code> 一直看向某个.点，传进某个 GameObject就会一直盯着看，重载了的也可以传position。</p>
<div class="info custom-block"><p class="custom-block-title">[📝Note]</p>
<p>使用eulerAngles属性获得的始终是0-360度的角度，但是面板上是可以出现负数的，需要自己写一些逻辑转换角度</p>
</div>
<p>自身方向的偏转角是怎么算出来的？ #todo</p>
<details class="details custom-block"><summary>Transform的基本API用法</summary>
<p>ransform的基本API用法</p>
<div class="language-Csharp vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">Csharp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Update</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    // 每帧 移动 1/帧率*(0,0,1) 也就是每秒1单位(米)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    transform.position </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> transform.forward </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (Time.deltaTime </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1f</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    // transform封装好的和上面一样，一般用它位移，参数控制相对于世界坐标还是自身坐标</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    // 注意这里就有排列组合了，以[自己or世界]坐标中心，偏移[自己or世界]朝向运动</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    transform.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Translate</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(transform.up </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (Time.deltaTime </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1f</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">),Space.Self); </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    // 1. 相对于世界坐标系的z轴移动，始终是朝世界坐标系的z轴正方向移动</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    transform.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Translate</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(Vector3.forward </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> *</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Time.deltaTime), Space.World);</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    // 2. 相对于世界坐标的自己面朝向动，transform.forward会先转换为等效世界坐标系下的方向向量，然后始终朝自己的面朝向移动</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    transform.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Translate</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(transform.forward </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> *</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Time.deltaTime), Space.World);</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    // 3. 相对于自己的坐标系下的自己的面朝向量移动（一定不会这样让物体移动,因为Z轴偏转被算了两次</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    transform.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Translate</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(transform.forward </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> *</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Time.deltaTime), Space.Self);</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    // 4. 相对于自己的坐标系下的z轴正方向移动，始终朝自己的面朝向移动</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    transform.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Translate</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(Vector3.forward </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> *</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Time.deltaTime), Space.Self);</span></span>
<span class="line"></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(transform.eulerAngles);</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 相对世界坐标角度  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(transform.localEulerAngles);</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  相对父对象的角度，面板上是这个</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    transform.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Rotate</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Vector3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">10</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">),Space.Self); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  绕自己坐标的Y轴转  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    transform.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Rotate</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Vector3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">10</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">),Space.World); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 绕世界坐标的Y轴转  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    transform.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Rotate</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Vector3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">10</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">),</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">10</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Time.deltaTime,Space.Self); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 重载 绕着哪个轴，转多少度，相对哪个坐标  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    transform.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">RotateAround</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Vector3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">),</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Vector3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">),</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">100</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Time.deltaTime);</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 相对于哪个点，哪个轴，旋转的角度</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br></div></div></details>
<h4 id="quration" tabindex="-1">Quration <a class="header-anchor" href="#quration" aria-label="Permalink to &quot;Quration&quot;">&ZeroWidthSpace;</a></h4>
<p>相比于欧拉角可以提供Lerp。<br>
空间中的角旋转都可以分解为绕XYZ三个互相垂直的三个旋转角组成的序列。最常用的旋转序列约定就是heading-pitch-bank(Y-X-Z)约定，<code>transform.eulerAngles</code>欧拉角的缺点是<code>同一旋转的方式不唯一</code> <code>万向节死锁</code>(万向锁)。<br>
在unity中将物体的X轴调到±90度会出现此现象，此时转动YZ都是绕Z转。</p>
<div class="warning custom-block"><p class="custom-block-title">[⚠️Warning] Gimbal lock问题</p>
<p>imbal lock问题
理解此问题的关键在于了解欧拉角旋转时的层级关系，当规定欧拉(2,1,3)时，其旋转层级关系可简单表述为y-&gt;x-&gt;z，即前者为后者的父层级。父层级的旋转会带动所有子层级旋转，而子层级的旋转不影响父层级的状态。<br/>
当x轴旋转时， <mark>有概率使得z轴所在环与y轴所在环共面</mark> ，此时即发生万向节死锁问题，导致z轴功能与y轴功能基本等效，即z轴失效。<br/>
此时若要旋转到需要的位置必须同时旋转3个轴，但这种旋转过程在实际空间中轨迹为弧线，不满足实际工程应用（比如摄像机转动会在球面上画个S弧而不是直线，运镜就很怪）</p>
</div>
<p>此时我们要用四元数解决这个问题，四元数包含一个标量和一个3D向量<code>[w,(x,y,z)]</code>代表了3D空间中的一个旋转量，在3D空间中，任意旋转都可以表示绕着某个轴v旋转一个角度w(轴-角 对)得到，因为只有一个轴所以避免了轴面重合<br>
对于给定旋转，假设为绕着 N轴旋转 β 度，N轴为(x,y,z)，那可以构成四元数 <code>Q=[cos⁡(β/2),sin⁡(β/2)N]</code>具体展开 <code>Q=[cos⁡(β/2),sin⁡(β/2)x,sin⁡(β/2)y,sin⁡(β/2)z]</code>，第一个元素为四元数的实部，后面三个为虚部。<br>
<strong>两个四元数相乘代表旋转四元数</strong>，四元数把角空间转换到<code>180 ~ -180</code> 此时位置的表示是唯一的，解决了 同一旋转表示不唯一 的问题。</p>
<p>单位四元数即<code>[1,(0,0,0)] [-1,(0,0,0)]</code>角度为0或者360度，没有旋转量的，使用<code>Quaternion.identity</code>获得，初始化对象的时候可以传入赋值<br>
四元数同样提供了插值运算，即角度转向过程的插值，<code>Quaternion.Lerp</code>和<code>Quaternion.Slerp</code>。Lerp更快 但是如果旋转范围较大效果较差,建议首选Slerp进行插值运算。<br>
注意LookRotation的运算，当A朝向B的时候，AB向量为轴，A可以绕此轴旋转自身，此时使用<code>upwards</code>规定Y轴也就是上的方向，三个角度就都就确定了，默认upwards是世界坐标的上方向</p>
<details class="details custom-block"><summary>四元数相关操作</summary>
<p>元数相关操作</p>
<div class="language-Csharp vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">Csharp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Start</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    Vector3</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> fake_part</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Mathf.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Sin</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">((</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">60</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> /</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Mathf.Deg2Rad) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Vector3.right;  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    Quaternion</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> q1</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Quaternion</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(fake_part.x,fake_part.y,fake_part.z, (</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">60</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> /</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Mathf.Deg2Rad); </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    Quaternion</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> q2</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Quaternion.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">AngleAxis</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">60</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, Vector3.right); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 这种初始化常用，上面的不常用</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    Quaternion</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> q3</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Quaternion.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Euler</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Vector3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">30</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">30</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">90</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 欧拉角 转 四元数</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    q3.eulerAngles </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 获得 四元数 的 欧拉角 </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    Quaternion.identity; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  单位四元数 </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Update</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    transform.rotation</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Quaternion.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">AngleAxis</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, Vector3.up); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 四元数相乘，绕世界的Y轴转1度，每帧转  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    //  Lerp和前面几个Lerp参数一样。</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    A.transform.rotation </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Quaternion.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Lerp</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(A.transform.rotation,target.transform.rotation,Time.deltaTime</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0.3f</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    B.transform.rotation </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Quaternion.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Slerp</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(B.transform.rotation,target.transform.rotation,Time.deltaTime</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0.3f</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    // 传入自己 A指向B的向量 可以计算出 A面朝B 需要的四元数，可以做到lookAt的效果，其实LookAt就是通过四元数做的。</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    A.transform.rotation</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Quaternion.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">LookRotation</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(B.transform.position </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> A.transform.position, </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">upwards</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:Vector3.up);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br></div></div></details>
<p>两个四元数相乘的结果，相当于绕物体自己的坐标系旋转角叠加后的四元数， <mark>注意四元数运算永远是使用物体本地坐标系进行旋转的</mark><br>
使用向量乘四元数的结果，相当于把此向量旋转对应四元数的旋转量后的向量， <mark>注意此运算不满足交换律四元数必须在前</mark></p>
<h3 id="子对象和坐标" tabindex="-1">子对象和坐标 <a class="header-anchor" href="#子对象和坐标" aria-label="Permalink to &quot;子对象和坐标&quot;">&ZeroWidthSpace;</a></h3>
<p>当把子对象拖到世界空间的时候，位置信息是加法，而缩放信息是乘法的；如果你再拖回去，那么就倒过来算一次(拖到GameObject下同理)。<br>
坐标转换的时时候，会受到缩放影响，应该是除了scale</p>
<details class="details custom-block"><summary>也可以用代码完成拖动</summary>
<p>可以用代码完成拖动</p>
<div class="language-Csharp vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">Csharp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Start</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(transform.parent.name);</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 获取父对象  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    transform.parent </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 脱离父对象  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    GameObject</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> F2</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> GameObject.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Find</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"F2"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    transform.parent </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> F2.transform; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 绑定父对象  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    GameObject</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> F3</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> GameObject.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Find</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"F3"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    // 如果是False，那么会不经过计算而是直接绑定对象关系然后把原来的transform赋值过去  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    transform.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">SetParent</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(F3.transform,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    transform.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">DetachChildren</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 把自己下一层的物体都脱离，非递归  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    transform.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Find</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"S2"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// transform下的Find是查找子对象，且失活的也能找到，非递归  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(transform.childCount);</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 获得自己的子对象数量  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    transform.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetChild</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 通过下标索引获得子对象，这样就可以便利了  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    transform.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">IsChildOf</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(F2.transform); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 判断是不是传入对象子对象  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    transform.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetSiblingIndex</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 获得自己的子对象编号，当然也有Set，Set传入溢出的时候就成为最后一个  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    transform.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">SetAsFirstSibling</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 设置为第一个，设置为最后一个  </span></span>
<span class="line"></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    //世界转本地 #转换坐标系，可以大概判断相对位置</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(transform.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">InverseTransformPoint</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(Vector3.forward)); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  点转换</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(transform.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">InverseTransformDirection</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(Vector3.forward));</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  单位向量转换 不受缩放影响  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(transform.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">InverseTransformVector</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(Vector3.forward));</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  单位向量转换 这个会受缩放影响</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    // 本地转世界  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(transform.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">TransformPoint</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(Vector3.forward)); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  ⭐️点转换(在单位的某方向放效果，可以直接转为世界然后创建)</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(transform.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">TransformDirection</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(Vector3.forward));</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  单位向量转换 不受缩放影响  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(transform.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">TransformVector</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(Vector3.forward));</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  单位向量转换 这个会受缩放影响</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br></div></div></details>
<hr>
<h2 id="核心组件" tabindex="-1">核心组件 <a class="header-anchor" href="#核心组件" aria-label="Permalink to &quot;核心组件&quot;">&ZeroWidthSpace;</a></h2>
<h3 id="inuptsystem和screen" tabindex="-1">InuptSystem和Screen <a class="header-anchor" href="#inuptsystem和screen" aria-label="Permalink to &quot;InuptSystem和Screen&quot;">&ZeroWidthSpace;</a></h3>
<p><strong>Input</strong>类是内置的。键盘鼠标：屏幕的原点是左下角，所有的输入都是在<code>Input</code>类中管理的，一般用键盘的枚举在<code>KeyCode</code>，用<code>Input.anyKeyDown</code>和 <code>Input.inputString</code>捕获输入设置快捷键可以这么干
在 输入管理器 ProjectSettings-&gt; InputManager设置默认轴输入<code>Input.GetAxis</code>，Unity中使用轴向来代表输入的方向，键鼠有四个常用的，不用我们手动处理按键和移动距离直接返回Float，移动越快值越大<br>
这个方法返回的值是会缓冲逐渐加速 在 -1~0~1 之间，如果使用<code>Input.GetAxisRaw</code>可以获得不带加速度的<br>
注意怎么处理组合键，如果组合键非常多，可以先用变量都捕获，然后下面自己加一堆逻辑判断。什么多点触控屏幕陀螺仪手柄，用到了再说</p>
<details class="details custom-block"><summary>Input的基本API用法</summary>
<p>nput的基本API用法</p>
<div class="language-Csharp vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">Csharp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Input.mousePosition; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 获得鼠标在屏幕上的位置</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Input.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetMouseButtonDown</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 0左键1右键</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Input.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetMouseButtonUp</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Input.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetMouseButton</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 持续按下</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (Input.mouseScrollDelta</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">!=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Vector2.zero){  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  鼠标滚动返回的是Vector2,正数向上滚反之可推</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(Input.mouseScrollDelta);</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 滚动了才打印, 而且只变动Y值</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Input.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetKeyDown</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(KeyCode.X) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 获得某个键的按下事件，只会触发一次</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Input.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetKeyDown</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"b"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 也可以使用函数调用而不是枚举，大小写敏感，只接受小写字符串</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Input.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetKeyUp</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(KeyCode.X) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 获得某个键的弹起事件</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Input.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetKey</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(KeyCode.D)  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 长按理论上是一帧一次,但是会帧率太高的话Unity中会优化,让触发频率降低</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">/* 处理组合键 */</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">bool</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> isCtrlPressed</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Input.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetKey</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(KeyCode.LeftControl) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">||</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Input.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetKey</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(KeyCode.RightControl);</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">bool</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> isCPressed</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Input.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetKey</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(KeyCode.C);</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (isCtrlPressed </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x26;&#x26;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> isCPressed)Debug.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Ctrl + C is pressed."</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">/* 下面这俩搭配可以记录快捷键 */</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Input.anyKeyDown </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// bool 是否有任意键按下</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Input.anyKey </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// bool 是否有任意键长按</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (Input.anyKeyDown) </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">$"Pressed {</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Input</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">inputString</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">}"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 记录下捕获的，他只会捕获上一个</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">string</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[] </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">strs</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Input.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetJoystickNames</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  获得所有手柄的名字</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">/* 使用默认轴输入 */</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(Input.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetAxis</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Horizontal"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 默认AD  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(Input.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetAxis</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Vertical"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 默认WS  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(Input.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetAxis</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Mouse X"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 鼠标水平  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(Input.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetAxis</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Mouse Y"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 鼠标竖直</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br></div></div></details>
<p><strong>InputSystem</strong>官方搞的新的输入系统，2019后都推荐6之后是默认，要求.net4+，如果没有从PackageMannager安装。Edit-&gt;ProjectSettiing-&gt;Player-&gt;OtherSettings-&gt;Configuration-&gt;ActiveInputHandler中选择启用老的还是新的，选择之后重启生效。</p>
<ul>
<li>长按的逻辑，在按下的那一帧isPressed就被标记为true，后续只要不松开每一帧都是true。wasPressedThisFrame的逻辑是被按下的那一帧true，后续是false，wasReleasedThisFrame同理。
<ul>
<li>如果要做自定义长按检测结合计时器实现比较好</li>
</ul>
</li>
<li>触屏(或者其他设备)可能有些设备没有，使用前检测一下比较好，检测方式就是对应的类current为null，没有直接调用会报错的。</li>
<li></li>
</ul>
<p><a href="https://www.tongyi.com/?sessionId=b6feca1d661948fab3baeeb4a88c83ca" target="_blank" rel="noreferrer">通义 - 你的超级个人助理</a></p>
<p><strong>Screen属性</strong>很简单就是宽高刷新率，注意设备分辨率和窗口的区别，自动旋转屏幕和运行时全屏也可以设置但是不太重要。</p>
<details class="details custom-block"><summary>Screen的基本API用法</summary>
<p>creen的基本API用法</p>
<div class="language-Csharp vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">Csharp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Start</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    int</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> w</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Screen.width; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 软件画面窗口宽</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    int</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> h</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Screen.height; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 软件画面窗口高</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">$"运行窗口(游戏内部帧缓冲) 高{</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">h</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">} 宽{</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">w</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">}"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    Resolution</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> r</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Screen.currentResolution; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 物理显示器屏幕的宽高，如果是在编辑器里面是开发机器的屏幕，受系统设置影响</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">$"执行程序的机器 高{</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">r</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">height</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">} 宽{</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">r</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">width</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">} 分辨率{</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">r</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">}"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    Screen.sleepTimeout </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> SleepTimeout.NeverSleep; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 运行着的时候设备屏幕不休眠  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    Screen.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">SetResolution</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1920</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1080</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 一般是在非移动设备上才设置分辨率</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    Screen.fullScreen </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 运行时全屏  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    Screen.fullScreenMode </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> FullScreenMode.Windowed;</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  独占全屏 全屏窗口 最大化窗口 窗口模式 去枚举里面看  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br></div></div></details>
<div class="info custom-block"><p class="custom-block-title">[📝Note] 坐标系汇总</p>
<p>标系汇总
世界坐标系-世界原点为中心<br/>
物体坐标系-建模时候确定,相对父对象的坐标<br/>
屏幕坐标系-使用Screen获得宽高原点在左下角<br/>
视口坐标系-和将屏幕坐标系百分比化，xy最大值都是1，对角为(1,1)<br/>
视口坐标和场景坐标转换API也在Camera中<code>Camera.main.WorldToViewportPoint()</code></p>
</div>
<h3 id="camera和light" tabindex="-1">Camera和Light <a class="header-anchor" href="#camera和light" aria-label="Permalink to &quot;Camera和Light&quot;">&ZeroWidthSpace;</a></h3>
<p>Camera可以设置的属性，非核心的随便看看就行了</p>
<ul>
<li>ClearFlags Skybox3D游戏常用；Soilder Color 2D游戏常用；<strong>Depth Only叠加渲染</strong>；最后是覆盖渲染模式不常用</li>
<li>CullingMask 可以选择哪些Layer会被此摄像机渲染出来（想一下tag和<strong>layer系统</strong></li>
<li>Projection 透视模式或者正交模式
<ul>
<li>Perspective 透视模式
<ul>
<li>FOV Axis 视场角轴一般不改就用竖直方向就行</li>
<li>Field of view 视口大小</li>
<li>Physical Camera可以模拟真实世界中的摄像机焦距传感器尺寸透镜移位等，不懂摄影不改他</li>
</ul>
</li>
<li>Orthographic 正交摄像机（一般用于2D游戏制作）
<ul>
<li>Size 摄制范围</li>
</ul>
</li>
</ul>
</li>
<li>ClippingPlanes 摄像机梯形盒的厚度</li>
<li><strong>Depth</strong> 多摄像机渲染的顺序，当多个摄像机渲染多帧，深度越深越早被叠加，会被后面摄像机的帧盖住
<ul>
<li>此时ClearFlags如果选择了Depth Only，那么此摄像机就只渲染选定层数的物体，然后按顺序叠加上去</li>
<li>如果想要使用多个摄像机，往往上层的摄像机会使用此模式。(UI一般会单独使用一个摄像机去渲染。<strong>这个很重要</strong></li>
</ul>
</li>
<li>TargetTexture 渲染纹理，把摄像机输出的画面输出到一张图上，可以用来制作预览和小地图
<ul>
<li>创建RenderTexture选中即可使用</li>
</ul>
</li>
<li>Occlusion Culling 默认勾选被遮挡的物体不渲染省性能</li>
<li>ViewportRect 不太重要可以调出类似于双人成行的效果</li>
<li>TargetDisplay 不太重要可以输出到多个屏幕</li>
</ul>
<div class="tip custom-block"><p class="custom-block-title">[💡Tip] 摄像机拖影</p>
<p>像机拖影
在 <code>Depth Only</code> 模式下，Unity 不会清除颜色缓冲区（Color Buffer），只会清除深度缓冲区（Depth Buffer）<br/>
这种模式通常用于多摄像机叠加渲染（如背景摄像机和UI摄像机分离）时，避免重复绘制背景<br/>
如果主摄像机或其他摄像机没有正确清理颜色缓冲区，可能会导致上一帧的画面残留，从而产生拖影<br/>
<br/>
如果你有多个摄像机，请确保至少有一个摄像机（通常是主摄像机）的 <code>Clear Flags</code> 设置为 <code>Skybox</code> 或 <code>Solid Color</code>，以清理颜色缓冲区。</p>
</div>
<p>从代码中获取摄像机的场景中Camera的Tag为MainCamera的摄像机可以直接通过静态方法Camera.main获取，如果有多个(一般只有一个)随机获得一个<br>
Inspector中的属性都可以用对象获得，摄像机提供的委托前妻不常用<br>
注意 屏幕坐标&lt;-&gt;世界坐标 转换Z轴值的问题</p>
<details class="details custom-block"><summary>摄像机的的常用API用法</summary>
<p>像机的的常用API用法</p>
<div class="language-Csharp vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">Csharp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Start</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(Camera.main.transform.position);  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    foreach</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Camera</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> c</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> in</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Camera.allCameras) </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(c);</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 获得场景所有摄像机的数组  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(Camera.allCamerasCount); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  获得摄像机的计数  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    // 转换之后返回Vector3, xy就是屏幕坐标，z就是物体离屏幕远近  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    Camera.main.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">WorldToScreenPoint</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(transform.position);  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    // 屏幕转世界  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    Vector3</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> mousePos</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Input.mousePosition;  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    // 如果不改变这个值，那么屏幕上的值是没有Z的，默认就是0  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    mousePos.z </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 10</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 所以这里要改成10，这里的Z就是 距离摄像机横切面是多远  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    //  这样才不会一直是一个点，如果Z是0那么xy在三维空间中转换也是一直在一个点上  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    Camera.main.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">ScreenToWorldPoint</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(mousePos);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    // 在特殊的时刻调用的委托  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    Camera.onPreCull </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Func; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 比如这个就是 剔除遮挡 时候的委托  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    Camera.onPreRender </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Func;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    Camera.onPostRender </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Func;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br></div></div></details>
<p><strong>Light相关</strong>，一眼能看出来的和不重要的属性就不放上去了。代码改改光晕强度什么的，照着面板改吧，其实提供的API不多<br>
可以用点光源挑动和Holo大小模拟蜡烛，用方向光模拟白天黑夜轮换等</p>
<ul>
<li>Type 光源类型
<ul>
<li>Spot 聚光灯
<ul>
<li>Range 发光范围距离</li>
<li>Spot Angle 光锥角度</li>
</ul>
</li>
<li>Directional 方向光（环境光）</li>
<li>Point 点光源</li>
<li>Area 面光源 只有在烘焙模式下有用不管他</li>
</ul>
</li>
<li>Mode 光源模式
<ul>
<li>Realtime 实时光源 每帧实时计算，效果好，性能消耗大</li>
<li>Baked 烘焙光源 事先计算好，无法动态变化</li>
<li>Mixed 混合光源 预先计算+实时运算</li>
</ul>
</li>
<li>RealtimeShadows 实时阴影</li>
<li>Cookie 灯罩，用灰度图叠加出来光的形状，类似于灰度遮罩那种
<ul>
<li>Cookie Size 灯罩大小</li>
</ul>
</li>
<li>Flare 耀斑，镜头耀斑，动漫开场里太阳那种
<ul>
<li><mark>注意必须给Camera添加FlareLayer组件</mark> 才能在Game中看到耀斑</li>
</ul>
</li>
<li>Draw Halo 球形光环开关</li>
<li>Culling Mask 哪些Layer会受到此光源影响</li>
</ul>
<p>光源环境的设置在 菜单Window-&gt;Rendering-&gt;Lighting里面<br>
在SkyboxMaterial中可以设置默认的天空盒(其实就是6个面的美术资源)，默认最亮的方向光代表太阳<br>
也可以改Fog雾(吃性能) Flare耀斑 Holo光晕 效果等，接触不到的时候暂时不用看</p>
<h4 id="烘焙" tabindex="-1">烘焙 <a class="header-anchor" href="#烘焙" aria-label="Permalink to &quot;烘焙&quot;">&ZeroWidthSpace;</a></h4>
<h3 id="_3d-collider和rigidbody" tabindex="-1">3D Collider和Rigidbody <a class="header-anchor" href="#_3d-collider和rigidbody" aria-label="Permalink to &quot;3D Collider和Rigidbody&quot;">&ZeroWidthSpace;</a></h3>
<p>碰撞产生的条件: <mark>两个物体都有Collider且至少一个有Rigidbody</mark> 有了刚体<strong>Rigidbody</strong>物体才会受到力的作用<br>
检测不到的常见原因: 不在同一Layer，trigger和碰撞没对好，<code>Body Type: Kinematic</code>脚本接管了</p>
<ul>
<li>质量<strong>Mess</strong>越大越不容易被别的力推动(惯性大)。有了Rigibody才能受重力<strong>UseGravity</strong>影响，空气阻力<strong>Drag</strong>参数才有用。互相碰到的时候会产生扭矩作用力，随着飞行被<strong>AngularDrag</strong>扭矩阻力衰减，让物体旋转着飞出去。</li>
<li><strong>IsKinematic</strong>是否直接用代码接管物理特性
<ul>
<li>当脚本接管的时候，如果碰撞双方都是Kinematic就碰撞不了</li>
</ul>
</li>
<li>当物理帧更新间隔太长的时候，可以使用插值运算<strong>Interpolate</strong>让物体的物理现象更平滑
<ul>
<li>菜单Edit-&gt;PorjectSettings-&gt;Time-&gt;FixedTimestep每隔多少秒进行一次物理计算，也就是FixUpdate的间隔。</li>
<li>Interpolate 根据前一帧的变换来平滑变换</li>
<li>Extrapolate 根据下一帧的估计变换来平滑变换</li>
</ul>
</li>
<li><strong>CollisionDetection碰撞检测频率算法</strong> <mark>性能消耗依次增高，相应也更准确</mark>
<ul>
<li>Discrete默认频率较低，有时候速度比较快可能没检测到，就会穿模</li>
<li>Continuous连续检测</li>
<li>Continuous Speculative连续推测检</li>
<li>Continuous Dynamic连续动态检测</li>
</ul>
</li>
<li>Constraints可以冻结某个轴的旋转或坐标，全冻结就失去了物理特性,比如冻结Y轴的位移可以避免对象被弹飞</li>
</ul>
<table tabindex="0">
<thead>
<tr>
<th>使用不同检测算法的物体<br>互相碰撞会用什么算法</th>
<th>无刚体碰撞盒</th>
<th>Discrete <br>(离散检测)</th>
<th>Continuous<br> (连续检测)</th>
<th>Continuous Dynamic<br> (连续动态检测)</th>
<th>Continuous Speculative<br> (连续推测检测)</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>无刚体碰撞盒</strong></td>
<td>不检测碰撞</td>
<td>Discrete</td>
<td>Continuous</td>
<td>Continuous</td>
<td>Continuous Speculative</td>
</tr>
<tr>
<td><strong>Discrete</strong></td>
<td>Discrete</td>
<td>Discrete</td>
<td>Discrete</td>
<td>Discrete</td>
<td>Continuous Speculative</td>
</tr>
<tr>
<td><strong>Continuous</strong></td>
<td>Continuous</td>
<td>Discrete</td>
<td>Discrete</td>
<td>Continuous</td>
<td>Continuous Speculative</td>
</tr>
<tr>
<td><strong>Continuous Dynamic</strong></td>
<td>Continuous</td>
<td>Discrete</td>
<td>Continuous</td>
<td>Continuous</td>
<td>Continuous Speculative</td>
</tr>
<tr>
<td><strong>Continuous Speculative</strong></td>
<td>Continuous Speculative</td>
<td>Continuous Speculative</td>
<td>Continuous Speculative</td>
<td>Continuous Speculative</td>
<td>Continuous Speculative</td>
</tr>
</tbody>
</table>
<p>Collider是描述物体体积的，有了<strong>Collider</strong>物体才有体积不会穿模。IsTrigger勾选会只有碰撞检测，但是没有物理效果(比如剑和魔法穿过人物)。<br>
Rigidbody直接加在父对象上，会把子对象都包括进来，Collider也是，<strong>父对象的碰撞检测会使用所有子对象累积起来的形状参与检测</strong><br>
网格碰撞器开启刚体必须开启Convex才能参与刚体计算。</p>
<p><strong>在代码中检测</strong><br>
碰撞和Trigger属于特殊的生命周期函数，<strong>在FixedUpdate之后固定调用,调用循环间隔和Update不一样</strong>，也是通过反射调用。<br>
只要挂载的对象能和别的对象产生碰撞和触发，那么对应的函数就会响应，有物理效果的是Collison没有的是Trigger，自己没挂别的挂了碰我也会触发<br>
默认private，可以写成protected去子类中去重写，一般不会手动调用所以不要写成public。<br>
参与计算的是Rigibody组件，父物体挂组件子物体挂了脚本触发不了的。<br>
Rigibody添加力的单位是牛N，如果没阻力就会一直飞，想要一直动就一直加力和物理世界一样。注意爆炸力函数只对挂载的本脚本的物体起效，所以模拟爆炸就获得所有受影响的物体然后执行这个函数<br>
使用组件ConstantForce组件，可以直接在面板上为物体施加力场，<strong>注意Unity有刚体休眠机制节约性能</strong>，如果发现刚体不好使了，叫醒一下</p>
<details class="details custom-block"><summary>碰撞和力的基本API用法</summary>
<p>撞和力的基本API用法</p>
<div class="language-Csharp vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">Csharp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Rigid</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> : </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">MonoBehaviour</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    private</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Rigidbody</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> rigidBody</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Start</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        rigidBody </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> gameObject.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetComponent</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Rigidbody</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>(); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 获得刚体组件  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        rigidBody.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">AddForce</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(Vector3.forward</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">10</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 添加相对于世界坐标系方向的力  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        rigidBody.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">AddRelativeForce</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(Vector3.forward</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">10</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 添加相对于自己标系方向的力  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        rigidBody.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">AddTorque</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(Vector3.forward</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">10</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 添加扭矩力  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        rigidBody.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">AddRelativeTorque</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(Vector3.forward</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">10</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 添加相对于自己标系方向的扭矩力  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        rigidBody.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">AddExplosionForce</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">100</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,Vector3.zero, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">10</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 爆炸力 爆炸中心 爆炸半径  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        rigidBody.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">AddForce</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(Vector3.forward</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">10</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,ForceMode.Force); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 第二个参数是施加力的模式，力的函数都可以添加</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">          </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        rigidBody.velocity </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Vector3.forward</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">10</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 很少用，可以直接改变速度  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    private</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> OnCollisionEnter</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Collision</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> collision</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 刚碰撞到</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(collision.collider); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 获得对方碰撞器的信息</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(collision.gameObject); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 获得对方游戏对象</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(collision.transform); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  获得对方的位置信息</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(collision.contactCount); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 获得有哪些点碰撞了</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        ContactPoint</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[] </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">pos</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> collision.contacts; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  甚至获得所有碰撞了的点（不常用</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    private</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> OnCollisionExit</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Collision</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> collision</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">){} </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 结束碰撞的</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    private</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> OnCollisionStay</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Collision</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> collision</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">){} </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  持续碰撞过程中</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    /* Collider 对象属性和Collison差不太多,点进去看着属性拿 */</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    private</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> OnTriggerEnter</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Collider</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> other</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) {} </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 刚开始接触</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    private</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> OnTriggerExit</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Collider</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> other</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">){} </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 结束接触，穿越过去的时候</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    private</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> OnTriggerStay</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Collider</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> other</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">){} </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  两者正在穿模的时候</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Update</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(rigidBody.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">IsSleeping</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()) rigidBody.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">WakeUp</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  当然也有rigidBody.Sleep()</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    //  让物体位移的方式，position赋值，Translate，AddForce, </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br></div></div></details>
<p>#todo 力的模式和计算,父子物体的碰撞器组合实现CompositeCollider2D的效果
使用meshcollider太费性能了，所以可以加多个碰撞器拼个大概就行了，节省性能。</p>
<h3 id="范围检测和射线检测" tabindex="-1">范围检测和射线检测 <a class="header-anchor" href="#范围检测和射线检测" aria-label="Permalink to &quot;范围检测和射线检测&quot;">&ZeroWidthSpace;</a></h3>
<p><strong>被检测的对象必须要有碰撞器。范围检测不会真正产生新碰撞器，而且检测是瞬时的</strong>。生成的触发器形状和默认能创建的那几个物体类型一样，最后会获得一个检测到的Coillder数组</p>
<div class="language-Csharp vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">Csharp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Collider</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[] </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">colliders</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Physics.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">OverlapBox</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(Vector3.zero, Vector3.one, Quaternion.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">AngleAxis</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">45</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,Vector3.up), </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  中心 大小 旋转角</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    1</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x3C;&#x3C;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">LayerMask.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">NameToLayer</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"UI"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">), </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  检测哪一层</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    QueryTriggerInteraction.Ignore); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  是否忽略触发器</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Collider</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[] </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">colliders</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Physics.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">OverlapSphere</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(transform.position</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">transform.forward</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">transform.up, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 中心(自己的位置往上和前偏移1个单位)，半径1 </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    1</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x3C;&#x3C;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">LayerMask.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">NameToLayer</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Monster"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//这里创建的是球形范围检测</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  Physics.OverlapBoxNonAlloc多了个参数，直接先传入碰撞器数组存储结果，和ref一样 调用者负责初始化数组，方法只负责填充数据。</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br></div></div><p><code>QueryTriggerInteraction</code>是个枚举类，默认值是使用Unity中的设置Edit-&gt;ProjectSettings-&gt;Physics-&gt;QueriesHitTriggers默认是勾上的，是否检测触发器Trigger。</p>
<p>射线检测 也是瞬时的。<br>
注意<code>Physics.RaycastAll</code> <strong>距离从远到近排序</strong> 排序的，最远的在index0</p>
<details class="details custom-block"><summary>射线检测主要的API</summary>
<p>线检测主要的API</p>
<div class="language-Csharp vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">Csharp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Start</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    Ray</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> r</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Ray</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(transform.position, transform.forward); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 从哪个点发出射线，以及射线的方向向量</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(r.origin);</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(r.direction);</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    Ray</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> r2</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Camera.main.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">ScreenPointToRay</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(Input.mousePosition); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 从摄像机位置发条射线到鼠标的位置</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Update</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    Ray</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> r3</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Ray</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(Vector3.zero, Vector3.forward); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 搞一条射线</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    bool</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> isHit</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Physics.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Raycast</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(r3,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1000</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x3C;&#x3C;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">LayerMask.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">NameToLayer</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Monster"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 只返回是不是碰到了 也可以传QueryTriggerInteraction</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (Physics.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Raycast</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(Vector3.zero, Vector3.forward, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> &#x3C;&#x3C;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> LayerMask.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">NameToLayer</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Monster"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)))</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">$"Hited {</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">isHit</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">}"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (Input.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetMouseButtonDown</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">))</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Debug.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"常见 鼠标点击检测碰撞点并导航"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        Ray</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> ray</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Camera.main.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">ScreenPointToRay</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(Input.mousePosition);</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        RaycastHit</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> hit</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (Physics.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Raycast</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(ray, </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">out</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> hit))</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            agent.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">SetDestination</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(hit.point);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            agent.isStopped </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            Debug.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"目标点: "</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> +</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> hit.point);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    RaycastHit</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> rh</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (Physics.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Raycast</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(r3,</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">out</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> rh,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1000</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> &#x3C;&#x3C;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> LayerMask.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">NameToLayer</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Monster"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)))</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(rh.collider.gameObject.name); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 这样就拿到了碰到了谁，只能拿到第一个碰到的</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(hit.point); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 获得碰撞点</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(rh.distance);</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 获得离我多远</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(rh.normal); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 获得碰撞的法线向量</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    RaycastHit</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[] </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">rhs</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Physics.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">RaycastAll</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(r3, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1000</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> &#x3C;&#x3C;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> LayerMask.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">NameToLayer</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Monster"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">));</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (rhs.Length</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">!=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        foreach</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">RaycastHit</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> r</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> in</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> rhs)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        {</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">            print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(r.collider.gameObject.name);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br></div></div></details>
<p>顺口把这俩API也看一眼，这俩是调试用的射线</p>
<div class="language-Csharp vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">Csharp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Debug.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">DrawLine</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(A.position, B.position, Color.red, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0.1f</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 绘制从 A 到 B 的红色线段 显示时间0.1s</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Debug.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">DrawRay</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(A.position, A.up </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 5</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, Color.green, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0.1f</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 绘制从 A 出发的绿色射线，向 A 的上方方向 显示时间0.1s</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br></div></div><h3 id="physicmaterial和linerenderer" tabindex="-1">PhysicMaterial和LineRenderer <a class="header-anchor" href="#physicmaterial和linerenderer" aria-label="Permalink to &quot;PhysicMaterial和LineRenderer&quot;">&ZeroWidthSpace;</a></h3>
<p>物理材质和显示的模型材质不同，物理材质规定的是碰撞时物理特性。右键创建之后可以在Collider中为对象分配。</p>
<ul>
<li>Dynamic Friction 物体在上面运动时候的摩擦</li>
<li>Static Friction 推动物体开始动的摩擦</li>
<li>Bounciness 0不会反弹 1在反弹时不产生任何能量损失，但可能只会给模拟增加少量能量。</li>
<li>Friction Combine 摩擦组合方式
<ul>
<li>Average：对两个摩擦值求平均值</li>
<li>Minimum：使用两个值中的最小值</li>
<li>Maximum：使用两个值中的最大值</li>
<li>Multiply：两个摩擦值相乘</li>
</ul>
</li>
<li>Bounce Combine 弹性组合方式与Friction Combine模式相同</li>
</ul>
<p>使用<strong>LineRenderer</strong>组件 可用多个<strong>点</strong>划一些线段，点的多少可以增加减少，他会把点连起来绘制线段，每个对象身上只能有一个LineRenderer</p>
<ul>
<li>Loop 是否首尾点自动相连</li>
<li>Positions调整线段粗细曲线</li>
<li>Corner Vertices (角顶点的圆角)绘制角时使用了多少额外的顶点增大线角看起来更圆</li>
<li>End Cap Vertices (终端顶点的圆角)</li>
<li>UseWorldSpace对齐世界坐标还是本地坐标<br>
材质什么的要么一看就懂要么就是不太重要的 面板里的东西和代码属性一一对应点进去看就行，注意怎么代码加点</li>
</ul>
<div class="language-Csharp vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">Csharp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">lineRenderer.positionCount </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 4</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  必须要先规定个数</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">lineRenderer.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">SetPositions</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Vector3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[] {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Vector3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">),</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Vector3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">5</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">),</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Vector3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">5</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">});</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">lineRenderer.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">SetPosition</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Vector3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 重载可以指定操作</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br></div></div><h3 id="音频系统-和-视频播放" tabindex="-1">音频系统 和 视频播放 <a class="header-anchor" href="#音频系统-和-视频播放" aria-label="Permalink to &quot;音频系统 和 视频播放&quot;">&ZeroWidthSpace;</a></h3>
<p>常用兼容格式<code>mp3 wav ogg aiff</code>面板下面能预览，参数中比较重要的是 <strong>LoadInBackground</strong>后台加载不阻塞主线程 <strong>LoadType</strong>性能和内存取舍参数 <strong>Preload Audio Data</strong>场景使用前是否预加载音效
::: note [💬Quote] 参数一览
数一览</p>
<ul>
<li>Force To Mono 强制为单声道时，混合过程中被标准化 适合需要将多声道音频转换成单声道的情况</li>
<li><strong>Load In Background</strong> 在后台加载，不会阻塞主线程，有助于提高应用的响应速度和用户体验</li>
<li>Ambisonic 立体混响声，非常适合360度视频和XR应用程序 如果音频文件包含立体混响声编码的音频，请启用此选项</li>
<li><strong>LoadType</strong> (加载类型)
<ul>
<li>Decompress On Load 不压缩形式存在内存中，虽然会占用更多内存但可以快速加载 适用于小音效</li>
<li>Compress in memory 压缩形式存在于内存中，尽管加载时间较长但是能节省内存空间 仅适用于较大音效文件</li>
<li>Streaming 以流的形式存在，使用时解码 这种形式对内存的影响最小，但可能会增加CPU的消耗</li>
</ul>
</li>
<li><strong>Preload Audio Data</strong> 勾选后进入场景即加载音频数据；不勾选则在第一次使用时才加载，有助于管理首次加载时间</li>
<li>Compression Format (压缩方式)
<ul>
<li>PCM 音频以最高质量存储，适合对音质有高要求的应用场景</li>
<li>Vorbis 相比PCM，提供了更高效的压缩率，根据所需的质量级别调整压缩程度</li>
<li>ADPCM 包含一定的噪音，适用于会被多次播放的声音，如碰撞声或环境音效</li>
</ul>
</li>
<li>Quality (音频质量) 确定要应用于压缩剪辑的压缩量 不适用于 PCM/ADPCM/HEVAG 格式</li>
<li>Sample Rate Setting (采样率设置) PCM 和 ADPCM 压缩格式允许自动优化或手动降低采样率
<ul>
<li>Preserve Sample Rate 此设置可保持采样率不变（默认值）</li>
<li>Optimize Sample Rate 此设置根据分析的最高频率内容自动优化采样率</li>
<li>Override Sample Rate 此设置允许手动覆盖采样率，因此可有效地将其用于丢弃频率内容
:::</li>
</ul>
</li>
</ul>
<p><strong>AudioSource组件</strong>是让 GameObject发出声音的组件。<strong>AudioListener是声音监听器</strong>，可以理解为声音总线，一般会跟随摄像机挂载有且仅有一个多了删掉，如果出现了<strong>多个AudioListener会报警告</strong>。
注意参数：</p>
<ol>
<li><strong>Play On Awake (启动播放开关)</strong>：物体Awake事件时立即播放</li>
<li>Spatial Blend (空间混合) 2D 音源（0）例如给UI用固定、3D 音源（1）<strong>随GameObject有远近</strong>，或者是二者插值的复合音源。一般只会01</li>
<li>Volume Rolloff 声音随距离衰减速度，选择不同的模式看曲线就知道了，3D的游戏用线性比较真实
::: note [💬Quote] 参数一览
数一览</li>
</ol>
<ul>
<li><strong>AudioClip (音频剪辑)</strong>：播放的音频</li>
<li><strong>Output</strong> 默认将直接输出到音频监听器(默认为MainCamera挂的)可以更改为输出到混音器</li>
<li><strong>Mute</strong> 静音开关(静音了不是不播放了)占用内存小可以放很多音效，因此可以让画面快速响应关闭和恢复当前音效</li>
<li>Bypass Effect 开关滤波器效果</li>
<li>Bypass Listener Effects 快速开关所有监听器</li>
<li>Bypass Reverb Zones 快速开关所有混响区</li>
<li><strong>Play On Awake</strong> 对象创建时就播放音乐，也就是开关启动游戏就播放</li>
<li><strong>Loop</strong> 循环</li>
<li>Priority 优先级</li>
<li><strong>Volume</strong> 音量大小</li>
<li>Pitch 音高</li>
<li>Stereo Pan 调节左右声道</li>
<li>Spatial Blend 音频受3D空间的影响程度</li>
<li>Reverb Zone Mix 到混响区的输出信号量</li>
<li>3D Sound Settings 和 Spatial Blend 参数成正比应用
<ul>
<li>Doppler Level 多普勒效果等级</li>
<li>Spread 扩散角度设置为3D立体声还是多声道</li>
<li><strong>Volume Rolloff</strong> 声音衰减速度
<ul>
<li>Logarithmic Rolloff 对数衰減</li>
<li>Linear Rolloff 线性衰减</li>
<li>Custom Rolloff 自定义曲线衰减</li>
</ul>
</li>
<li>Min/Max Distance 开始衰減的最小距离/声音可听到的最大距离
:::</li>
</ul>
</li>
</ul>
<p><strong>使用代码控制音频</strong><br>
<strong>没开始Play是不能Pause的</strong>。动态控制音频常用的方式，可以直接搞好挂对象身上；可以挂在一个prefab上然后动态生成销毁；可以通过指定clip用一个AudioSource组件管理。<br>
<code>PlayOneShot</code> 允许你在一个已有的 <code>AudioSource</code> 组件上播放一次<code>AudioClip</code>，而不会影响当前正在播放的音频，例如播放背景音乐的同时播放角色行走或射击的音效<br>
AudioClip类要用<strong>浮点数组存储，长度是 声道数x剪辑长度</strong>  可以Get和Set数据<br>
<strong>麦克风输入音频</strong> frequency默认就填44100，返回的是一个AudioClip</p>
<ul>
<li>audioSource.clip是null访问length会报NullReferenceException</li>
<li>音频是动态加载的(如Addressables或WWW异步加载)确保加载完成再访问</li>
<li>循环播放length仍然是单次音频长度</li>
<li>播放时调整了pitch实际播放时长会变，但clip.length不变</li>
</ul>
<div class="warning custom-block"><p class="custom-block-title">[⚠️Warning]</p>
<p>一个AudioSource管一个音效，如果使用同一个， 那PlayOneShot和Play可能会会被一块触发导致重叠播放，比如上面想用按键控制攻击音效的时候，背景音乐同时也会跟着起停。所以改为了获取两个组件（问题来了我怎么知道我获取的组件顺序哪个是BGM哪个是攻击）</p>
</div>
<p>Unity 在内部使用的是 <strong>底层音频系统（如 FMOD、OpenAL、平台音频 API）</strong> 来初始化音频设备不会动态检测设备热切换，官方确认这是预期行为暂时没有解决方案</p>
<details class="details custom-block"><summary>音频组件的基本API</summary>
<p>频组件的基本API</p>
<div class="language-Csharp vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">Csharp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> AusT</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> : </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">MonoBehaviour</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    private</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> AudioSource</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> aus</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> AudioClip</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> clip</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> AudioClip</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> RecordClip</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    // Start is called before the first frame update</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Start</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        aus</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetComponent</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">AudioSource</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>();</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        string</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[] </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">microps</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Microphone.devices; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  所有的麦克风设备</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        foreach</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">string</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> microp</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> in</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> microps)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        {</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">            print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(microp);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        }</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(clip.length) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  获取音频长度</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    // Update is called once per frame</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Update</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(Input.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetKeyDown</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(KeyCode.P)) aus.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Play</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  这个Play的delay参数是根据采样率来的，最好别直接用</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(Input.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetKeyDown</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(KeyCode.S)) aus.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Stop</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(Input.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetKeyDown</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(KeyCode.Space))</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        {   </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">            // 实际上Unity没有提供音效是否播放完毕的API，用isPlaying一直检测，直到播完</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(aus.isPlaying) aus.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Pause</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 暂停再开始会接着播</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            else</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> aus.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">UnPause</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  暂停之后用也行</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        }</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(Input.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetKeyDown</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(KeyCode.C)) </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        aus.clip</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">clip; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 更换clip</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (Input.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetKeyDown</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(KeyCode.R))</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        {</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">            // 设备使用默认选null loop如果录制超长会重录 录制长度(S) 采样率一般就这个固定数44100</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            RecordClip</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Microphone.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Start</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">10</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">44100</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (Input.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetKeyUp</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(KeyCode.R))</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        {</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">            print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(Microphone.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">IsRecording</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 录制完了吗</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            Microphone.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">End</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 结束</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            aus.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">PlayOneShot</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(RecordClip); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 不知道为什么我这里能录制，能调用麦克风 但播放会有问题</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            float</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[] </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">f</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> float</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[RecordClip.channels</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">RecordClip.samples]; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 浮点数组存储，存储的长度是 声道数*剪辑长度  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            RecordClip.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetData</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(f, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 直接Get出来塞进去</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br></div></div></details>
<p><strong>视频播放</strong>内置的VideoPlayer已经很好用了没必要玩的三方。MovieTexture很老了别用。<br>
一般都用mp4+H.264就够,平台发布比较广可以使用VP8比h264性能差点兼容性好。<br>
支持h.265编解码器的平台<code>macOS 11.13+</code>，<code>Windows 10</code>，<code>Android 5.0+</code>，<code>iOS 11.0+</code>。</p>
<table tabindex="0">
<thead>
<tr>
<th>平台兼容性</th>
<th>Windows</th>
<th>macOS</th>
<th>Linux</th>
</tr>
</thead>
<tbody>
<tr>
<td>.asf</td>
<td>✓</td>
<td></td>
<td></td>
</tr>
<tr>
<td>.avi</td>
<td>✓</td>
<td></td>
<td></td>
</tr>
<tr>
<td>.dv</td>
<td>✓</td>
<td>✓</td>
<td></td>
</tr>
<tr>
<td>.m4v</td>
<td>✓</td>
<td>✓</td>
<td></td>
</tr>
<tr>
<td>.mov</td>
<td>✓</td>
<td>✓</td>
<td></td>
</tr>
<tr>
<td>.mp4</td>
<td>✓</td>
<td>✓</td>
<td></td>
</tr>
<tr>
<td>.mpg</td>
<td>✓</td>
<td>✓</td>
<td></td>
</tr>
<tr>
<td>.mpeg</td>
<td>✓</td>
<td>✓</td>
<td></td>
</tr>
<tr>
<td>.ogv</td>
<td>✓</td>
<td>✓</td>
<td>✓</td>
</tr>
<tr>
<td>.vp8</td>
<td>✓</td>
<td>✓</td>
<td>✓</td>
</tr>
<tr>
<td>.webm</td>
<td>✓</td>
<td>✓</td>
<td>✓</td>
</tr>
<tr>
<td>.wmv</td>
<td>✓</td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
<p>更多平台兼容性参考</p>
<ul>
<li><strong>Windows</strong>: <a href="https://docs.microsoft.com/en-us/windows/win32/medfound/supported-media-formats-in-media-foundation" target="_blank" rel="noreferrer">Supported Media Formats in Media Foundation</a></li>
<li><strong>macOS</strong>: <a href="https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/OSX_Technology_Overview/MediaLayer/MediaLayer.html" target="_blank" rel="noreferrer">Media Layer Documentation</a></li>
<li>Android: <a href="https://developer.android.com/guide/topics/media/media-formats#recommendations" target="_blank" rel="noreferrer">Media Formats</a></li>
<li>iOS: <a href="https://www.apple.com/iphone/compare/" target="_blank" rel="noreferrer">iPhone Compare</a></li>
</ul>
<p>目标平台兼容性:</p>
<ol>
<li>视频与UnityEditor兼容，和目标平台不兼容：unity提供了转码功能</li>
<li>视频只与目标平台兼容，但是不一定能在UnityEditor播放：使用宏执行对应平台代码段<code>#if</code></li>
</ol>
<p>视频的Inspector参数一览</p>
<ul>
<li>sRGB: 开启sRGB：统一色彩标准确保在不同设备上避免色差默认勾选</li>
<li>Transcode（转码）</li>
<li>AspectRatio: NoScaling不拉申有黑边；Stratch拉伸没黑边但是会失去比例；影响Dimensions的选项</li>
<li>Dimensions尺寸调整
<ul>
<li>Original（保持原始大小）：不改变视频的原始尺寸（一般是这个</li>
<li>Three Quarter Res：其原始宽度和高度的四分之三</li>
<li>Half Res：原始宽度和高度的一半</li>
<li>Quarter Res：原始宽度和高度的四分之一</li>
<li>Square (1024x1024)：1024x1024的正方形，宽高比可控制</li>
<li>Square (512x512)：512x512的正方形，宽高比可控制</li>
<li>Square (256x256)：256x256的正方形，宽高比可控制</li>
<li>Custom：允许用户自定义视频的分辨率，宽高比同样可以控制</li>
</ul>
</li>
<li>Codec（编解码器选择）
<ul>
<li>Auto：自动为所选目标平台选择最合适的视频编解码器。</li>
<li>H264：MPEG-4编+AVC解，广泛支持</li>
<li>H265：MPEG-H Part 2编+HEVC解 提供更高的压缩效率</li>
<li>VP8：一种视频编解码器，受大多数平台上的软件支持，并且在Android和WebGL等几个平台上获得硬件支持</li>
</ul>
</li>
<li>SpatialQuality质量和压缩看着来就行</li>
</ul>
<p>原生VP8编解码器在Android平台上并不支持透明度所以必须启用转码。目的是为了让Unity等应用程序能够使用其内部机制来处理和表示Alpha通道.<br>
<code>AudioSampleProvider buffer overflow. XXXX sample frames discarded.</code>某些平台导入视频之后会出现丢失音频帧没声音，不知道为啥重启就好了。<br>
视频播放使用<strong>VideoPlayer组件</strong>，关联你的VideoClip。<br>
先看Inspector：</p>
<ul>
<li>Source-&gt;URL视频源可以本地可以网络地址</li>
<li>WaitForFirstFrame，准备完了才开播不会丢弃。播放的时候程序是需要一点点准备的，准备消耗的时间也算上，播的时候前面那些丢掉从消耗后的时间开始播</li>
<li>RenderMode-&gt;RenderTexture 把视频输出到Image(这样就可以作为背景了)思路就是使用 <strong>输出到RawImage(大小最好和视频一样)</strong> 就可以放UI中使用了；MaterialOverride可以覆盖物体MeshRender的材质</li>
<li>VideoAspectRatio 缩放比例
<ul>
<li>Fit Vertically（优先适配高度）左右黑边或裁剪；Fit Horizontally（优先适配宽度）上下黑边或裁剪</li>
<li>Fit Inside（适应内部）不裁剪有黑边优先自适应</li>
<li>Fit Outside（适应外部）保留宽高比有裁剪无黑边，充满区域</li>
<li>Stretch（拉伸）不会保留源宽高适应播放窗，视频可能变形</li>
</ul>
</li>
<li>AudioMode的Direct是直接通过Unity播放，AudioSource是通过一个音频源让场景上的音频监听器播放</li>
</ul>
<p>看代码面板上有的一眼能对上的不写。</p>
<details class="details custom-block"><summary>VideoPlayer基本API</summary>
<p>ideoPlayer基本API</p>
<div class="language-Csharp vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">Csharp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> videoplay</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> : </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">MonoBehaviour</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> RenderTexture</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> texture</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> VideoClip</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> clip</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    VideoPlayer</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> videoPlayer</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Start</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        videoPlayer </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Camera.main.gameObject.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">AddComponent</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">VideoPlayer</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>();</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        videoPlayer.playOnAwake </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        videoPlayer.renderMode </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> VideoRenderMode.CameraFarPlane;</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        //videoPlayer.targetTexture = texture;</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> // 贴图模式才能用</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        //videoPlayer.targetCamera</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        videoPlayer.targetCameraAlpha </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 0.5f</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        //videoPlayer.targetCamera3DLayout = Video3DLayout.OverUnder3D;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        videoPlayer.source </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> VideoSource.VideoClip;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        videoPlayer.clip </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> clip;</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        //videoPlayer.source = VideoSource.Url;</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        //videoPlayer.url = Application.streamingAssetsPath + "/Video.mp4";</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(videoPlayer.length);</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//总长多少秒</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(videoPlayer.time);</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//播放了多少秒 可以设置它以从某个时间播放</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(videoPlayer.frameCount);</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  总帧数</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(videoPlayer.frame);</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  当前播放了多少帧</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        videoPlayer.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Prepare</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  需要先准备完才能播，可以提前准备，搭配WaitForFirstFrame用。  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        videoPlayer.prepareCompleted </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">v</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"准备完成事件"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  这里就可以传标志位准备好了按键再播</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        videoPlayer.started </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">v</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"开始Play的事件"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        videoPlayer.loopPointReached </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">v</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"结束Play的事件"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Update</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(Input.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetKeyDown</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(KeyCode.Space))videoPlayer.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Play</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//视频播放</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (Input.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetKeyDown</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(KeyCode.S))videoPlayer.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Stop</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//视频停止</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (Input.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetKeyDown</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(KeyCode.P)) videoPlayer.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Pause</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//视频暂停</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br></div></div></details>
<p>全景视频先不搞</p>
<h3 id="动画系统" tabindex="-1">动画系统 <a class="header-anchor" href="#动画系统" aria-label="Permalink to &quot;动画系统&quot;">&ZeroWidthSpace;</a></h3>
<p>常识类的跳过，窗口在Window-&gt;Animation-&gt;Animation，创建对象可以Assets-&gt;Create-&gt;Animation。动画除了K帧按钮之外还可以添加事件，播放到这个地方的时候就会触发指定的事件。
面板上定位的不是秒数而是当前帧数，默认是60fps<br>
关键对象:</p>
<ul>
<li>AnimationClip 一段动画（描述信息），把这段动画拖到想施加的对象身上(可以加多个对象)，就会产生一个动画状态机AnimatorController，并且为对象增加了Animator组件关联到此状态机。</li>
<li>状态机中可以多次拖入多个AnimationClip</li>
<li>AnimationClip的Inspector 更多 中可以切换为Debug模式，主要是可以调整SampleRate每秒多少帧，和WrapMode播放模式</li>
<li>在动画Animation窗口的 更多 中也可以切换帧率和以秒显示时间轴。</li>
</ul>
<p><strong>新动画系统</strong>，Mecanim动画系统主要用<code>Animator</code>状态机组件来控制动画。<br>
人物的动作是有限的，且同一时间只能有一个动作状态，而且随时可以切换(任意状态)，动画和游戏AI是有限状态机应用的绝佳场景。<br>
AnimatorController可以在Animator窗口中编辑，注意窗口中的重要参数:</p>
<ul>
<li>Layers可以为动画分层级，调整Weight权重可以让动画播放覆盖或者融合，越靠近1权重越大。</li>
<li>Parameters可以添加基础类型的参数。</li>
<li>默认就带三个状态，初始Entry，Exit退出，AnyState任意。橙色的动画和Entry相连，表示进入的默认状态，灰色是自己拖进来的。状态AnimationState是关联动画AnimationClip的。
<ul>
<li>播放到最后一个状态是会一直loop，双向 连线Transition 会两个动画循环播放</li>
</ul>
</li>
<li>每个Transition中都可以绑定参数列表Parameters中的参数，设置参数对应的条件，满足条件才能够触发动画，多个条件是与判断
<ul>
<li>Tirgger类型 置为true触发后会自动变回false，一般用来点一下触发一次动画，然后自动返回上一个状态的动画</li>
<li>Transition的HasExitTime属性控制切换动画的时候是不是要把当前这个播放完</li>
</ul>
</li>
<li>直接Play就可以指定播放但是一般不用</li>
</ul>
<p>多种怪物和角色复用状态机，Project-&gt;右键Create-&gt;AnimatorOverrideController，关联需要继承和改变的状态机，然后就可以替换所有的AnimationCliper，达到保留原状态机调整的参数和事件，只替换掉动作复用的效果。<br>
和AnyState连接的Transition要取消勾选CanTransitionToSelf，不然死了会一直自己切换自己，循环播放最后一个一直抖</p>
<details class="details custom-block"><summary>使用AnimatorController代码控制动画</summary>
<p>用AnimatorController代码控制动画</p>
<div class="language-Csharp vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">Csharp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> AnimeTest</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">MonoBehaviour</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    Animator</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> animator</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Start</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        animator </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> GetComponent</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Animator</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>();</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        animator.runtimeAnimatorController </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Resources.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Load</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">RuntimeAnimatorController</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>(monsterInfo.animator); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 可以在运行时通过Resources动态加载Animator资源赋值</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Update</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        bool</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> b1</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> animator.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetBool</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"b1"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        bool</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> b2</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> animator.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetBool</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"b2"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        animator.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">SetBool</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"b1"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        // 可用API包括 SetFloat SetInteger SetTrigger；Get同理</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br></div></div></details>
<div class="warning custom-block"><p class="custom-block-title">[⚠️Warning] 新老动画系统中的AnimationClip不能通用</p>
<p>老动画系统中的AnimationClip不能通用
拖进去之后AnimatorController中的State绑定不了旧Clip，可以手动转换或者创建新的。</p>
</div>
<p><strong>老动画系统</strong>，Animation动画系统用<code>Animation</code>组件代码来控制动画<br>
在需要动画的物体上挂载Animation组件，此时不会在自动创建Animator和AnimatorController，这个组件上的参数:</p>
<ul>
<li>Animation和Animations默认播放 和 绑定了可以用代码获得的 AnimationClip</li>
<li>CullingType: Always一直播放或者BasedOnRenderers渲染不到的时候不播放
当你 要播放动画的状态 和 动画开始状态 不一样的时候才会产生过渡效果，系统会自动计算，比如A-&gt;B,A-&gt;C。播放A-&gt;C的时候会先把物体从B状态过渡到A状态（不一定是还原。<br>
一般动画和属性改变应该是分离的</li>
</ul>
<details class="details custom-block"><summary>使用Animation组件控制动画</summary>
<p>用Animation组件控制动画</p>
<div class="language-Csharp vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">Csharp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> TestAnimation</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> : </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">MonoBehaviour</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    private</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Animation</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> anim</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Start</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        anim </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> GetComponent</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Animation</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>(); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 获得动画组件</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Update</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (Input.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetKeyDown</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(KeyCode.Alpha1))</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            anim.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Play</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"anime1"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 播放动画1</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        }</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (Input.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetKeyDown</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(KeyCode.Alpha2))</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            anim.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Play</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"anime2"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 会把当前动画中断去播放动画2</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            anim.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">CrossFade</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"anime2"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 把当前动画中断但是系统会自动计算一个插值，去播放动画2，看起来更顺畅</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            anim.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">PlayQueued</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"anime2"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 队列播放，放完上一个才放动画2，但是也没有过渡</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            anim.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">CrossFadeQueued</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"anime2"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (Input.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetKeyDown</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(KeyCode.S))</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            anim.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Stop</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 停止所有动画</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        }</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (anim.isPlaying </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">==</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            Debug.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"有动画正在播放"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        }</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (anim.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">IsPlaying</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"anime2"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">))</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">           Debug.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"正在播放动画2"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> AnimationEvent</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">int</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> param1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 界面上可以为动画事件传参数，什么都可传</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Debug.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">$"Trigger AnimationEvent total Frame: {</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Time</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">frameCount</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">}"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br></div></div></details>
<h4 id="_3d模型" tabindex="-1">3D模型 <a class="header-anchor" href="#_3d模型" aria-label="Permalink to &quot;3D模型&quot;">&ZeroWidthSpace;</a></h4>
<p>导入规范上面写了不重复，一个fbx Assets 的设置主要这四个Model Rig Animation Materials<br>
先记一下需要加深印象的参数，其他参数用到了去查或者问AI<br>
<strong>Model</strong>：</p>
<ul>
<li>GlobalScale 当模型中的比例不符合项目中的预期比例时，修改此值来改变该模型的全局比例。<strong>Unity的物理系统希望游戏世界中的1米在导入模型文件中为1个单位</strong></li>
<li>ConvertUnits启用可将模型文件中定义的模型比例转换为Unity的比例。不同的格式的比例 <code>.fbx .max .jas = 0.01</code> <code>.3ds = 0.1</code> <code>.mb .ma .lxo .dxf .blend .dae = 1</code></li>
<li>MeshCompression是不是压缩一下网格节省性能</li>
<li>Read/Write是否在内存中保留网格信息以供读写，增加内存占用。
<ol>
<li>需要在代码中读取或写入网格数据。</li>
<li>需要运行时合并网格</li>
<li>需要使用网格碰撞器时</li>
<li>需要运行时使用NavMesh构建组件来烘焙NavMesh时</li>
</ol>
</li>
<li>WeldVertices合并在空间中共享位置的顶点，前提是这些顶点总体上共享相同属性(UV 法线 切线)，能优化网格的顶点计数，一般开启除非你想运行的时候获取并修改顶点<br>
<strong>Rig:</strong></li>
<li>AnimationType
<ul>
<li>None环境等不需要骨骼和动画的</li>
<li>Humanoid人形的模型，可以指定此模型的Avatar信息，可以使用模型自己的或者复制其他模型的Avatar信息</li>
<li>Generic 通用不规则模型，比人形多一个RootNode参数，设置用于此Avatar的根节点骨骼</li>
</ul>
</li>
<li>Avatar化身系统，让人形模型已经绑定好的模型动作可以在其他的人形模型上复用，Assets中编辑Avatar或者在模型Rig中Configure就可以打开编辑页
<ul>
<li>Mipping为标准人形对应模型中的骨骼，在页签左下可以保存/读取到文件，自动应用等。姿势建议使用强制T姿势，美术一般也使用这个。</li>
<li>Muscles&amp;Settings肌肉群设置。可以设置不同姿势旋转变化预览映射关系是否合理。Pre-MuscleSettings设置骨骼在旋转时的范围限制，TranslationDoF如果需要骨骼长度变化拉伸的动画才开启。<br>
<strong>Animation：</strong><br>
动画文件是可以单独导出的，建议美术导出 <strong>只包含网格信息不包含动作的模型</strong> 与 <strong>只包含动作不包含网格信息的文件</strong> <a href="https://docs.unity.cn/cn/2022.2/Manual/Splittinganimations.html" target="_blank" rel="noreferrer">动画导出标准</a></li>
</ul>
</li>
<li>ImportAnimation是否导入动画的总开关</li>
<li>Anim.Compression导入动画时使用的压缩类型
<ul>
<li>禁用压缩效果好耗性能</li>
<li>Keyframe Reduction（减少冗余关键帧）仅适用于Generic通用动画类型</li>
<li>Keyframe Reduction and Compression（减少关键帧并在文件中存储动画时压缩关键帧）仅适用于Legacy旧版动画类型会影响文件大小，但内存大小与Keyframe Reduction相同</li>
<li><strong>Optimal（让Unity决定如何压缩）</strong> 仅使用Generic通用和Humanoid人形动画类型</li>
</ul>
</li>
<li>Clips 动画在导出的时候可能会把一个长的动画导出，然后根据关键帧切成多个Clips，在这里可以添加Clips
<ul>
<li>LoopTime动画是不是循环播放，Loop Pose无缝循环 和Loop Match平滑过渡，CycleOffset第一次播放从哪一帧开始一般不调整。如果属性后面的灯绿了说明是开始结尾对齐的。</li>
<li>在RootTransformRotation和下面三个参数中，有个最重要的属性<strong>BakeIntoPose烘焙到动作</strong> 此选项决定<strong>动作产生的移动是否应用到根还是只有动画动作</strong>，下面几个也是根据不同轴的平面来分的。</li>
<li>Mirror人形镜像反转只有人形能用</li>
<li>Curves可以在动画播放过程中按照曲线更改一个同名的自定义值，创建一个动画状态机和条件值，把动画扔进去状态机应用到人物，新建一个和曲线名称相同的变量，就可以在代码中获得这个随着播放曲线变化的值（没啥用</li>
<li><strong>Events</strong>动画事件(和下面的 状态机行为脚本 对比一下)，可以在指定帧插入一个Event，确定Event的名字和要传的参数，啥都不改就是没有参数。 <mark>动画过渡时间不会触发 他会在运行的时候查找所有挂载在物体上的脚本执行同名的函数，找不到就报错</mark></li>
<li>Mask编辑遮罩，可以让遮罩的部位动画失效，人形的自带了一个，非人形的要自己绑<br>
预览窗口可以查看IK查看质心 根等，可以拖模型进来预览等。<br>
<strong>Materials：</strong></li>
</ul>
</li>
<li>MaterialImportMode 导入模型使用的材质
<ul>
<li>None 不使用此模型的任何材质，用Unity默认的漫反射材质</li>
<li>Standard使用Unity默认规则来生成材质</li>
<li>ImportviaMaterialDescription使用FBX中嵌入的材质来生成Unity中的材质（但注意，材质一半是在游戏内部来设置的，建模中的材质可能和Unity中的材质不一样，很多时候不选。</li>
</ul>
</li>
<li>UseSRGBMaterialColor是否在伽玛空间中使用反射率颜色，使用线性颜色空间时禁用此选项，使用FBX嵌入的材质时此选项不会出现。</li>
<li>Location选择UseEmbeddedMaterials可以在下面提取嵌入的Material材质和Texture贴图
<ul>
<li>EthanWhite如果解析出来了使用哪个材质，一般解析成功了就会默认一个正确的</li>
</ul>
</li>
<li>Naming 材质的命名 Search就是从哪些地方搜索此模型要用的材质</li>
</ul>
<p><strong>状态机行为脚本</strong> 在State上可以挂脚本，这个脚本比较特殊，继承StateMachineBehaviour，当角色进入、退出或保持在某一个特定状态时，可以通过这些脚本进行一些逻辑处理。就是在AnimatorController状态机窗口中的某个状态添加一个脚本来实现一些特殊功能，比如播放声音检测落地播放特效等<br>
主要的生命周期函数，必须overraid指定的函数进行操作，参数都是一样的。+</p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>Animator animator 挂载的动画组件</span></span>
<span class="line"><span>AnimatorStateInfo stateInfo 脚本挂载的状态</span></span>
<span class="line"><span>int layerIndex 状态所在的层</span></span>
<span class="line"><span></span></span>
<span class="line"><span>OnStateEnter 进入状态时，第一个Update中调用</span></span>
<span class="line"><span>OnStateExit 退出状态时，最后一个Update中调用</span></span>
<span class="line"><span>OnStateIK 在OnAnimatorIK后调用</span></span>
<span class="line"><span>OnStateMove 在OnAnimatorMove后调用</span></span>
<span class="line"><span>OnStateUpdate 除第一帧和最后一帧，每个Update上调用</span></span>
<span class="line"><span>OnStateMachineEnter 子状态机进入时调用，第一个Update中调用</span></span>
<span class="line"><span>OnStateMachineExit 子状态机退出时调用，最后一个Update中调用</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br></div></div><blockquote>
<p><strong>状态机行为脚本</strong> 和 <strong>Events</strong>动画事件相比更精确，但是更麻烦</p>
</blockquote>
<h4 id="混合动画" tabindex="-1">混合动画 <a class="header-anchor" href="#混合动画" aria-label="Permalink to &quot;混合动画&quot;">&ZeroWidthSpace;</a></h4>
<p><strong>动画分层</strong>
比如上半身播放开枪动画，下半身可以蹲跑跳，由不同的动画层组合播放。在Animator窗口中，添加状态机Layer，每个Layer对动画的影响是同时施加的。
Layer的参数：</p>
<ul>
<li>Weight 权重，选择叠加模式Addtive的时候混合占比多高；使用覆盖模式Overraid的时候，谁权重最高就播放哪个。第一层强制为1最高</li>
<li>Mask遮罩，可以选择一个遮罩对该层动画都生效而不需要修改模型的遮罩（遮罩可以在Assets中创建Avatar</li>
<li><strong>Sync</strong> 同步，开启之后可以选择一个Layer同步，此时会复制这个Layer中的所有状态，可以为复制过来的State更改绑定的Motion，然后通过代码更改Weight达到按照权重混合的模式，比如按照血量更改走路姿势等。
<ul>
<li>Timing勾了会让复制过来的State播放速度根据Weight改变</li>
</ul>
</li>
<li>多层动画叠加播放的时候，比如上半身射击下半身跑走，用mask隔开，上半身Layer的可以创建一个空状态作为默认状态，然后利用Trigger触发</li>
</ul>
<p><strong>混合树</strong><br>
在AnimatorController-&gt;CreateState-&gt;FromNewBlendTree创建一个混合树，双击混合树可以编辑。<br>
在Blend参数那可以选择类型，<strong>1D混合</strong>树就是只用一个参数控制的混合树，此时就已经自动创建了一个参数。<br>
此时就有一个可以调节的二维坐标，X轴即为变量，Y轴即是播放Motion里哪个的Threshold权重，会按照权重混合起来播放。可以在Motion中调整权重和速度 。<br>
AutomateThreshold自动权重会自动平分权重（一般就是0-1之间的权重，使用混合树可以达到参数逐渐增加动作从idle-&gt;walk-&gt;run这个效果，当然衔接和相似度越高看起来越好。<br>
<strong>2D混合</strong>就是两个参数控制动画混合程度。在Paramters中指定绑定的参数。</p>
<ul>
<li>2D Simple Directional 2D简单定向模式 运动表示不同方向时使用 比如向前、后、左、右走</li>
<li>2D Freeform Directional 2D自由形式定向模式 同上 运动表示不同方向时使用 但是可以在同一方向上有多个运动 比如向前跑和走</li>
<li>2D Freeform Cartesian 2D自由形式笛卡尔坐标模式 运动不表示不同方向时使用 比如向前走不拐弯 向前跑不拐弯 向前走右转 向前跑右转</li>
<li>Direct 直接模式 自由控制每个节点权重 一般做表情动作等（大型游戏才会做表情系统</li>
</ul>
<p>混合树嵌套看混合树的工作流图，就可以知道怎么嵌套的<br>
此时在图表中就可以编辑不同的Motion的权重位置，三种2D混合树只是算法不同，作用是一样的。<br>
<strong>子状态机</strong><br>
可以把多个状态机连成一个子状态机，直接在AnimatorController-&gt;Create-&gt;SubStateMachine.<br>
注意:  <mark>连接UpperStateMachine的时候，如果直接连出去会播放上层的默认动画，连过去的时候右键UpperStateMachine可以选择转移到上层哪个状态</mark><br>
<strong>IK控制</strong>
在动画Animator窗口-&gt;Layer的设置IK Pass此层的动画才会受到IK影响，IK动画控制用来捡东西弓箭锁定瞄准，上半身随着鼠标旋转下半身走路等场景。<br>
IK在Update和LateUpdate之间被调用，也就是说会在每帧的状态机和动画处理完后调用<strong>OnAnimatorIK</strong>(处理IK)在<strong>OnAnimatorMove</strong>(处理根运动)之前调用</p>
<details class="details custom-block"><summary>IK代码控制</summary>
<p>K代码控制</p>
<div class="language-Csharp vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">Csharp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> CodeIK</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> : </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">MonoBehaviour</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Animator</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> ant</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Transform</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> pos</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Start</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {        </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        ant </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> this</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetComponent</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Animator</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>();  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }    </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    private</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> OnAnimatorIK</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">int</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> layerIndex</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 特殊生命周期函数  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        ant.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">SetLookAtWeight</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1f</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1f</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 设置头部IK权重，这函数重载了5次，注意参数，去界面上调一调。  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        // weight: 全局权重  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        // bodyWeight: 身体的权重  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        // headWeight: 头部的权重  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        // eyesWeight: 眼睛的权重  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        // clampWeight  限制角色转动幅度的权重0不限制1完全不能转动0.5转一半  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        ant.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">SetLookAtPosition</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(pos.position);</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 设置头部IK看向的位置，可以目光和头跟着位置动  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        ant.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">SetIKPositionWeight</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(AvatarIKGoal.RightHand, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 设置Avatar某个IK点(四个枚举可以在Avatar骨骼那里查看)的位置权重  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        ant.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">SetIKRotationWeight</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(AvatarIKGoal.RightHand, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  旋转权重  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        ant.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">SetIKPosition</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(AvatarIKGoal.LeftHand,pos.position);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        ant.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">SetIKRotation</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(AvatarIKGoal.LeftHand,pos.rotation);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br></div></div></details>
<p><strong>动画目标匹配</strong>，比如跳过障碍，脚指定落点抓住房梁等。</p>
<div class="warning custom-block"><p class="custom-block-title">[⚠️Warning] 调用目标匹配限制</p>
<p>用目标匹配限制
必须保证动画已经切换到是目标动画上，不能在(前后)过渡阶段，开启ApplyRootMotion根运动</p>
</div>
<p>注意调用方式，可以通过动画的Events触发，保证满足目标匹配的触发限制</p>
<details class="details custom-block"><summary>动画目标匹配</summary>
<p>画目标匹配</p>
<div class="language-Csharp vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">Csharp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> MatchMotion</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> : </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">MonoBehaviour</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    private</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Animator</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> ant</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Transform</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> jumpTarget</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Start</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        ant </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> GetComponent</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Animator</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>();</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Update</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (Input.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetKeyDown</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(KeyCode.Space))</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            ant.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">SetTrigger</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Jump"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  只触发动画</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Jump</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">() </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 通过动画的Events触发，保证满足目标匹配的触发限制</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Debug.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"jump trigger"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        ant.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">MatchTarget</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(jumpTarget.position,</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 目标位置，角度</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            jumpTarget.rotation,AvatarTarget.LeftFoot,</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 匹配的骨骼位置播放完之后哪个位置要和指定的位置重合</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> MatchTargetWeightMask</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(Vector3.one, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">),</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 位置角度权重。位置权重X/Y/Z 轴的权重都是1，表示完全匹配位置（移动到目标位置）旋转匹配权重：1，表示完全匹配旋转（朝向与目标一致）。</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">            0.4f</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 开始位移动作的百分比，播放到百分之多少开始位移</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">            0.63f</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 结束位移动作的百分比</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br></div></div></details>
<h4 id="角色控制器" tabindex="-1">角色控制器 <a class="header-anchor" href="#角色控制器" aria-label="Permalink to &quot;角色控制器&quot;">&ZeroWidthSpace;</a></h4>
<p>人形Avatar更合适角色控制器，添加角色控制器之后不需要再添加刚体，能检测触发器 碰撞 射线，使用的时候需关闭Anmiator的<code>ApplyRootMotion</code>使用角色控制器的好处是可以避免使用刚体判断碰撞时容易撞飞斜坡滑动抖动等角色bug，控制角色更稳定。
CharacterController组件，用了这个就不用Collider和Rigidbody, 自带一个Collider不过形状未知。</p>
<ul>
<li>Slope Limit: 控制角色最大的爬坡斜率</li>
<li>Step Offset: 控制角色可以迈上最大的台阶高度</li>
<li>Skin Width: 在角色的外圈包裹着一层“皮肤”的厚度，如果Skin Width设置为1米，那么角色当然就会“浮空”1米，一般保持默认即可</li>
<li>Min Move Distance: 最小移动距离，默认为1毫米，如果该数值过大但代码中单位移动速度很慢，角色就不会动</li>
<li>Center/Radius/Height: 角色控制器组件在Scene面板中体现为一个“胶囊碰撞器”的形状，这也导致其他的碰撞体我们并不需要，Center为胶囊中心点位置，Radius为半径，Height为高度</li>
<li>不使用 Rigidbody 的物理系统，也就是说，它不会被力推着走也不会自动转动，<strong>纯粹的碰撞盒 + 自己写的运动逻辑</strong>例如 <code>controller.Move(Vector3)</code>
<ul>
<li>所以如果要让CharacterController转向需要</li>
</ul>
</li>
</ul>
<p>注意组件的方法<br>
<code>characterController.isGrounded</code>返回布尔值，检测是否在地面上。<br>
<code>characterController.Move(vector3.forward);</code> 和<code>transform.Translate</code>类似,没有重力适合平地，需要传递向量，数值大小会直接影响移动速度，所以要乘<code>Time.deltaTime</code><br>
<code>characterController.SimpleMove(vector3.forward);</code>在Update里调用会自动应用重力，需要传递一个速度，不受帧率影响，不需要乘<code>Time.deltaTime</code><br>
<code>public void OnControllerColliderHit(ControllerColliderHit hit){}</code> 额外提供了碰撞检测函数，接收被碰撞的对象，但是常规的碰撞函数就没用了，常规的触发器函数还有用</p>
<h3 id="寻路导航" tabindex="-1">寻路导航 <a class="header-anchor" href="#寻路导航" aria-label="Permalink to &quot;寻路导航&quot;">&ZeroWidthSpace;</a></h3>
<p>Unity的寻路本质是A星寻路的拓展和优化，A星只支持2D和静态阻挡，navi3D和动态阻挡都支持。<br>
<a href="https://www.bilibili.com/video/BV1PGqgYKE7d/" target="_blank" rel="noreferrer">2代和一代不太一样</a>，新版本的支持动态烘焙<br>
注意这几个重要的对象 导航网格 (NavMesh) 导航网格寻路组件 (NavMesh Agent) 导航网格连接组件 (Off-Mesh Link) 导航网格动态障碍物组件 (NavMesh Obstacle)。 导航的单位都是米<br>
做导航的流程，定义地形和消耗，烘焙，设置导航寻路Agen，设置障碍。</p>
<div class="warning custom-block"><p class="custom-block-title">[⚠️Warning]</p>
<p>注意如果已经烘焙好了导航网格会无视碰撞体直接穿过去，所以最好障碍一块烘焙导航网格，烘焙网格不能运行过程中动态生成。</p>
</div>
<h4 id="老版本" tabindex="-1">老版本 <a class="header-anchor" href="#老版本" aria-label="Permalink to &quot;老版本&quot;">&ZeroWidthSpace;</a></h4>
<p>2022之后的版本需要额外安装Window-&gt;PackageManager-&gt;AI Navigation才能启用老版本。装完在Winodow-&gt;AI-&gt;Navigation(Obsolete)打开。<br>
<strong>地形烘焙</strong>:<br>
Object 中可以过滤场景中物体，方便设置导航属性，在Static中设置导航静态NavigationStatic物体才能参与地形烘焙。<strong>Terrins是挂载了的地形脚本的对象</strong><br>
Area 中可以规定导航区域的寻路消耗，在Object的 NavigationArea中选择，寻路的时候会根据消耗和路径选择消耗最少的路径。
Bake 参数一览:</p>
<ul>
<li>AgentRadius 烘焙边缘精确度，可行走区域的padding</li>
<li>AgentHeight 拱桥是否可穿越的高度</li>
<li>MaxSlope 斜坡是否可以行走的度数</li>
<li>StepHeight 最小楼梯高度，台阶是否可以行走</li>
<li>Generated off mesh Links
<ul>
<li>DropHeight 可以从小于此高度掉下来继续寻路</li>
<li>JumpDistance 小于此间距的视为可以跳跃过去继续寻路，只要你设置了小于这个间隙的就一定能跳过去无视性能，你说这扯不扯</li>
</ul>
</li>
<li>VoxelSize 设置(立)体(像)素大小,控制烘焙的准确度,立体像素大小减半会使内存使用量增加4倍，构建时间也增加4倍,除非想要极其准确的导航网格再去修改</li>
<li>MinRegionArea 面积小于此处值的导航网格区域会被移除</li>
<li>HeightMesh高度网格构建开关 解决楼梯烘焙为斜坡时，希望在楼梯表面的位置 准确的放置在楼梯平面而不是斜坡上，启用它会增加烘焙时间</li>
<li>Bake完之后会在场景下同名文件夹生成对应的烘焙数据。<br>
Agents 中的参数和bake差不多 调整某个对象的代理对象，默认使用人形代理。</li>
</ul>
<p><strong>NavMeshAgent组件</strong>：需要导航的对象挂上就多了一个寻路检测盒，参数:</p>
<ul>
<li>AgentType 代理类型，使用Agents中哪个预设的参数用</li>
<li>BaseOffset 寻路检测盒的偏移</li>
<li>Steering移动设置
<ul>
<li>Speed寻路时最大移速 Angular Speed寻路时转身的最大旋转速度(度/秒) Acceleration最大加速度</li>
<li>StoppingDistance 距目标点小于此距离时停止移动</li>
<li>Auto Braking 到达目标点自动制动 连续移动比如巡逻移动时不要开启</li>
</ul>
</li>
<li>ObstacleAvoidance 避障设置
<ul>
<li>Radius/Height 寻路检测盒的半径/高度</li>
<li>Quality 障碍躲避精度，越高躲避障碍越准确，但是性能消耗较大，如果不想主动避开其它动态障碍，可以设置为无，则只会解析碰撞 #todo</li>
<li>Priority 优先级，0~99，避障时，数字较小的障碍物表示较高的优先级优先级低的会忽略避障 #todo</li>
<li>Auto Traverse OffMesh Link是否开启自动遍历网格格外的其它网格连接</li>
</ul>
</li>
<li>PathFinding寻路规则
<ul>
<li>AutoRepath 是否开启自动重设路线，当到达路径后段时会再次尝试寻路，到不了的时候就找个离目标最近的点，经典RTS人在对岸小兵卡住</li>
<li>AreaMask 寻路时纳入的区域,寻路时不想考虑某些区域，则取消选中塔防游戏中常见的功能</li>
</ul>
</li>
</ul>
<details class="details custom-block"><summary>NavMeshAgent的API</summary>
<p>avMeshAgent的API</p>
<div class="language-Csharp vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">Csharp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Update</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (Input.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetMouseButtonDown</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">))</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Debug.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"鼠标点击导航点"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        Ray</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> ray</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Camera.main.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">ScreenPointToRay</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(Input.mousePosition);</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        RaycastHit</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> hit</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (Physics.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Raycast</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(ray, </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">out</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> hit))</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            agent.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">SetDestination</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(hit.point); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  设置导航目标点</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            agent.isStopped </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  停止导航，再次导航必须打开</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            Debug.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"目标点: "</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> +</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> hit.point);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(agent.velocity.sqrMagnitude </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x3C;</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 0.01f</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) animator.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">SetBool</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"run"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 利用速度判断动画状态机</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    else</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> animator.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">SetBool</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"run"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">#</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">region</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 不常用API</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(agent.speed); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//1.面板参数相关 速度 </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(agent.acceleration); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//1.面板参数相关 加速度 </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(agent.angularSpeed); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//1.面板参数相关 旋转速度</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(agent.hasPath){} </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//2-1当前是否有路径</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(agent.destination); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//2-2代理目标点 可以设置 也可以得到</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(agent.isStopped); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//2-3是否停止 可以得到也可以设置</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(agent.path); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//2-4当前路径</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(agent.pathPending){} </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//2-5路径是否在计算中</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(agent.pathStatus); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//2-6路径状态</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">agent.updatePosition </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//2-7是否更新位置</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">agent.updateRotation </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//2-8是否更新角度</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(agent.velocity); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//2-9代理速度</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">NavMeshPath</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> path</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> NavMeshPath</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(agent.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">CalculatePath</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(Vector3.zero, path)){} </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//计算生成路径</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(agent.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">SetPath</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(path)){} </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//设置新路径</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">agent.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">ResetPath</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//清除路径</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">agent.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Warp</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(Vector3.zero); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//调整到指定点位置</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">#</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">endregion</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br></div></div></details>
<blockquote>
<p>agent.velocity 的开销极低 velocity 是 NavMeshAgent 的一个属性，本质是 Unity 内部已经计算好的一个 Vector3，取它只是一次内存读取。sqrMagnitude 只是 xx + yy + zz 三次乘法一次加法，比 Magnitude（会开平方）更省。
animator.SetBool 也是轻量操作 Animator 参数更新是在下一帧的动画系统中批量处理的，你调用 SetBool 只是把值写到一个缓存，并不会立刻重算整套动画。</p>
</blockquote>
<p><strong>OffMeshLink网格外连接组件</strong> 他可以挂在任何一个东西上，只要把start end 拖上去就行<br>
参数:</p>
<ul>
<li>CostOverride -1或者0使用所在区域的消耗值，否则使用 所在 <code>区域消耗值*CostOverride</code></li>
<li>BiDirectional 让不让从end跳回start</li>
<li>Activated 激活失活</li>
<li>AutoUpdatePositions 在运行过程中动态修改跳跃点对象位置时，导航网格也更新</li>
</ul>
<p><strong>NavMeshObstacle动态障碍组件</strong>，给物体挂上就会有一个导航体积盒，可以运行中动态计算导航<br>
Carve 该障碍会在烘焙网格上动态开孔，固定不动的建议为true(门栅栏什么的)，移动的不用(玩家汽车什么的)</p>
<ul>
<li>MoveThreshold移动超过该距离时会认为其为移动状态，更新移动的孔</li>
<li>TimeToStationary单位为秒 超过该值会认为真正静止</li>
<li>CarveOnlyStationary（只有在静止状态时才会计算孔）</li>
</ul>
<p>#todo 这个障碍被玩家点击破坏才能通过练习题核心P95</p>
<h4 id="新版本" tabindex="-1">新版本 <a class="header-anchor" href="#新版本" aria-label="Permalink to &quot;新版本&quot;">&ZeroWidthSpace;</a></h4>
<p>现在内置的已经是新版本了。
新版本把Bake和Object独立出来了，在任意组件上挂载NavMeshSurface组装一下，</p>
<p><a href="https://www.bilibili.com/video/BV1PdQZYGEAh" target="_blank" rel="noreferrer">你说熟悉Unity的导航寻路，那我问你--1.如何用网格表示世界_哔哩哔哩_bilibili</a><br/>
<a href="https://www.bilibili.com/video/BV1zRebetE6C/" target="_blank" rel="noreferrer">【Unity3D基础】【导航系统】新版本导航系统的使用方法_哔哩哔哩_bilibili</a><br/>
<a href="https://www.bilibili.com/video/BV1Lv421i7MY/" target="_blank" rel="noreferrer">全网最详细Unity NavMesh寻路第一期：基础讲解，烘焙场景_哔哩哔哩_bilibili</a></p>
<h3 id="粒子系统" tabindex="-1">粒子系统 <a class="header-anchor" href="#粒子系统" aria-label="Permalink to &quot;粒子系统&quot;">&ZeroWidthSpace;</a></h3>
<p>类似下雪下雨法球之类的，很多都用到粒子，程序主要是使用粒子，而不需要自己做粒子。<br>
粒子就是普通的空gameObject，但是挂载了Particle System(Create-&gt;Effects-&gt;ParticleSystem)
在ParticleSystem组件下，以下几个属性常用：</p>
<ul>
<li>Duration持续时间</li>
<li>looping是否循环</li>
<li>startLifetime每个粒子的存活时间</li>
<li>playOnAwake是否一开始就播放，如果设置false，那就只能在代码里获得然后播放</li>
<li>stopAction选项很明确，Disable播放完后禁用自己，Destory播放完之后销毁自己，Callback要自己去绑定回调方法了但很少这么做。</li>
</ul>
<h2 id="_2d系统" tabindex="-1">2D系统 <a class="header-anchor" href="#_2d系统" aria-label="Permalink to &quot;2D系统&quot;">&ZeroWidthSpace;</a></h2>
<p>在开始选择的时候2D和3D只是预设不同，其他的没什么区别，但是我也不知道为什么有些东西建了3D项目导入不进去2D就可以比如标准包里的瓦片</p>
<table tabindex="0">
<thead>
<tr>
<th>大致看一眼留个印象</th>
<th>2D 工程（默认设置）</th>
<th>3D 工程（默认设置）</th>
</tr>
</thead>
<tbody>
<tr>
<td>摄像机投影方式</td>
<td>正交 (Orthographic)</td>
<td>透视 (Perspective)</td>
</tr>
<tr>
<td>场景视图模式</td>
<td>默认启用 2D 视图</td>
<td>默认启用 3D 视图</td>
</tr>
<tr>
<td>对象坐标轴方向</td>
<td>X（横）、Y（竖）</td>
<td>X（横）、Y（高）、Z（深度）</td>
</tr>
<tr>
<td>图片导入类型</td>
<td>Sprite</td>
<td>Texture（Default）</td>
</tr>
<tr>
<td>精灵渲染组件</td>
<td>SpriteRenderer</td>
<td>MeshRenderer</td>
</tr>
<tr>
<td>碰撞体类型</td>
<td>Collider2D 系列（Box2D）</td>
<td>Collider 系列（PhysX）</td>
</tr>
<tr>
<td>刚体组件</td>
<td>Rigidbody2D</td>
<td>Rigidbody</td>
</tr>
<tr>
<td>地面检测/射线等默认行为</td>
<td>使用 Physics2D</td>
<td>使用 Physics</td>
</tr>
<tr>
<td>默认物理引擎</td>
<td>Box2D（2D 物理）</td>
<td>NVIDIA PhysX（3D 物理）</td>
</tr>
<tr>
<td>Tilemap 支持</td>
<td>默认包含（可用于地图编辑）</td>
<td>需手动添加 Tilemap 支持</td>
</tr>
<tr>
<td>渲染管线</td>
<td>通常为 Built-in 或 2D Renderer（URP）</td>
<td>通常为 Built-in、URP 或 HDRP</td>
</tr>
<tr>
<td>照明系统</td>
<td>基本无光照（除非手动添加）</td>
<td>支持光源、阴影、材质、反射等</td>
</tr>
</tbody>
</table>
<h3 id="素材相关" tabindex="-1">素材相关 <a class="header-anchor" href="#素材相关" aria-label="Permalink to &quot;素材相关&quot;">&ZeroWidthSpace;</a></h3>
<p>需要搞懂的几个流程概念：</p>
<ol>
<li>建模
<ul>
<li>模型，面片，网格信息</li>
</ul>
</li>
<li>展开UV
<ul>
<li>UV，U轴和V轴</li>
</ul>
</li>
<li>纹理贴图
<ul>
<li>材质(shader决定材质展现效果)，纹理，贴图</li>
</ul>
</li>
<li>骨骼</li>
<li>动画</li>
</ol>
<p>概念不赘述，想不起来的搜。<br>
伽玛颜色空间，<a href="https://learnopengl-cn.github.io/05%20Advanced%20Lighting/02%20Gamma%20Correction/" target="_blank" rel="noreferrer">详细的解释</a>，<a href="https://docs.unity3d.com/cn/2022.3/Manual/LinearRendering-LinearOrGammaWorkflow.html" target="_blank" rel="noreferrer">Unity的颜色空间文档</a></p>
<blockquote>
<p>建模一般使用三角形面片，因为在数学和物理上有天然优势。三角形是唯一总是<strong>共面</strong>的最小多边形，<strong>无论三个顶点怎么放，都始终在同一个平面上</strong> 的图形；图形硬件和渲染管线只支持三角形；三角形可以组成任意复杂模型，不存在“无法拼出来”的情况。建模和美术工具链中三角形是公认标准</p>
</blockquote>
<h4 id="图像材质导入" tabindex="-1">图像材质导入 <a class="header-anchor" href="#图像材质导入" aria-label="Permalink to &quot;图像材质导入&quot;">&ZeroWidthSpace;</a></h4>
<div class="tip custom-block"><p class="custom-block-title">[💡Tip] Unity支持的图片格式</p>
<p>nity支持的图片格式</p>
<ul>
<li>BMP：是Windows操作系统的标准图像文件格式，特点是几乎不进行压缩，占磁盘空间大。</li>
<li>TIF：基本不损失图片信息的图片格式，缺点是体积大。</li>
<li>JPG：一般指JPEG格式，属于有损压缩格式，能够让图像压缩在很小的存储空间，但一定程度上会损失图片数据，无透明通道。</li>
<li>PNG：无损压缩算法的位图格式，压缩比高，生成文件小，有透明通道。</li>
<li>TGA：支持压缩，使用不失真的压缩算法，还支持编码压缩。体积小，效果清晰，兼备BMP的图像质量和JPG的体积优势，有透明通道。</li>
<li>PSD：是Photoshop（PS）图形处理软件专用的格式，通过一些第三方工具或自制工具可以直接将PSD界面转为UI界面。</li>
<li>EXR</li>
<li>GIF</li>
<li>HDR</li>
<li>IFF</li>
<li>PICT
其中，Unity最常用的图片格式是JPG、PNG和TGA三种格式。</li>
</ul>
</div>
<p>导入了图片之后在Inspactor面板可以选择材质类型(TextureType) 贴图，法线贴图等等。怎么这么多参数要记
<strong>TextureType</strong>类型,大致记一下就好，遇到增量补充:</p>
<ol>
<li>Default贴图
<ul>
<li>sRGBTexture是否启用gamma颜色通道</li>
<li>AlphaUsage透明通道使用哪个</li>
</ul>
</li>
<li>Normal map 法线贴图。<strong>法线是建模上垂直于每个点的法线，用高模生成法线贴图，在低模计算的时候应用法线贴图去计算材质和光照，减少性能消耗提高低模的表现效果</strong>
<ul>
<li>CreateFromGrayscale 从灰度高度贴图创建发现贴图</li>
<li>Bumpiness凹凸程度</li>
<li>Filtering如何计算凹凸值Smooth标准法线Sharp使用更锐利的法线贴图</li>
</ul>
</li>
<li><strong>精灵Sprite</strong>
<ul>
<li>SpriteMode: Single单张图 Multiple精灵图集
<ul>
<li>Sprite PixelsToUnits场景中1m对应多少个像素默认100，UI自适应可能使用这东西进行计算</li>
<li>Sprite MeshType网格模式，FullRect会生成一个覆盖此图片正方形，Tight基于像素的alpha值生成网格，多面片拼合形状；如果像素小于32x32会直接转换为FullRect。</li>
<li>Pivot 九宫格轴心点，Single模式才有也可自定义</li>
<li>Sprite GenerateFallbackPhysicsShape 根据精灵轮廓生成物理形状</li>
</ul>
</li>
</ul>
</li>
<li>其他一时半会用不到
<ul>
<li>EditorGUIandLegacyGUI编辑器和IMGUI用的</li>
<li>Cursor给自定义鼠标用的素材</li>
<li>Cookie光源剪影
<ul>
<li>Light Type <strong>Spotlight</strong>: 聚光灯类型，需要边缘纯黑色纹理。<strong>Directional</strong>: 方向光，平铺纹理。<strong>Point</strong>: 点光源，需要设置为立方体形状。</li>
</ul>
</li>
<li>Lightmap光照贴图</li>
<li>SingleChannel单通道格式</li>
</ul>
</li>
<li>高级设置
<ul>
<li>如果纹理尺寸非2的幂如何处理
<ul>
<li><strong>None</strong>: 不管</li>
<li><strong>To nearest</strong>: 整体缩放到最接近2的幂的大小（注：PVRTC格式要求纹理为正方形）</li>
<li><strong>To larger</strong>: 按照最大边尺寸缩放</li>
<li><strong>To smaller</strong>: 按照最小边尺寸缩放</li>
</ul>
</li>
<li>Read/Write会往内存中额外存如一些信息以便使用代码更改</li>
<li>WarpMode材质贴图铺在此物体上的模式
<ul>
<li><strong>Repeat</strong>: 在区块中重复纹理</li>
<li><strong>Clamp</strong>: 拉伸纹理的边缘</li>
<li><strong>Mirror</strong>: 在每个整数边界上镜像纹理以创建重复图案</li>
<li><strong>Mirror Once</strong>: 镜像纹理一次，然后将拉伸边缘纹理</li>
<li><strong>Per-axis</strong>: 单独控制如何在U轴和V轴上包裹纹理</li>
</ul>
</li>
<li>Filter Mode 纹理在通过3D变化拉伸时如何进行过度
<ul>
<li><strong>Point</strong>: 块状马赛克</li>
<li><strong>Bilinear</strong>: 模糊</li>
<li><strong>Trilinear</strong>: 与Bilinear类似，但纹理也在不同的Mip级别之间模糊</li>
</ul>
</li>
</ul>
</li>
<li><strong>Mipmap</strong>在右下角可以拖动预览层级
<ul>
<li>StreamingMipmaps 使用串流使用计算性能换内存消耗</li>
</ul>
</li>
</ol>
<div class="info custom-block"><p class="custom-block-title">[📝Note] Mipmap技术</p>
<p>ipmap技术
在3D场景中，如果镜头离材质贴图很远，那么材质的像素就会被压缩采样，比如四个像素采样一个。这样会采样不足渲染失真，远景出现锯齿摩尔纹和运动噪点。<br/>
Mipmap技术就是预先从原分辨率材质生成不同层级大小的材质最小为1*1然后根据摄像机远近应用不同层级采样解决这个问题。<br/>
Mipmap的纹理比原始纹理小很多，更容易被GPU的纹理缓存容纳，可以提高缓存命中率，但是总显存占用率大约+33%<br/>
2D和UI一般不启用，3D项目显存不是特别紧张最好是开，没用到的地方就别打开。Mipmap的选择模式Bilinear选择最相邻的一个层级 和 Trilinear选择最相邻的两个层级进行插值采样</p>
</div>
<p><strong>TextureShape</strong> 纹理形状，Cube用于天空盒和反射探针，Mapping是如何将纹理投影到游戏对象上，进阶的时候在天空盒会讲
<strong>纹理平台设置</strong> 很重要，和性能相关</p>
<ul>
<li>最大纹理尺寸即便原图很大打包也会压到这个尺寸，一般2048</li>
<li>ResizeAlgorithm 当纹理大于最大尺寸使用什么算法压缩
<ul>
<li>Mitchell米歇尔算法：默认使用的算法，常用于尺寸缩小</li>
<li>Bilinear双线性插值 ：使用双线性插值来调整图像大小。对于细节很重要的图片，推荐使用此方法能保留更多的细节信息</li>
</ul>
</li>
<li>不同平台支持的<a href="https://docs.unity3d.com/cn/2022.3/Manual/class-TextureImporterOverride.html" target="_blank" rel="noreferrer">Unity材质格式</a>看一遍有印象
<ul>
<li>IOS默认使用PVRTC获得更大的兼容性，如果已经不包含OpenGL ES2的支持，可以选择ASTC比前面全方位好一些</li>
<li>安卓标准不统一，一般根据不同的设备制作多个不同的安装包，省事就ETC，追求一点性能就ETC2</li>
</ul>
<ol>
<li>构建一个以 OpenGL ES 3 为目标的 APK: 访问 Android 的 Player Settings (Edit -&gt; Project Settings -&gt; Player Settings, 然后选择 Android 类别) -&gt; 向下滚动到 Graphics APIs 部分 -&gt; 确保 OpenGL ES 2 不在列表中 -&gt; 构建 APK (File -&gt; Build Settings, 然后单击 Build)。</li>
<li>构建一个以 OpenGL ES 2 为目标的单独 APK: 访问 Android Player Settings -&gt; 向下滚动到 Graphics APIs 部分 -&gt; 在列表中添加 OpenGL ES 2 并删除 OpenGL ES 3 和 Vulkan -&gt; 构建 APK。</li>
</ol>
<ul>
<li>压缩<strong>Compression</strong>和使用压缩算法<strong>Use Crunch Compression</strong>打包慢解压快</li>
<li><strong>Split Alpha Channel</strong>节约内存会把一张图分成两张纹理，一张包含RGB数据另一张包含Alpha数据在渲染时再合并渲染</li>
<li><strong>Override ETC2 fallback</strong>不支持ETC2的时候回滚格式</li>
</ul>
</li>
</ul>
<h4 id="spriteeditor" tabindex="-1">SpriteEditor <a class="header-anchor" href="#spriteeditor" aria-label="Permalink to &quot;SpriteEditor&quot;">&ZeroWidthSpace;</a></h4>
<p>在Window-&gt;PackageManager-&gt;2D Sprite安上才能用，还不能用看看自己预设是不是选成了3D项目</p>
<ul>
<li>注意<strong>Border</strong>和<strong>Pivot</strong>设置边框和中心点</li>
<li>CustomOutline自定义边缘线，此边缘线外的会不渲染，节省性能</li>
<li>CustomPhysicsShape自定义Collider的形状</li>
<li>SecondaryTextures附加其他材质以供代码调用
使用Multiple模式可以切割图集</li>
<li>Slice Type就是怎么切片，就Automatic用的最多</li>
<li>Trim自动修剪透明区域</li>
<li><strong>Pivot</strong>规定的点会规定切出来之后每个图的中心点</li>
<li><strong>Method</strong>如果有手动切的应该怎么处理</li>
</ul>
<h4 id="spriterenderer" tabindex="-1">SpriteRenderer <a class="header-anchor" href="#spriterenderer" aria-label="Permalink to &quot;SpriteRenderer&quot;">&ZeroWidthSpace;</a></h4>
<p>SpriteRenderer是可以挂载Sprite的组件。</p>
<ul>
<li>SortingLayers相当于PS中层的概念，每个Object属于哪个层，最下面的从层最靠前</li>
<li>Order in Layer在层中的优先级</li>
<li>DrawMode
<ul>
<li>Simple模式就整体缩放</li>
<li>Sliced 使用九宫格切分素材必须保证Sprite的<strong>MeshType: FullReact</strong></li>
<li>Tiled平铺模式
<ul>
<li>TileMode 平铺的时候是平铺拉伸还是超过阈值就增加一层</li>
</ul>
</li>
<li>MaskInteraction 遮罩交互</li>
<li>Sprite-Default默认的精灵材质不会受到光照影响</li>
</ul>
</li>
</ul>
<details class="details custom-block"><summary>Sprite组件基本API</summary>
<p>prite组件基本API</p>
<div class="language-Csharp vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">Csharp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> SpriteTest</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> : </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">MonoBehaviour</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    // 挂在Sprite对象上的组件  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    private</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> SpriteRenderer</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> spriteRenderer</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  声明一个spriteRenderer  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Sprite</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> sprite</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  声明一个Sprite对象  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Start</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {        </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        spriteRenderer </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> gameObject.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetComponent</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">SpriteRenderer</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>();  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  获得本Sprite的Renderer  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        spriteRenderer.sprite </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> sprite;   </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  可以替换掉  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        spriteRenderer.color </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Color.cyan;  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  其他属性参考着吗面板改  </span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        //动态加载图集</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Sprite[] </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> sprs </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Resources.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">LoadAll</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Sprite</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"RobotBoyIdleSprite"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//这里是图集的名字，从数组里取对应的Sprite</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br></div></div></details>
<p>可以直接Create-&gt;Sprite-&gt;形状，还没出美术素材作为替代资源，等出了之后换上就行了。<br>
Create-&gt;SpriteMask可以创建遮罩，注意遮罩对象的CustomRange属性，只有在这个层级内遮罩才能起效，新加Layer是下方Layer的0-N，新Layer的0-Front</p>
<p>使用<strong>SortingGroup</strong>组件可以整体的加一个排序分组，比SpriteRender的AdditionalSettings-&gt;SortingLayer优先级还要高。子对象的<strong>SortingGroup</strong>只会在同级别发作用，对上层的无效，而且是<strong>优先于Z轴发挥作用的</strong>。<br>
如果这个组件被放进了Prefabs中，拖出来的时候为了避免有同样值的SortingGroups冲突最好修改一下。</p>
<h4 id="spriteatlas图集" tabindex="-1">SpriteAtlas图集 <a class="header-anchor" href="#spriteatlas图集" aria-label="Permalink to &quot;SpriteAtlas图集&quot;">&ZeroWidthSpace;</a></h4>
<p>打图集将多个纹理texture合并成一个大纹理，当访问图集中的多个纹理时，也只需要调用一次DrawCall， 默认是不会打图集的。在Edit-&gt;ProjectSettings-&gt;Editor-&gt;SpritePacker中打开<br>
选择<code>Sprite Atlas V2 - AlwaysEnabled</code>,右键在资源文件夹中Create-&gt;2D-&gt;Sprite Atlas，一般会通过代码动态加载它</p>
<blockquote>
<p>Sprite Atlas V1 不支持缓存服务器（Cache Server），Unity只能将打包的图集数据存储在<code>Library/AtlasCache</code>文件夹中，并且也不能有依赖项，不支持命名对象导入器（named objects importer），而Sprite Atlas V2提供了对上述功能的支持。具体可以参考 <a href="https://docs.unity.cn/Manual/SpriteAtlasExperimental.html" target="_blank" rel="noreferrer">Unity Manual：Sprite Atlas Version 2</a></p>
</blockquote>
<p>主图集（Master）</p>
<ul>
<li><strong>Include in Build</strong>：在当前构建中包含其他图集</li>
<li><strong>Allow Rotation</strong>：在打包图集时允许图片元素旋转，可提高图集密度； <mark>注意 如果是UI图集，请禁用此选项，因为打包时会将场景中UI元素旋转</mark> ！！！</li>
<li><strong>Tight Packing</strong>：使用图片轮廓来打包而不是放到矩形中再排列，可提高图集密度</li>
<li><strong>Padding</strong>：图集中各图片的间隔像素
变体类型的图集（Variant）</li>
<li><strong>Master Atlas</strong>：关联的主图集（图集类型必须是Master）</li>
<li><strong>Scale</strong>：设置变体图集的缩放因子（0~1），变体图集的大小是主图集乘以Scale的结果，差不多就是对图集缩放。</li>
</ul>
<p>把Texture或者包含Texture的文件夹拖进来就可以放进图集就行。如果发现没有PackPreview按钮，说明忘了打开允许图集。<br>
直接使用Texture的时候，他会自动使用图集的，在 <strong>Game窗口-&gt;Stats(Statistics)-&gt;Batches</strong>就是DrawCall的数量看看有没有变，<strong>注意只有运行的时候才会变化</strong><br>
注意 <mark>如果一个图集的两个Texture中间有其他SortingLayer的Texture，此时图集会触发两次Drawcall，拼UI尤其注意</mark> ！</p>
<div class="language-Csharp vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">Csharp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">SpriteAtlas</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> spriteAtlas</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Resources.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Load</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">SpriteAtlas</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"MyAtlas"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 和加载普通资源一样</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">sr.sprite </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> spriteAtlas.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetSprite</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"sprite1"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br></div></div><p><strong>图集的尺寸最佳实践</strong><br>
如果 Sprite Atlas 设置的最大尺寸为 2048x2048，而所有 Sprite 加在一起超过了这个尺寸，Unity 会自动拆分成多个图集纹理（Texture），所以此时Drawcall也是两次。Sprite Atlas → Inspector → 下方可以看到 “Objects Preview”有没有被拆分
注意不同平台（Android/iOS）支持的最大纹理尺寸略有不同。旧设备普遍不支持大于 2048。</p>
<h4 id="spriteshape" tabindex="-1">SpriteShape <a class="header-anchor" href="#spriteshape" aria-label="Permalink to &quot;SpriteShape&quot;">&ZeroWidthSpace;</a></h4>
<p>同样需要在Window-&gt;PackageManager中安装才能使用,主要用来拼接2D游戏中不规则的地形的<br>
<strong>SpriteShapeProfile</strong><br>
安装完此时右键在Assets右键Create-&gt;Sprite（创建SpriteShapeProfile）每个版本貌似路径还不太一样只要创建出这个文件就可以。<br>
新版本的close和open的版本合并了，close的是封闭的一个圈可以使用很多;open就可以随便加折线编辑使用的是一个Texture。可以在圆圈上设置角度，然后点过去就可以设置这个角度区间的材质了</p>
<ul>
<li>UseSpriteBorders勾选这个东西之后它会使用九宫格拉伸的效果，默认选就行。</li>
<li>Texture只有是repeat模式才能用于填充；Offset调整的是填充的时候偏移的角度；中间编辑的是角度区间使用的Sprite可以放多个然后用的时候选其中一个；角度边上的order是折角处相交显示优先级</li>
<li>下面的8个角的素材是这东西折叠起来的时候角上会用哪Texture</li>
</ul>
<p><strong>SpriteShapeController</strong>参数几乎一看就会<br>
<strong>SpriteShapeRenderer</strong></p>
<ul>
<li>Detail使用Sprite的质量</li>
<li>CornerThreshold超过此角阈值才会使用角上的材质</li>
<li>AdaptiveUV 自动判断纹理是平铺还是拉伸，宽度足够时会平铺不够时会拉伸，不开启则始终平铺但可能会出现裁剪效果</li>
<li>Fill里面的参数PixelPerUnit（需要先禁用拉伸UV）像素/米比例尺，平铺密度</li>
</ul>
<p>为这东西添加碰撞器有两种<br>
边界碰撞器EdgeCollider2D会直接顺着中轴线添加碰撞器<br>
多边形碰撞器PolygonCollider2D+复合碰撞器CompositeCollider2D，然后PolygonCollider2D-&gt;UseByComposite形成类似边界碰撞器的效果，多边形碰撞器必须使用Rigidbody，如果想让它不动就得选择成Static有检测碰撞限制</p>
<h4 id="tilemap瓦片地图" tabindex="-1">TileMap瓦片地图 <a class="header-anchor" href="#tilemap瓦片地图" aria-label="Permalink to &quot;TileMap瓦片地图&quot;">&ZeroWidthSpace;</a></h4>
<p>需要在Window-&gt;PackageManager中安装<strong>2DTileMapEditor</strong>才能使用，也是用来创建2D地图。关键的是两个文件，一个是Tile.asstes文件和TilePalette预制体，点击预制体能打开TilePalette编辑器。<br>
安装完后在 Asset-&gt;Create-&gt;2D-&gt;TilePalette 选择一个类型 或 Window-&gt;2D-&gt;TilePalette打开窗口，这样我们就创建了一个新的<strong>瓦片调色盘TilePalette</strong>，把这东西拖进场景中，再把Sprite拖进调色盘就创建了瓦片</p>
<div class="info custom-block"><p class="custom-block-title">[📝Note] 和SpriteShape差异</p>
<p>SpriteShape差异
SpriteShape可以让地形具有弧度，适合制作曲线圆形等不规则形状的地图元素。<br/>
TileMap更适合由方块组成的平铺地图，可以通过层叠不同图层来快捷地制作有伪“Z”轴效果的地图，即模拟出三维空间的效果。<br/>
这一节更接近美术，在untiy中看着弄比较好。</p>
</div>
<p>创建TilePalette的时候，注意几个参数</p>
<ul>
<li>Grid网格布局，Rectangle方形地形(横版游戏)；Hexagon六边形(可以选点朝上还是横线朝上,策略类游戏)；Isometric等距瓦片(有“Z”轴效果的2D游戏)；IsometricZAsY 转换Z轴为Y轴的等距瓦片（适用于不同类型的游戏，看一眼就大致明白了</li>
<li>CellSize格子大小</li>
</ul>
<p>滚轮中键 或 alt+左键 平移视角，放大缩小单选多选就不多说了，瓦片编辑器和PS一样，美术相关的不多说（就是魔兽地图编辑器一样的，都可以编辑。<br>
调色盘的正确用法是，把TilePalette当调色盘用，把所有可能用到的瓦片拖进来一份，在Scene中Create-&gt;2D-&gt;Tilemap-&gt;选一个 就创建了一个Grid，然后用笔刷工具吸取自己想要的色块绘制Grid。<br>
<strong>等距ZasY瓦片地图</strong>的排列是按照Sprite的轴心点定位的，有些素材不是中心贴合的。<strong>在等距瓦片Grid中默认是按照Z轴排序的</strong>，在ProjectSetting-&gt;Graphics-&gt;TransparencySortMode: Custom-&gt;TransparencySortAxis: <strong>(X,Y,Z)=(0,1,-0.26)</strong>，设置Grid对象的TileMap中设置TileMap的Mode为Individual，然后高低差就正常了。在TilePalette的Brush中勾掉<strong>LockZPosition</strong>就可以使用 <code>- +</code> 键调整地形的高度，他使用Y轴模拟了高度。</p>
<p><strong>Grid组件</strong>是网格的基本组件，参数一看就懂，注意网格大小&lt;-&gt;Sprite PixelPerUnite对应，调整格子和Sprite的填充。<br>
<strong>TileMapRenderer组件</strong>，SortOrder设置所选瓦片地图上的瓦片排序方向，带Z轴模拟的一般左上角，其他一般默认右下角就行；Mode渲染模式，chunk按位置分组批处理渲染瓦片，Individual单独渲染每个瓦片，带位置和排序顺序</p>
<p>选择需要添加Collider的TileMap层，然后添加TileMapCollider2D然后自动根据有Sprite的格子生成了Collider，注意格子生成瓦片使用的Collider格式。</p>
<p>轴心点排序: 参与等距网格的角色一般把Sprite的中心点设置为脚下(0.5X,Y)，地图上的Sprite的SpriteSortPoint需要设为Pivot，轴心点排序，Sprite的轴心点如果在指定地图轴心点Y轴的上方那就会显示在前面。这样就会影响轴心点画地图不太推荐<br>
排序层排序: 可以创建多个等距瓦片地形，给不同的OrderInLayer，形成植被景观等效果分层，但是不同层不会产生遮挡，1.这时候可以再创建一个层，比玩家层高绘制的东西就可以挡在玩家前面；2.如果是植物这种，把它和玩家放一个层都设置好轴心点排序，控制轴心点</p>
<p>一般在这种2D游戏中，不会使用重力和Rigidbody控制移动，而是使用Transform。伪Z轴碰撞的话，地形瓦片Sprite是不使用碰撞的， 墙体瓦片Sprite使用Gride碰撞，会约束玩家在格子里。如果碰撞在本层网格上看起来靠不到边，那就再在外面叠一层让它和外面的进行碰撞。<br>
2.5D的跳跃动画可以创建一个空父物体，跳跃的时候让人物子物体在Y轴动。</p>
<h4 id="tilemap拓展包" tabindex="-1">TileMap拓展包 <a class="header-anchor" href="#tilemap拓展包" aria-label="Permalink to &quot;TileMap拓展包&quot;">&ZeroWidthSpace;</a></h4>
<p>旧版本去<a href="https://github.com/Unity-Technologies/2d-extras" target="_blank" rel="noreferrer">github下载对应版本</a>，然后拖进Assets导入；2020之后的版本直接在Window-&gt;PackageManager中安装<br>
感觉这东西一时半会用不到，而且好多年没更新了，进行一个挖坑然后有空了再补TIleMap Extra</p>
<details class="details custom-block"><summary>代码控制Tile</summary>
<p>码控制Tile</p>
<div class="language-Csharp vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">Csharp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Tilemap</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> map</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  瓦片地图  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Grid</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> grid</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 布局，可以有多层瓦片  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> TileBase</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> tile</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  瓦片  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> TileBase</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> new_tile</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Start</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    map.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">ClearAllTiles</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 直接清图  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    TileBase</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> tile</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> map.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetTile</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Vector3Int</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  获得这个map坐标上的Tile  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    map.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">SetTile</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Vector3Int</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">), tile); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 把指定位置替换成这个瓦片，SetTiles可以设置多个，清理格子可以用null  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    map.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">SwapTile</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(tile,new_tile); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 把地上所有的 tile类型 替换成 new_tile类型  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    grid.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">WorldToCell</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(Vector3.zero); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 把指定的世界坐标转换为指定的格子的坐标  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br></div></div></details>
<h3 id="_2d-collider和rigidbody" tabindex="-1">2D Collider和Rigidbody <a class="header-anchor" href="#_2d-collider和rigidbody" aria-label="Permalink to &quot;2D Collider和Rigidbody&quot;">&ZeroWidthSpace;</a></h3>
<p>先看一下参数，重点记和3D不同的参数。<br>
前提条件和3D的碰撞体刚体一样，必须两者都有Collider至少一个有Rigidbody，2D的碰撞器在检测碰撞的时候只计算XY轴忽略Z轴。<br>
2D Collider和Rigidbody都能设置物理材质，物理材质<strong>应用优先级是 2D Collider指定的材质&gt;2D Rigidbody指定的材质&gt;Physics2D窗口指定的物理材质&gt;Unity默认的值</strong>。子物体如果没有设置材质，则会<strong>继承父物体Rigidbody指定的材质</strong>。<br>
在ProjectSettings-&gt;Physics2D可以指定全局2D物理材质，一般的实践都是在Collider上指定，有一些子物体需要的时候才用Rigidbody指定</p>
<ul>
<li>Simulate默认选上否则会不使用物理系统。AutoMess就是自动计算质量，可能根据体积？一般是自己指定他算的不准。</li>
<li>LinearDrag和AngularDrag，GravityScale就是 位移阻力系数 和 旋转阻力系数，重力系数，跟3D里面一样</li>
<li>SleepingMode睡眠模式：StartAwake移动时唤醒(经常移动的单位)，Start Asleep碰撞时唤醒（静止的单位）</li>
</ul>
<p>Dyanmic（常规运动和碰撞的对象<br>
Static（不动不受力但是需要碰撞检测的对象，碰撞器和所有的其他碰撞器检测，但它只能和Dyanmic刚体进行碰撞检测<br>
<strong>Kinematic运动学类型</strong> （通过API移动不受力的作用但是要进行碰撞检测</p>
<ul>
<li><strong>不受力的影响</strong>，只能通过代码让其动起来。</li>
<li>能和Dynamic 2D刚体产生碰撞，但是不会动，只会进入碰撞检测函数。</li>
<li>因此它没有了质量、摩擦系数等属性。</li>
<li>性能消耗较低，主要会通过代码来处理其移动旋转。</li>
</ul>
<ol>
<li>Simulated
<ul>
<li>如果希望2D刚体以及所有子对象2D碰撞器和2D关节都能模拟物理效果，需要启用该选项。</li>
<li>当启用时，会充当一个无限质量的不可移动对象，可以和所有2D刚体产生碰撞。</li>
<li>如果Use Full Kinematic Contacts禁用，它只会和Dynamic 2D刚体碰撞。</li>
</ul>
</li>
<li>Use Full Kinematic Contacts
<ul>
<li>如果希望能和所有2D刚体碰撞，启用它。</li>
<li>如果不启用，它不会和Kinematic 2D和Static 2D刚体碰撞。</li>
</ul>
</li>
</ol>
<p>自带的碰撞器，粗糙点的，人物一般用胶囊碰撞器。<br>
再就是边界碰撞器可以自己编辑；复合碰撞器会统合子对象所有的碰撞器作为统一的碰撞检测，复合碰撞器一定是要配合刚体使用，GeometryType可以规定碰撞器是不是实心的。<br>
物理材质和3D中的材质参数一样，摩擦力和弹力系数，计算的时候是两个物体的材质系数一块计算的<br>
Constant Force组件可以添加恒定力，效果类似于每帧AddForce，但是应用场景上不太一样。</p>
<h4 id="效应器" tabindex="-1">效应器 <a class="header-anchor" href="#效应器" aria-label="Permalink to &quot;效应器&quot;">&ZeroWidthSpace;</a></h4>
<p>首先需要在Collider中开启UsedByEffector并且勾选Trigger才能使用效应器</p>
<ul>
<li>AreaEffector2D 区域效应器 对此区域不断施加<strong>力和扭矩力</strong>，参数大部分一看就懂，注意UseGlobalAngle是否使用世界坐标；ForceTarget是按照 <strong>碰撞器中心</strong> 还是按照 <strong>刚体质心</strong>，<strong>按照刚体的话不会产生旋转力</strong>（下同；关闭是否启用碰撞器遮罩就会施加到所有层。</li>
<li>BouyancyEffector2D 福利效应器 SurfaceLevel 是浮力的面在哪里，在线的下面会受到力的作用达到平衡。三个参数分别是 流体<strong>角度</strong> 流体<strong>速度</strong> 和 流体<strong>速度的波动范围</strong></li>
<li>PointEffector2D 点效应器 ForceMode：<strong>Constant</strong> 忽略距离施加力大小固定；<strong>Inverse Linear</strong>力的大小与距离成线性反比；<strong>Inverse Squared</strong> 模拟现实世界中的重力效果，力的大小与距离的平方成反比</li>
<li>PlatformEffector2D 平台效应器 作用是让区域成为可以从下面跳上去但是上面能接住的平台(可以不使用Trigger
<ul>
<li>UseOneWay是是否使用上半部分作为单向碰撞器</li>
<li>UseOneWayGrouping如果有多个碰撞器勾选后会把所有的碰撞器都设置为单向碰撞器</li>
<li>SurfaceArc包含的角度会被视为平台跳不上去</li>
<li><strong>UseSideFriction; UseSideBounce; SideArc</strong> 这三个规定的是两个侧边的面积角度，摩擦力和弹力（就是边上能扒住</li>
</ul>
</li>
<li>SurfaceEffector2D表面效应器(可以不使用Trigger
<ul>
<li>Speed速度 SpeedVariation速度波动范围</li>
<li>ForceScale 控制了沿表面移动时施加的力的系数。建议不要将其设置为1，因为这样可能会抵消其他作用在物体上的力</li>
<li>UseContactForce是否在接触点的表面施加力，而不是在质心（可能导致旋转和倒伏</li>
</ul>
</li>
</ul>
<div class="warning custom-block"><p class="custom-block-title">[⚠️Warning] 效应器的局限性</p>
<p>应器的局限性
效应器其实也是写好代码的组件，本质还是施加力，如果功能有限不符合项目要求不要犹豫，自己写</p>
</div>
<h3 id="_2d动画" tabindex="-1">2D动画 <a class="header-anchor" href="#_2d动画" aria-label="Permalink to &quot;2D动画&quot;">&ZeroWidthSpace;</a></h3>
<p>原理是固定时间间隔在一个Sprite数组中切换当前Sprite，就可以达到2D帧动画的效果。正常创建是把序列Sprite创建到Anime中，可以修改此anime的Inspector-&gt;Debug可以修改动画的帧率，<strong>记得如果修改帧率一定要把原先的动画帧删除再拖新的进去，否则可能会出现丢帧问题</strong>。创建的帧动画可以直接在状态机中使用。<br>
其实这个anime的原理也是固定切换Sprite，它默认只能驱动SpriteRenderer,但是你可以把动画挂到UI的Image上然后在关键帧里直接更改属性拖进序列去就可以驱动UI播放帧动画。</p>
<h4 id="_2d骨骼动画" tabindex="-1">2D骨骼动画 <a class="header-anchor" href="#_2d骨骼动画" aria-label="Permalink to &quot;2D骨骼动画&quot;">&ZeroWidthSpace;</a></h4>
<p>利用3D美术骨骼的原理进行制作，为每个部位绑骨骼，性能换内存节省资源。2018后用的方案是2D Animation，先在PackageManager安装。<br>
在SpriteEditor-&gt;SkinningEditor编辑骨骼。编辑器中双击选中图片，PreviewPose不会真正影响骨骼，可以预览。 骨骼可以从根部创建，父骨骼动会带动子骨骼。<br>
绑完<strong>骨骼</strong>就进行Geometry蒙皮，一般是先自动生成再手动调整细节，蒙皮的点越多越占用性能，也会越精细。<br>
调整完<strong>蒙皮</strong>下一步是设置权重，蒙皮自动生成的时候自动会产生<strong>权重</strong>，即受骨骼影响大小<br>
注意这几个参数</p>
<ul>
<li>Outline Detail（边缘细节）值越大，模型的轮廓就越细致。它影响模型边缘的清晰度和精细程度</li>
<li>Alpha Tolerance（阿尔法公差值）控制蒙皮细节，通过调整它可以优化模型表面的透明度处理，确保在半透明或有复杂纹理区域的平滑过渡</li>
</ul>
<p>最后给Scene中的Sprite添加SpriteSkin组件，生成一下骨骼就可以在动画中使用它了，图集的骨骼编辑好导入之后，先建立一个空的父对象，挂Sprite子对象，可以直接场景上编辑父子关系，2D对象一般把中心位置放在脚下。</p>
<p>psb文件和psd都是PS的原生文件格式，unity中推荐使用psb格式导入ps的素材需要先安装Window-&gt;PackageManager-&gt;2DPSDImporter<br>
一般来说ImportHiddenLayers不勾选，隐藏图层美术留着不导入的；UseLayerGroup一般也不勾选<br>
ImportMode默认Individual Sprites (Mosaic)每个图层会被当作独立的 Sprite 导入，MosaicPadding一般设置1-8不要设置0，在将多个图层合成一张 Mosaic 贴图时，它们之间的间隔像素数，防止图集边缘出现“图像溢出”或采样错误（通常在缩放、模糊、移动时容易出现）</p>
<p><strong>反向动力学IK</strong>（Inverse Kinematics）正向动力学FK（Forward Kinematics）正向动力学就是父骨骼带动子骨骼摆动，2022.2后IK已经包含在2DAnimation里面<br>
添加IK Solvers的模式三种 <strong>Chain (CCD)</strong> 可以自定义影响N个关节点，但不能反向；<strong>Chain (FABRIK)</strong> 同样可以自定义影响N个关节点，但与CCD不同的是，它可以反向计算；<strong>Limb</strong> 只会影响3个关节点。<br>
为Sprite添加一个空的父对象，在这个父对象上挂载<strong>IK Manager2D</strong>组件，添加Solver，此时会在此父对象下生成一个Solver对象；在每个想要被IK控制的骨骼末端位置放置一个子对象。把末端的物体拖到生成的Solver的Effector上，生成的新对象就会牵引着骨骼动。<br>
CCD模式不能直接180度往上拉，FABRIK可以。Limb一般给四肢用，位置不对可以Flip反向，使用此IK的时候，只改变身体的骨骼保持IK的点不动，可以方便的制作idel动画。使用IK点可以使动态动画瞄准某个地方或者动态的生成拾取等动画。</p>
<p>2D换装的实现，在psb中把对应位置的装备都做好，然后都隐藏，需要哪个显示哪个。在SpriteEditor-&gt;SkinngEditor-&gt;Visibility-&gt;Sprite中可以给同部位的装备打Category，一般设置同部位Category相同。<br>
此时场景的psb的对象下<strong>SpriteLibrary</strong>关联了<strong>SpriteLibraryAssets</strong>记录类别分组信息，在对应要换装部位的物体上自动挂载<strong>SpriteResolver</strong>组件选择使用什么装备，换装会自动依赖骨骼。</p>
<details class="details custom-block"><summary>2DSprite换装的API</summary>
<p>DSprite换装的API</p>
<div class="language-Csharp vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">Csharp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> TestSpriteResolver</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> : </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">MonoBehaviour</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> SpriteResolver</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> sr</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    private</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Dictionary</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">string</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">SpriteResolver</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">> </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">equipDict</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Dictionary</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">string</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">SpriteResolver</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>();</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Start</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        SpriteResolver</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[] </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">srs</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> this</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetComponentsInChildren</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">SpriteResolver</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>(); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 递归查找所有部位的SpriteResolver</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">int</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> i</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x3C;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> srs.Length; i</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">++</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            equipDict.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Add</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(srs[i].</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetCategory</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(), srs[i]); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 存储当前的 类别名:SpriteResolver组件</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        }</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        ChangeEquipment</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Cask"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"CASK 1"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  把CASK部位切换成CASK 1</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> ChangeEquipment</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">string</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> category</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">string</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> item</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 封装一下</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (equipDict.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">ContainsKey</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(category))</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            equipDict[category].</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">SetCategoryAndLabel</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(category,item);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br></div></div></details>
<p>图片都在一个psb下的时候，图集会很大，所以大的时候需要在不同psb中制作换装。在制作psb的时候，制作多套psb隐藏某些图层，某一套只保留本体，其他的多套只保留装备，换一套叠加就换了一套装备。<br>
注意 <mark>不同文件的骨骼信息必须统一，所以直接复制骨骼到各个套装</mark> PreviewPose选中需要复制的骨骼，然后CopyRig，不要关掉窗口选择新的psb PasteRig。就复制过去了。<br>
手动创建SpriteLibraryAssets，编辑Inspector；给根对象添加SpriteLibrary组件，关联SpriteLibraryAssets文件；在想要换装的部位添加SpriteResolver，然后就可以看到换装类别了。代码上面的就能重复使用了。<br>
当换装的内容特别多的时候，放一起图集会越来越大，有些移动设备不支持太大图集。</p>
<blockquote>
<p>这一节的东西基本都是美术类的直接去Unity中摸的多了就会了，记的东西不多</p>
</blockquote>
<h4 id="spine动画" tabindex="-1">Spine动画 <a class="header-anchor" href="#spine动画" aria-label="Permalink to &quot;Spine动画&quot;">&ZeroWidthSpace;</a></h4>
<p>收费跨平台主流2D动画方案，三个主流引擎都支持，<a href="https://zh.esotericsoftware.com/" target="_blank" rel="noreferrer">官网在这</a>。程序会用就行，不用制作。下载安装导入不多bb，动画都是用Spine制作完之后导出，然后扔到引擎中使用。<br>
Spine导出的资源文件夹下（官网建议使用二进制导出因为性能更好）</p>
<ul>
<li><code>.json</code> 文件：骨骼结构动画数据等</li>
<li><code>.png</code> 文件：使用的图集</li>
<li><code>.atlas.txt</code> 图片在图集中的位置信息，定位和提取具体的贴图<br>
拖入入Unity Assets后的自动生成:（确认引入了Spine运行库</li>
<li><code>_Atlas</code> 文件是材质和.atlas.txt文件的引用配置文件，用于管理图集资源</li>
<li><code>_Material</code> 材质文件</li>
<li><code>_SkeletonData</code> 骨骼动画文件，关联了.json文件和_Atlas资源。
最重要的是<code>_SkeletonData</code>文件，拖到场景中就可以创建。注意<code>_SkeletonData</code>的参数:</li>
<li>SkeletonDataJSON绑定的骨骼</li>
<li>scale缩放比例默认0.01</li>
<li>MixSettings可以设置动画之间的过渡时间和指定动画的过渡</li>
<li>Slots相当于Spine动画的图层</li>
<li>SkeletonMecanim生成新动画系统状态机，状态机展开就有AnimationClip用了
<code>_SkeletonData</code>创建的选项，第一种是挂载SkeletonAnimation组件，第二是挂载SkeletonMecanim+Animator使用状态机控制。</li>
</ul>
<details class="details custom-block"><summary>SkeletonAnimation的代码控制动画提供了额外的API</summary>
<p>keletonAnimation的代码控制动画提供了额外的API</p>
<div class="language-Csharp vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">Csharp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> SpineTest</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> : </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">MonoBehaviour</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    private</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> SkeletonAnimation</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> sa</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    [</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">SpineAnimation</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">] </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 标明下面的属性是存储动画的，在这Editor里指定  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> string</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> JumpAnimation</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    // 与上面同理  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    [</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">SpineBone</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">] </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 骨骼  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> string</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> boneName</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    [</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">SpineSlot</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">] </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 插槽  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> string</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> slotName</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    [</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">SpineAttachment</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">] </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 附件  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> string</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> attachName</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Start</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {        sa </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> GetComponent</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">SkeletonAnimation</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>();  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        sa.loop </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 需要先停止动画循环  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        sa.AnimationName </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "jump"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  再进行动画绑定  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        // trackIndex 默认一般0就可以，也不知道为啥  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        sa.AnimationState.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">SetAnimation</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, JumpAnimation,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 不循环直接播放jump动画 和上面两句等效  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        sa.AnimationState.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">AddAnimation</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"jump"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  不循环 延迟0s 添加junp到播放队列  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        sa.skeleton.ScaleX </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> -</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// X轴反转  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        sa.AnimationState.Start </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">t</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        {  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            Debug.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"动画开始播放"</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">sa.AnimationName);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        };        sa.AnimationState.End </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">t</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        {  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            Debug.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"动画中断或清除"</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">sa.AnimationName);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        };        sa.AnimationState.Complete </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">t</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        {  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            Debug.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"动画播放完成"</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">sa.AnimationName);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        };        sa.AnimationState.Event </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">t</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">e</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        {   </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  此自定义事件 做动画的时候在Spine中定义的这里只用  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            Debug.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"触发自定义事件"</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">sa.AnimationName);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        };  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        Bone</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> b</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> sa.skeleton.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">FindBone</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(boneName); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  可以控制骨骼旋转，牵引IK等  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        sa.skeleton.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">SetAttachment</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(slotName,attachName);</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 设置插槽的附件，达成换装的效果  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        }  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br></div></div></details>
<p>拖进去的时候使用<code>SkeletoGraphic</code>就可以挂载UI的Canvas下在UI中使用了。</p>
<hr>
<h2 id="游戏管理" tabindex="-1">游戏管理 <a class="header-anchor" href="#游戏管理" aria-label="Permalink to &quot;游戏管理&quot;">&ZeroWidthSpace;</a></h2>
<h3 id="委托和事件" tabindex="-1">委托和事件 <a class="header-anchor" href="#委托和事件" aria-label="Permalink to &quot;委托和事件&quot;">&ZeroWidthSpace;</a></h3>
<p>#todo 这里以后要再学一学，C#中的委托和Unity中委托的异同点<br>
Unity 额外提供了 <code>UnityEvent</code>，它是 <code>System.Delegate</code> 的封装，主要用于与 Inspector（检查器）交互，支持<strong>序列化</strong>，可以在 Unity 编辑器中直接绑定回调  <strong>Unity 的事件生命周期管理</strong> Unity 提供了 <code>Start()</code>, <code>Update()</code>, <code>OnDestroy()</code> 等生命周期方法，而 C# 传统的委托需要手动管理生命周期。<strong>GC（垃圾回收）影响</strong> Unity 的 <code>UnityEvent</code> 是基于 <code>List&lt;Delegate&gt;</code> 而非 C# 的 <code>MulticastDelegate</code>，因此不会像 C# 事件那样造成隐式的 GC 压力（捕获 <code>this</code> 时的内存泄漏风险较低）</p>
<p>订阅GC，订阅泄露</p>
<div class="info custom-block"><p class="custom-block-title">[📝Note] 柯里化概念复习</p>
<p>里化概念复习
柯里化（Currying）是一种将接受多个参数的函数转换成接受一个单一参数的函数，并且返回接受余下参数的函数的技术。这种技术由逻辑学家Haskell Curry提出，因此得名柯里化。<br/>
假设有一个函数 f(a, b, c)，经过柯里化处理后，它会被转换成 f(a)(b)(c) 的形式。<br/>
反柯里化（Uncurrying）是柯里化的逆操作，它将嵌套的函数转换为一个接受多个参数的函数。反柯里化可以使得嵌套的单参数函数变得更易用，特别是在需要处理多个参数的情况下。<br/>
假设有一个柯里化函数 f(a)(b)(c)，经过反柯里化处理后，它会被转换成 f(a, b, c) 的形式。<br/></p>
</div>
<h3 id="线程和协程" tabindex="-1">线程和协程 <a class="header-anchor" href="#线程和协程" aria-label="Permalink to &quot;线程和协程&quot;">&ZeroWidthSpace;</a></h3>
<p>线程其实正常的起就可以，一般是会把密集的计算或异步IO，线程没法直接传递结果，一般会声明公共的缓冲区，由untiy周期函数尝试去拿，拿到了就是计算完了。<br>
启动一个协程函数（即带有 <code>IEnumerator</code> 返回类型的函数）， <mark>必须通过 <code>StartCoroutine</code> 直接调用只会执行方法中的同步部分</mark> ，而不会处理 <code>yield return</code> 语句或等待异步操作完成。<br>
<code>IEnumerator Start()</code> 可以自动转换为异步执行，其他的生命周期函数不可以<br>
其实就可以直接搞生产消费者那套了</p>
<div class="warning custom-block"><p class="custom-block-title">[⚠️Warning] 线程一定要注意</p>
<p>程一定要注意
<strong>千万别Join</strong>，Unity编辑器本质也是通过反射调用的C#，如果在生命周期里Join整个程序会卡住。<br/>
所以<strong>线程用完一定要关闭</strong>！！！否则线程就会一直开启直到进程关闭<br/>
<strong>子线程无法访问Unity主线程内容中的东西</strong></p>
</div>
<details class="details custom-block"><summary>简单多线程演示</summary>
<p>单多线程演示</p>
<div class="language-Csharp vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">Csharp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Start</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    Thread</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> t</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Thread</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> TestThread</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">());  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    t.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Start</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">private</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> TestThread</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    int</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> count</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    while</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {        </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        count </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Thread.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Sleep</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1000</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Debug.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">$"TestThread print {</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">count</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">}"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        this</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetComponent</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Collider</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>();</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 这里尝试访问住线程的对象报错了！  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br></div></div></details>
<p>也可以使用线程池，频繁创建删除线程时提高性能节约内存，但不能控制线程池中线程的执行顺序，也不能获取线程池内线程取消/异常/完成的通知<br>
Task是基于线程池的改进。 #todo 练习使用 C#多进程 Unity中和C#中的线程池 Task async和await 进阶课3C系列知识14-17集和自己补充
Unity中的<strong>协程</strong>通常在一段时间内执行某些任务或在帧之间分配工作，在Update()⽅法之后LateUpdate()⽅法之前调用协程通过 <code>IEnumerator</code> 接口和 <code>StartCoroutine</code> 方法来实现。</p>
<ul>
<li>返回值必须为<code>IEnumerator</code>接口类型，使用<code>yield return</code>。</li>
<li>是非阻塞的，适合需要在多个帧之间执行的任务。</li>
<li>依赖于Unity的更新循环，无法脱离Unity环境使用。</li>
<li>脚本 物体销毁，物体失活 协程不执行。脚本如果已经运行了协程然后再失活协程仍会执行。</li>
</ul>
<details class="details custom-block"><summary>协程测试</summary>
<p>程测试</p>
<div class="language-Csharp vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">Csharp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Start</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{        </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    Coroutine</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> cor</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">StartCoroutine</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">AsyncDemo</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">10</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 去执行一个协程  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    StopCoroutine</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(cor); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 结束此协程调用  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    StopAllCoroutines</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 停止掉此脚本此脚本此脚本协程池里面所有协程  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    // StartCoroutine(AsyncDemo(10));</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> // 也可以这样,但是这样不知道在哪里用了几次。</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    // 所以建议直接不要这样用，做一件事最好的方法有且仅有一个  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> IEnumerator</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> AsyncDemo</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">int</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> num</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  协程的固定返回类型  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    Debug.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"wait for return "</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    yield</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> return</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> WaitForSeconds</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">3f</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 3s之后返回，有很多不同的返回函数，用到再看  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    Debug.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"done return 1s"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    yield</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    Debug.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">$"done next return , out {</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">num</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">}"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    transform.position </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Vector3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">10</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">10</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">10</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 做一次位移  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    yield</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> AsyncDemo2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  协程是可以嵌套的  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> IEnumerator</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> AsyncDemo2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">() </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 利用协程做动画，以及协程嵌套，协程本质就是一个函数栈暂停，控制权移交  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    Debug.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"start async2"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    while</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {            </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        transform.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Rotate</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Vector3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">10</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">));  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  调整角度，配合协程达到旋转的效果，不过这个旋转不是平滑的  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        // 这里可以用while true执行</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        yield</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> return</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> WaitForSeconds</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0.5f</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 0.5秒返回一次  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br></div></div><p>运行结果</p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>[22:40:01] wait for return</span></span>
<span class="line"><span>[22:40:04] done return 1s</span></span>
<span class="line"><span>[22:40:04] done next return, out 10</span></span>
<span class="line"><span>[22:40:04] start async2</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br></div></div></details>
<p>yield返回的特殊方法</p>
<ul>
<li><strong><code>yield return null/数字</code> 和 <code>yield return WaitForSeconds</code></strong>：在满足条件后的下一帧 <code>Update</code> 和 <code>LateUpdate</code> 之间执行</li>
<li><strong><code>yield return WaitForFixedUpdate</code></strong>：在 <code>FixedUpdate</code> 和碰撞检测相关函数之后执行(物理更新后)</li>
<li><strong><code>yield return WaitForEndOfFrame</code></strong>：在摄像机和GUI渲染完成后<code>FixedUpdate</code> 之后执行</li>
<li><strong><code>yield break</code></strong>：立即结束协程，协程对象会变<code>null</code></li>
<li>其他的异步对象(网络 场景)一般是<code>Update</code> 和 <code>LateUpdate</code> 之间执行<br>
<strong>协程的本质</strong>是迭代器，然后Unity调度器执行，和py里面迭代器一样，使用Current和MoveNext执行，直接点进<code>IEnumerator</code>看。<br>
自带的Coroutine无法进行trycacth，必须依赖于Monobehavior。使用C#原生的的async会跨线程而且Task消耗也不小，但是可以摆脱对MonoBehavior的依赖。</li>
</ul>
<div class="tip custom-block"><p class="custom-block-title">[💡Tip]</p>
<p>Task的本质上是起了新线程，Task.Delay完全不受TimeScale影响。</p>
</div>
<h4 id="延迟函数" tabindex="-1">延迟函数 <a class="header-anchor" href="#延迟函数" aria-label="Permalink to &quot;延迟函数&quot;">&ZeroWidthSpace;</a></h4>
<p>MonoBehaviour中提供了延迟调用函数的方法<code>Invoke</code> <code>InvokeRepeating</code> <code>CancelInvoke</code> (参数都简单易懂<br>
延时执行只能无参，而且只能执行本脚本中的对象，但是可以先获得，再通过函数或者Action包一下执行。<br>
<code>Invoke</code>即为调用，<code>Invoke</code>多次会调用多次，但是<code>CancelInvoke</code>是按照函数签名去取消的，也就是说会把该函数的调用全都踢出队列取消掉。<br>
<mark>注意 对象或脚本失活不会影响延迟函数调用；但是对象或脚本销毁移除，就延迟函数不会执行了</mark> 如果想要用失活激活控制，可以放到Enable和Disable中控制</p>
<details class="details custom-block"><summary>延迟函数</summary>
<p>迟函数</p>
<div class="language-Csharp vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">Csharp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> CurryingDelyDemo</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">string</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> s</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Debug.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">$"be Invoked {</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">s</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">}"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> InvokeDemo</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Debug.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"be Invoked"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> CalcelInvokeDemo</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    Debug.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Invoke is Canceled"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    CancelInvoke</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"InvokeDemo"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Start</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">() </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// GameObject加载完毕后所有的Awake执行完，的第一帧执行一次  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    Action</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> myInvokeDemo</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> CurryingDelyDemo</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Hello, World!"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    Debug.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Object start successfully Complete"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    // 定时任务  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    Invoke</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"InvokeDemo"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">3f</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 3秒(浮点)后通过反射来执行函数  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    InvokeRepeating</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"InvokeDemo"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">2f</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">3f</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 从调用的2秒后每3s执行一次  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    Invoke</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"CalcelInvokeDemo"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">10f</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//10秒(浮点)后通过反射来执行取消  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    Invoke</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(myInvokeDemo.Method.Name,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">3f</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 通过委托的闭包传递参数  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br></div></div></details>
<h3 id="unitask" tabindex="-1">Unitask <a class="header-anchor" href="#unitask" aria-label="Permalink to &quot;Unitask&quot;">&ZeroWidthSpace;</a></h3>
<p>常用的替代原生的异步任务库，其实是第三方插件。0GC，集合了原生async和unityCoroutine的优点。虽然异步的原理都是状态机但是实现的结构不太一样。看文档安装<a href="https://github.com/Cysharp/UniTask/tree/master" target="_blank" rel="noreferrer">GitHub - Cysharp/UniTask</a><br>
Debug模式下Unitask的起停性能差不多比原生协程强40%-50%，Release模式是原生协程的8-10倍左右。<br>
unitask使用await等待dotween动画需要开启一个宏<code>UNITASK_DOTWEEN_SUPPORT</code>。</p>
<div class="tip custom-block"><p class="custom-block-title">[💡Tip]</p>
<p>首先来嘱咐一下异步相关的问题，无论是使用任意一种异步方法，实际上也是在主线程中执行的，async实际上只是标识了可以使用异步方法，但是如果在async中调用同步方法依旧会阻塞主线程。所以建议使用await异步方法</p>
</div>
<p>我看的是<a href="https://linwentao785293209.github.io/2025/04/05/%E6%B8%B8%E6%88%8F%E5%BC%95%E6%93%8E/Unity/13.Unity%E8%BF%9B%E9%98%B6UniTask/1.%E6%A6%82%E8%BF%B0/" target="_blank" rel="noreferrer">唐老师</a>和<a href="https://www.bilibili.com/video/BV1PB4y1Y7dx/" target="_blank" rel="noreferrer">游戏石匠的视频</a>代码，用法很全面了，不过最好去下载一下石匠的执行一下对着理解，代码太多不放了打了注释直接去项目里面看吧。<br>
实践建议主线程只做渲染、输入、物理,耗时逻辑全异步</p>
<h4 id="基础用法" tabindex="-1">基础用法 <a class="header-anchor" href="#基础用法" aria-label="Permalink to &quot;基础用法&quot;">&ZeroWidthSpace;</a></h4>
<ul>
<li>使用UniTask的WhenAll和WhenAny监听，WaitUnitl对象挂载一次就只能使用一次，需要重复监听的话就得重新挂载。
<ul>
<li>会在每帧执行一次 <code>condition()</code> 检查委托调用 + 布尔判断，成本非常小，如果条件一直不触发那就一直监听</li>
<li>注意重复监听问题，多次注册会多次监听，虽然开销不大但是最好还是判断一下</li>
<li>WhenAll返回的是<code>Unitask&lt;T&gt;</code>,WhenAny返回的是<code>int index</code>，代表哪个最先完成的</li>
</ul>
</li>
<li>C#设计async和await的时候并不希望我们去取消所以支持很差。Unitask中有取消，可以用抛出异常或者额外返回值的方式取消，用额外返回值的方式性能更好。</li>
<li>使用Token取消，申请token在ToUniTask，Delay，NextFrame，WaitUnitl之类的函数中都能作为参数传入
<ul>
<li>调用Cancel即可取消，Token一次性Cancel之后就不能复用了，需要Dispose这个Token然后重新生成赋一个</li>
</ul>
</li>
</ul>
<h4 id="拓展用法" tabindex="-1">拓展用法 <a class="header-anchor" href="#拓展用法" aria-label="Permalink to &quot;拓展用法&quot;">&ZeroWidthSpace;</a></h4>
<ul>
<li>使用UnitaskVoid+Unitask.UnityAction是UI回调事件的专用方法，一般异步方法返回 <code>UniTask</code>但是UI 事件回调要求是void所以用<code>async UniTaskVoid</code>代替
<ul>
<li>Unity 的 UI 事件（<code>UnityEvent</code>）要求的签名是 <code>UnityAction</code>如果你想直接用异步方法会陷入回调地狱，所以用<code>UniTask.UnityAction</code></li>
</ul>
</li>
<li>使用<code>Calc().Forget();</code>可以在同步方法中调用异步函数但返回值必须是UniTask或者UniTaskVoid，可以使用<code>Calc().AsUniTask().Forget();</code>强行忽略，Forget的异常只能全局捕获</li>
<li>使用真正的线程执行注意上下文的切换,使用<code>UniTaskCompletionSource</code>产生的token是可以复用的。</li>
</ul>
<h4 id="进阶用法" tabindex="-1">进阶用法 <a class="header-anchor" href="#进阶用法" aria-label="Permalink to &quot;进阶用法&quot;">&ZeroWidthSpace;</a></h4>
<p>UI特有的事件转换为Unitask：</p>
<ul>
<li>OnClickAsAsyncEnumerable将点击事件转化为异步迭代器
<ul>
<li><code>ForEachAsync(value,index)</code>去异步迭代操作，相当于IEnumerator的非阻塞迭代，每次触发异步操作的时候迭代一次。但是里面的操作是阻塞的，注意千万别在里面搞骚操作卡住整个playerloop</li>
<li>只有当迭代器的Take全部迭代完成之后继续执行，Take(3)也是有头没尾，index是(0,1,2)。可以不写Take生成一个无限序列</li>
<li><code>asyncEnumerable</code>可以和其他的迭代器方法结合起来，过滤倒序等等更加灵活</li>
<li>注意fire-and-forget异步动画叠加问题,执行第一个动画forget，还没执行完就执行第二个动画forget，在动画计算的时候会依次计算然后覆盖，导致后面的覆盖掉前面的，但是前面的依旧消耗性能。最好的办法就是控制不要有冲突的动画逻辑</li>
</ul>
</li>
<li><code>OnClickAsync</code>是unitask为Button扩展的方法，可以在此处等待Button被click，下拉列表输入框的事件都可以转换</li>
<li><code>OnClickAsAsyncEnumerable</code>在C#8之后才支持，里面的操作支持异步，如果里面的await操作没有完成，即便触事件迭代器也不会响应，使用<code>.Queue().OnClickAsAsyncEnumerable()</code>可以先塞队列里不丢弃</li>
<li>球形case的思路,使用ForEachAsync每次点击去迭代，给球赋予动画</li>
<li>超时case使用的思路，使用<code>OnClickAsync</code>等待，第一次点击await，第二次点击不await了，把第二次点击和超时的Unitask放入WhenAny，判断哪个先完成</li>
<li>双击case的使用思路，<code>OnClickAsAsyncEnumerable</code>转换为异步迭代器，在迭代器中await 等待。</li>
</ul>
<p>值类型封装异步可迭代类型并订阅使用：</p>
<ul>
<li><code>AsyncReactiveProperty</code>封装异步迭代对象，可以达到类似于MVVM的效果。
<ul>
<li>注意代码中里利用三种方式订阅值变化，利用此可以轻松做到类似受到伤害后第五次免疫伤害的效果</li>
</ul>
</li>
<li>使用可订阅值添加到<code>ForEachAsync</code>的时候，会根根据当前值立即触发一次迭代，如果使用<code>asyobj.WithoutCurrent()</code>再<code>ForEachAsync</code>可以忽略当前值获得冷启动的效果</li>
</ul>
<p>MonoBehaviour事件输入：</p>
<ul>
<li>直接使用输入系统的键盘判断，必须在Update中执行，逻辑容易耦合一团糟，使用unitask可以避免这些问题</li>
<li>AsyncGamePlay可以做到不依赖MonoBehaviour的生命周期完成效果</li>
<li>使用<code>GameObject.transform.GetAsyncCollisionEnterTrigger</code>把Collision转化为异步迭代事件
<ul>
<li>先用source申请<code>UniTaskCompletionSource&lt;Collision&gt;</code></li>
<li>在异步迭代中<code>source.TrySetResult(collision);</code></li>
<li>然后就可以拿到碰撞结果<code>int result = await UniTask.WhenAny(waitAutoDestroy, source.Task);</code> result=1的时候进行处理</li>
</ul>
</li>
<li>这一块还挺复杂，这里先打一遍注释找时间吃回头草吧 #todo</li>
</ul>
<h4 id="配合dotween" tabindex="-1">配合Dotween <a class="header-anchor" href="#配合dotween" aria-label="Permalink to &quot;配合Dotween&quot;">&ZeroWidthSpace;</a></h4>
<h3 id="内置资源" tabindex="-1">内置资源 <a class="header-anchor" href="#内置资源" aria-label="Permalink to &quot;内置资源&quot;">&ZeroWidthSpace;</a></h3>
<h4 id="特殊文件夹" tabindex="-1">特殊文件夹 <a class="header-anchor" href="#特殊文件夹" aria-label="Permalink to &quot;特殊文件夹&quot;">&ZeroWidthSpace;</a></h4>
<ol>
<li><code>Application.dataPath</code>是总的工程目录文件夹<code>Assets</code> 的路径，在构建之后并不直接暴露给应用程序不能直接访问，一般只在开发阶段用用，也不保证跨平台一致性</li>
<li><code>Resources</code>资源文件夹直接使用<code>Resources</code>类读取资源。Resources可以在任意层级任意地方，<strong>但必须在Assets文件夹下</strong>，多个Resources会被合并起来。
<ul>
<li>当不同Resources中文件重名，会加载第一个找到的文件，如果有文件夹重名，则会报警告提示重复的资源路径 。在Start中使用<code>prefab_cube = Resources.Load&lt;GameObject&gt;(&quot;Perfabs/s2&quot;);</code>即可加载(非实例化仅加载对象到内存)。</li>
<li>适用于需要经常在运行时加载并实例化的资源（如场景、预制件、材质等）Unity会自动打包引入的资源文件，但是这个文件夹里的会全都加载。</li>
<li>不要存配置文件、日志文件等需要原样读取的文件，因为 Unity 会自动处理和打包，打包完后只读</li>
<li>无法被压缩和热更，所以现代商业项目一般不放东西，被那一堆资源管理取代了，不热更的小项目或者MVP可以用
<ul>
<li><code>BillingMode.json</code>Unity内购API自动生成的配置文件，构建时指定目标应用商店，以便在运行时加载正确的支付插件。Editor中使用 <code>UnityPurchasingEditor.TargetAndroidStore()</code> 选择目标商店时，Unity 会自动生成或更新该文件</li>
</ul>
</li>
</ul>
</li>
<li>位于<code>Assets/StreamingAssets</code>，使用<code>Application.streamingAssetsPath;</code>获得
<ul>
<li><strong>移动平台只读PC可读写</strong></li>
<li>常用<code>string path = Path.Combine(Application.streamingAssetsPath, &quot;netConfig.json&quot;);</code>读取其中资源</li>
<li><strong>跨平台一致性</strong> 文件夹中的内容在所有平台（Windows、macOS、iOS、Android等）上保持一致</li>
<li><strong>文件保持原样</strong> Unity 不会对 <code>StreamingAssets</code> 中的文件进行压缩或优化，适合存放<strong>媒体、配置文件、游戏内语言包、地图数据</strong>等静态数据</li>
</ul>
</li>
<li><code>persistentDataPath</code>持久数据文件夹<code>Application.persistentDataPath</code>获得使用在运行时可读写，动态下载或者游戏中生成的东西存储，<strong>游戏存档</strong>经常放里面</li>
<li><code>Plugins</code>插件文件夹 放第三方SDK的</li>
<li><code>Editor</code>编辑器文件夹 使用<code>Application.dataPath+&quot;/Editor&quot;</code>拼接，一般不获得；开发编辑器的时候脚本放里面；不会被打包
<ul>
<li><code>using UnityEditor</code>被打包到runtime的时候会报错</li>
</ul>
</li>
<li><code>StandardAssets</code>默认资源文件夹 Unity自带的文件都放这个文件夹，代码和资源优先被编译，一般不获得。</li>
</ol>
<h4 id="访问资源" tabindex="-1">访问资源 <a class="header-anchor" href="#访问资源" aria-label="Permalink to &quot;访问资源&quot;">&ZeroWidthSpace;</a></h4>
<p>UnityWebRequest不仅可以请求web还可以请求本地文件，但路径必须带<code>file://</code>，Win/Mac编辑器里运行时对本地<strong>绝对路径</strong>做了兼容，最佳实践就是直接全加上<code>file://</code>。<br>
实际上在Android和iOS的streamingAssetsPath被原样打包进了包里，用unity才能读到其他方式没权限拿包里的东西。</p>
<table tabindex="0">
<thead>
<tr>
<th>读取本地路径</th>
<th>persistentDataPath</th>
<th>persistentDataPath</th>
<th>streamingAssetsPath</th>
<th>streamingAssetsPath</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>读取方式</strong></td>
<td><strong>UnityWebRequest</strong></td>
<td><strong>C#文件读取</strong></td>
<td><strong>UnityWebRequest</strong></td>
<td><strong>C#文件读取</strong></td>
</tr>
<tr>
<td>PC</td>
<td>加 file:///</td>
<td>无需处理</td>
<td>加 file:///</td>
<td>无需处理</td>
</tr>
<tr>
<td>Android</td>
<td>加 file:///</td>
<td>无需处理</td>
<td>加 jar:file://</td>
<td>不可用</td>
</tr>
<tr>
<td>iOS</td>
<td>加 file:///</td>
<td>无需处理</td>
<td>加 file:///</td>
<td>无需处理</td>
</tr>
</tbody>
</table>
<p>再就是使用AB包的方式，放到任意文件系统能访问的位置即可加载。<br>
使用 <strong><code>Resources.Load&lt;T&gt;(&quot;Name&quot;,[typeof(TextAsset)])</code></strong> 同步加载资源，也可以指定类型或者传泛型。默认加载出来的类型为<code>Unity.Object</code> 可能需要类型转换</p>
<div class="warning custom-block"><p class="custom-block-title">[⚠️Warning] 注意文件名</p>
<p>意文件名
资源文件不要带文件后缀名，最好也不要带特殊字符，而且文件名是大小写敏感的</p>
</div>
<p>常见类型</p>
<ul>
<li>预设体GameObject</li>
<li>音效AudioClip</li>
<li>文本TextAsset</li>
<li>图片Texture</li>
<li>材质Material<br>
<code>Resources</code>加载到内存后会存在缓存区，多次加载不会重复加载，只会重复在缓存区中查找也会损耗一点性能。<br>
异步加载<code>Resources.LoadAsync</code>会新起一个线程进行加载，至少要等到下一帧才能拿到结果。</li>
</ul>
<details class="details custom-block"><summary>异步加载和使用协程异步加载</summary>
<p>步加载和使用协程异步加载</p>
<div class="language-Csharp vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">Csharp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Texture</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> TargetTexture</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Start</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    /* 使用线程加载 */</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    // ResourceRequest Rq = Resources.LoadAsync&#x3C;Texture>("Picture/t");</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> // 该类型包含Action对象  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    // Rq.completed += LoadDone;</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> // 加载完之后通过回调通知执行  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    /* 使用协程加载 */</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">   </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    Coroutine</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> cor</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">StartCoroutine</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">LoadTexture</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">());  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">private</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> LoadDone</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">AsyncOperation</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> op</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    TargetTexture </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (op </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">as</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> ResourceRequest</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">).asset </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">as</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Texture</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Loading Done"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">IEnumerator</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> LoadTexture</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    ResourceRequest</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Rq</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Resources.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">LoadAsync</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Texture</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Picture/t"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    yield</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Rq; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  协程调度器会监控 Rq.isDone 的状态 Rq.priority，完事才执行下面的  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    while</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">!</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Rq.isDone) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  也可以手动监控  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">$"porcessing {</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Rq</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">priority</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">}"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        yield</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Rq;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }    TargetTexture </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Rq.asset </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">as</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Texture</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}  </span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> OnGUI</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (TargetTexture </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">!=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {        </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Draw texture"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        GUI.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">DrawTexture</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Rect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">200</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">100</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">), TargetTexture);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br></div></div></details>
<p>资源必须是通过 <code>Resources.Load</code> 加载的才能卸载，使用<code>Resources.UnloadAsset(oldTexture);</code>卸载，但是<strong>不能卸载GameObject对象</strong>即使没有实例化。<br>
使用<code>Resources.UnloadUnusedAssets</code> 卸载所有未被引用的资源，此操作是异步的，会遍历所有资源并检查引用计数性能消耗很高，一般搭配<code>GC.Collect()</code>在过场景的时候使用。
某个资源正在被场景中的对象使用（例如一个纹理正被某个材质使用），卸载它可能导致渲染异常或崩溃</p>
<h4 id="加载场景" tabindex="-1">加载场景 <a class="header-anchor" href="#加载场景" aria-label="Permalink to &quot;加载场景&quot;">&ZeroWidthSpace;</a></h4>
<p>场景使用静态类<code>UnityEngine.SceneManagement.SceneManager</code>，需要引入命名空间。能够直接加载的场景需要提前添加到 菜单-&gt;File-&gt;BuildSettings-&gt;Scenes in  Build 中，注意这个里面场景有序号。<br>
然后就可以直接<code>SceneManager.LoadScene(&quot;NextScene&quot;)</code> 加载场景(即便BuildSetting中是带路径的也只用名字就行)，一般最常用的就是通过名字加载,<code>GameObject.DontDestroyOnLoad(gameObject)</code>挂载者自己在场景切换的时候不销毁<br>
退出游戏使用<code>Application.Quit()</code>,打包发布出去才行，编辑模式下没用。(Application类可以获得很多和游戏相关的属性，比如游戏是否在运行isPlaying<br>
加载的时候Unity会删除本场景上的所有对象然后读取下一个场景的东西，东西比较多的时候就耗时多。<br>
<strong>异步加载场景</strong><code>SceneManager.LoadSceneAsync(&quot;NextScene&quot;)</code>返回值和资源异步加载一样是<code>AsyncOperation</code>，可以使用complete事件绑定回调。<strong>常用来加载空场景然后使用指定的地图编辑器配置文件生成新场景的内容</strong></p>
<details class="details custom-block"><summary>异步加载场景的两种方法</summary>
<p>步加载场景的两种方法</p>
<div class="language-Csharp vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">Csharp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Start</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    AsyncOperation</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> loading</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">SceneManager.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">LoadSceneAsync</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    /* 注意这里，理论上这里加载完后就销毁，但是这个函数被回调引用，引用计数不会销毁它，所以能继续执行 */</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    loading.completed </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">AsyncOperation</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> a</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"场景2加载完毕"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">IEnumerator</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> LoadScene2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Loading Scene 2"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    GameObject.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">DontDestroyOnLoad</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">this</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.gameObject); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  这种操作应该提前操作，Unity切换场景yield完成的时候就已经切完了，涉及到旧场景的对象放在yield return后是不安全的</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    yield</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> SceneManager.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">LoadSceneAsync</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    /* 这样下面的语句就会执行，否则场景销毁对象也已经被销毁这里就不会被执行。 */</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Loading Scene 2 done"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    /* 这里就可以加过渡和进度条等，按照你想的进度去做 */</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">private</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> float</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> time</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Update</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    time </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Time.deltaTime;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (time </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">></span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  这里只演示，其实不该在Update里做</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        StartCoroutine</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">LoadScene2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">());</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br></div></div></details>
<h4 id="设置鼠标" tabindex="-1">设置鼠标 <a class="header-anchor" href="#设置鼠标" aria-label="Permalink to &quot;设置鼠标&quot;">&ZeroWidthSpace;</a></h4>
<p>鼠标使用公共类<code>Cursor</code>管理，如果你不想鼠标变形就找个一样大小的图片，最好把这个素材的Inspector面板的类型设置为Cursor</p>
<div class="language-Csharp vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">Csharp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Cursor.visible </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 显不显示  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Cursor.lockState </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> CursorLockMode.Locked; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// None不限制,Locked锁在屏幕中心还会被隐藏,Confined缩在游戏窗口  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Cursor.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">SetCursor</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(cursor_texture, Vector2.zero, CursorMode.Auto); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  一个Texture2d 偏移量 自动管理。</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br></div></div><h2 id="持久化" tabindex="-1">持久化 <a class="header-anchor" href="#持久化" aria-label="Permalink to &quot;持久化&quot;">&ZeroWidthSpace;</a></h2>
<h3 id="playerprefs" tabindex="-1">PlayerPrefs <a class="header-anchor" href="#playerprefs" aria-label="Permalink to &quot;PlayerPrefs&quot;">&ZeroWidthSpace;</a></h3>
<p>持久话键值对，<code>{string:[int string float]}</code> <strong>默认是游戏结束才落盘</strong>，如果崩溃就丢了，其实就是个类型支持不全的字典。<br>
存到哪，在BuildSettings-&gt;PlayerSettings-&gt;CompanyName;ProductName设置。</p>
<ol>
<li>win在注册表 <code>\HKCU\Software\[CompanyName]\[ProductName]</code></li>
<li>安卓<code>/data/data/包名/shared_prefs/pkg-name.xml</code></li>
<li>IOS <code>/Library/Preferences/[应用ID].plist</code></li>
</ol>
<details class="details custom-block"><summary>PlayerPrefs的基本API</summary>
<p>layerPrefs的基本API</p>
<div class="language-Csharp vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">Csharp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Start</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    PlayerPrefs.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">SetInt</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Test1"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">10</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    PlayerPrefs.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">SetFloat</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Test2"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0.5f</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    PlayerPrefs.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">SetString</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Test3"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"ttttt"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    PlayerPrefs.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Save</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 落盘  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    PlayerPrefs.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">DeleteKey</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Test1"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    //  如果读取的时候对应的类型错误 或者没有这个键，则会返回读取类型的默认值  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(PlayerPrefs.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetInt</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Test1"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  get的时候和dict一样可以获取默认值  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(PlayerPrefs.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetFloat</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Test2"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1f</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">));  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(PlayerPrefs.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetString</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Test3"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"NoValue"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">));  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    PlayerPrefs.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">DeleteAll</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 全清除，测试常用  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(PlayerPrefs.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">HasKey</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Test1"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">))</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Test1 有东西！"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br></div></div></details>
<p>这几个不是Unity自带的，C#直接看的书，有关序列化的坑也在这里了。</p>
<h3 id="json" tabindex="-1">JSON <a class="header-anchor" href="#json" aria-label="Permalink to &quot;JSON&quot;">&ZeroWidthSpace;</a></h3>
<p>主流的这四个<code>newtonsoft.json</code>, <code>System.Text.Json</code>,<code>fastjson</code> , <code>jsondotnet</code>，Unity自带的<code>JsonUtility</code>（非常不好用，只看第一个就行剩下俩碰到再说<br>
直接上代码</p>
<details class="details custom-block"><summary>基本用法</summary>
<p>本用法</p>
<div class="language-Csharp vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">Csharp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">using</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> System</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">using</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> System</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Collections</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Generic</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">using</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> System</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Runtime</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Serialization</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">using</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Newtonsoft</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Json</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">using</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Newtonsoft</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Json</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Converters</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">using</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Newtonsoft</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Json</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Linq</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">using</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Newtonsoft</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Json</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Serialization</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">namespace</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> PlayGround</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">#</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">region</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> NewtonSoft.Json基础用法</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Student</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> int</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Id</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> { </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">get</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">set</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; }</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> string</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">? </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">FullName</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> { </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">get</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">set</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; }</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> int</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Age</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> { </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">get</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">set</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; }</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> string</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">? </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Address</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> { </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">get</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">set</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; }</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> double</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> GPA</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> { </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">get</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">set</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Play1</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> string</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> S_string</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> """</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">                             {</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">                               "Id": 1,</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">                               "FullName": "Jhon",</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">                               "Age": 20,</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">                               "Address": "翻斗花园",</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">                               "GPA": 3.5</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">                             }</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">                             """</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    private</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> JsonSerializerSettings</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> _settings</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> JsonSerializerSettings</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Formatting </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Formatting.Indented, </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 使用缩进</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        ContractResolver </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> DefaultContractResolver</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        {</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">            // NamingStrategy = new DefaultNamingStrategy()</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            NamingStrategy </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> SnakeCaseNamingStrategy</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">() </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  蛇形</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">            // NamingStrategy = new CamelCaseNamingStrategy()//  大驼峰</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">            // NamingStrategy = new KebabCaseNamingStrategy()</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> //  烤-串-命-名</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        },</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        NullValueHandling </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> NullValueHandling.Ignore,</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  序列化遇到空值会跳过去掉这个属性</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        StringEscapeHandling </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> StringEscapeHandling.EscapeNonAscii, </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 会把非ascii进行unicode编码</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        TypeNameHandling </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> TypeNameHandling.Auto,</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 使用All可以强制带上序列化和反序列化的类型名。</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    };</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Run</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        Student</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> s</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Student</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            Id </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            FullName </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "Jhon"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            Age </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 20</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            Address </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "翻斗花园"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            GPA </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 3.5</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        };</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        string</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> jsonStr</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> JsonConvert.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">SerializeObject</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(s); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 默认是一行压缩展示</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        jsonStr</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">JsonConvert.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">SerializeObject</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(s,_settings); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 自动换行</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">WriteLine</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(jsonStr);</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        Student</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> s1</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> JsonConvert.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">DeserializeObject</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Student</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>(S_string); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 设置序列化和反序列化都能用</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">WriteLine</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(s1.FullName);</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">#</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">endregion</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">#</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">region</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> JsonPopulateObject用法</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Person2</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> string</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Name</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> { </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">get</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">set</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; }</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> int</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Age</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> { </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">get</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">set</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; }</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> List</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">string</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">> </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Hobbies</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> { </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">get</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">set</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> override</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> string</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> ToString</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=></span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> $"Name:{</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Name</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">},Age:{</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Age</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">},Hobbies:{</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">string</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Join</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">(",", </span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Hobbies</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">)}"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Play2</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    private</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> JsonSerializerSettings</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> _settings</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> JsonSerializerSettings</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Formatting </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Formatting.Indented, </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 使用缩进</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        ContractResolver </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> DefaultContractResolver</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            NamingStrategy </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> SnakeCaseNamingStrategy</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">() </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  蛇形</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        },</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        NullValueHandling </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> NullValueHandling.Ignore,</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  序列化遇到空值会跳过去掉这个属性</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        StringEscapeHandling </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> StringEscapeHandling.EscapeNonAscii, </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 会把非ascii进行unicode编码</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        ObjectCreationHandling </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> ObjectCreationHandling.Replace </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 使用PopulateObject如果是单独项则直接替换。如果是list就会append进来，指定Replace也会直接替换</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    };</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    private</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> string</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> s</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"""</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">                     {</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">                       "name": "Jack",</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">                       "age": 35,</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">                       "hobbies": [</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">                         "Chinese",</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">                         "English",</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">                         "Write"</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">                       ]</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">                     }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">                     """</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Run</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        Person2</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> p</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Person2</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            Name </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "Jack"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            Age </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 20</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            Hobbies </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> List</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">string</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">> { </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Play"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Read"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Write"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        };</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">WriteLine</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(JsonConvert.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">SerializeObject</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(p,_settings));</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        JsonConvert.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">PopulateObject</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(s, p,_settings);</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 读取json字符串，然后更新当前的对象</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">WriteLine</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(JsonConvert.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">SerializeObject</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(p,_settings));</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">#</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">endregion</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">#</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">region</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 提供的Attributes</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// MemberSerialization.OptIn 白名单模式，写了JsonProperty的才要</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// MemberSerialization.OptOut 黑名单模式，写了JsonIgnore的才不要</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// MemberSerialization.Fields 很奇怪，会把封装到IL的真实属性带出来？</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">JsonObject</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(MemberSerialization.Fields),]</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Person3</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    [</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">JsonProperty</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"create_at1"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)] </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 我就想序列化,还指定自定义名称！</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    private</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> readonly</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> DateTime</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> CreateAt</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> DateTime.Now;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Guid</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Id</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> { </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">get</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">set</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; }</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> string</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Name</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> { </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">get</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">set</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; }</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> int</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Age</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> { </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">get</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">set</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; }</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> List</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">string</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">> </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Hobbies</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> { </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">get</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">set</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; }</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> event</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> EventHandler</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">? </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">OnPropertyChanged</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    [</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">JsonIgnore</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">] </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 如果我不想序列化</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> string</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">? </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Description</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =></span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> $"Name:{</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Name</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">},Age:{</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Age</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">},Hobbies:{</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">string</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Join</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">(",", </span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Hobbies</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">)}"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Play3</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    Person3</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> p</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Person3</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Id </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Guid.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">NewGuid</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(),</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Name </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "Jhon"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Age </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 10</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Hobbies </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> List</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">string</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">> { </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Funk"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Music"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    };</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    private</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> JsonSerializerSettings</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> _settings</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> JsonSerializerSettings</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Formatting </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Formatting.Indented, </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 使用缩进</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        ContractResolver </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> DefaultContractResolver</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            NamingStrategy </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> SnakeCaseNamingStrategy</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">() </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  蛇形</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        },</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        StringEscapeHandling </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> StringEscapeHandling.EscapeNonAscii, </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 会把非ascii进行unicode编码</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    };</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Run</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">WriteLine</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(JsonConvert.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">SerializeObject</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(p,_settings));</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">#</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">endregion</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">#</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">region</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 自定义的Converter序列化器</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Person4</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    [</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">JsonProperty</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">JsonConverter</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">typeof</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">DateTimeFormateConverter</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">))]</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    private</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> readonly</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> DateTime</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> CreateAt</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> DateTime.Now;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Guid</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Id</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> { </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">get</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">set</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; }</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> string</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Name</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> { </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">get</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">set</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; }</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> IntWapper</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> _Age</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> { </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">get</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">set</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; } </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  直接用会相当于嵌套对象一样的效果"_Age":{"Value":10}</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    // public int Age { get=>_Age.Value; set=>_Age.Value = value; }</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> // 使用自定义的JsonConverter可以不用单独写这东西</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    [</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">JsonConverter</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">typeof</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">StringEnumConverter</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">))] </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 可以让序列化出来的Enum使用名字而不是数字</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Gender</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Gender</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> { </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">get</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">set</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    [</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">JsonConverter</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">typeof</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">StringEnumConverter</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">))]</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> WorkDays</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> WorkDays</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> { </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">get</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">set</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; }</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> List</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">string</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">> </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Hobbies</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> { </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">get</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">set</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Play4</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    Person4</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> p</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Person4</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Id </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Guid.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">NewGuid</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(),</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Name </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "Jhon"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        _Age </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> IntWapper</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">10</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">),</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Gender </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  Gender.Male,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        WorkDays </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> WorkDays.Monday </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">|</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">WorkDays.Tuesday</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">|</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">WorkDays.Wednesday</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">|</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">WorkDays.Saturday</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">|</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">WorkDays.Friday, </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 使用二进制表示哪天干活</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Hobbies </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> List</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">string</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">> { </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Funk"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Music"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    };</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Run</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        string</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> j</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> JsonConvert.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">SerializeObject</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(p,Formatting.Indented);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">WriteLine</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(j);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">enum</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Gender</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    Male</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    Female</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Flags</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">] </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 让一个枚举值可以同时表示多个状态的组合。序列化和 ToString() 时，自动输出组合名称。</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> enum</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> WorkDays</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    Monday</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    Tuesday</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    Wednesday</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">4</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    Thursday</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">8</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    Friday</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">16</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    Saturday</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">32</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    Sunday</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">64</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> DateTimeFormateConverter</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> : </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">IsoDateTimeConverter</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> // 自定义时间的序列化</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> DateTimeFormateConverter</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        DateTimeFormat </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "yyyy-MM-dd"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">JsonConverter</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">typeof</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">IntWapperConverter</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">))] </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 所有使用IntWapper类的属性在自动序列化的时候都会走自定义的Converter</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> IntWapper</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> IntWapper</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">int</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> value</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        this</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.Value </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> value;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> int</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Value</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> { </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">get</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">set</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> IntWapperConverter</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> : </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">JsonConverter</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> override</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> WriteJson</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">JsonWriter</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> writer</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">object</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">? </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">value</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">JsonSerializer</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> serializer</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        serializer.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Serialize</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(writer, ((</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">IntWapper</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)value).Value); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  序列化的时候怎么做</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> override</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> object</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">? </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">ReadJson</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">JsonReader</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> reader</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Type</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> objectType</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">object</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">? </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">existingValue</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">JsonSerializer</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> serializer</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        return</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> IntWapper</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(Convert.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">ToInt32</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(reader.Value)); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  反序列化的时候怎么做</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> override</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> bool</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> CanConvert</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Type</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> objectType</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        return</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> typeof</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">IntWapper</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">).</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">IsAssignableFrom</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(objectType); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  能不能被序列化</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">#</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">endregion</span></span>
<span class="line"></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">#</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">region</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 序列化的HOOK函数</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Person5</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> string</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Name</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> { </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">get</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">set</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; }</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> int</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Age</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> { </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">get</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">set</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; }</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> List</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">string</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">> </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Hobbies</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> { </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">get</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">set</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; }</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> event</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> EventHandler</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">? </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">OnPropertyChanged</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    [</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">OnSerializing</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    internal</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> OnSerializingMethod</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">StreamingContext</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> context</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    [</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">OnSerialized</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    internal</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> OnSerializedMethod</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">StreamingContext</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> context</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    [</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">OnDeserializing</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    internal</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> OnDeserializingMethod</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">StreamingContext</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> context</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">WriteLine</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Deserializing!"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Hobbies</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">?</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Clear</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 反序列化的时候先把原来的列表清掉</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    [</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">OnDeserialized</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    internal</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> OnDeserializedMethod</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">StreamingContext</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> context</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        this</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.OnPropertyChanged</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">sender</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">e</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">WriteLine</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"属性变化了"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        this</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.OnPropertyChanged.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Invoke</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">this</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> EventArgs</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 调用一下试试</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"></span>
<span class="line"></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Play5</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    Person5</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> p</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Person5</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Name </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "Jhon"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Age </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 10</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Hobbies </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> List</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">string</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">> { </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Funk"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Music"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    };</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    private</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> string</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> s</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> """</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">                       {</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">                         "name": "ahon",</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">                         "age": 15,</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">                         "hobbies": [</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">                           "Chinese",</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">                           "Math"</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">                         ]</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">                       }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">                       """</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    private</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> JsonSerializerSettings</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> _settings</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> JsonSerializerSettings</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Formatting </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Formatting.Indented, </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 使用缩进</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        ContractResolver </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> DefaultContractResolver</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            NamingStrategy </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> SnakeCaseNamingStrategy</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">() </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  蛇形</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        },</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        StringEscapeHandling </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> StringEscapeHandling.EscapeNonAscii, </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 会把非ascii进行unicode编码</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    };</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Run</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">WriteLine</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(JsonConvert.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">SerializeObject</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(p,_settings));</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        JsonConvert.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">DeserializeObject</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Person5</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>(s,_settings); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 这里应该就会输出日志并且挂上了那个是函数事件</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">#</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">endregion</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Play6</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    private</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> string</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> s</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> @"</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">        [{</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">            ""</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">$schema</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">""</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">""</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">http://json.schemastore.org/launchsettings.json</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">""</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">,</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">            ""</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">profiles</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">""</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">: {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">                ""</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">Newtonsoft.Json.Tutorial</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">""</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">: {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">                    ""</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">commandName</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">""</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">""</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">Project</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">""</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">,</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">                    ""</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">environmentVariables</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">""</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">: {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">                        ""</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">ASPNETCORE_ENVIRONMENT</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">""</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">""</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">Development</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">""</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">,</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">                        ""</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">ASPNETCORE_URLS</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">""</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">""</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">http://localhost:5000</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">""</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">,</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">                        ""</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">DOTNET_USE_POLLING_FILE_WATCHER</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">""</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">""</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">true</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">""</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">                    }</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">                }</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">            }</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">        }]"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Run</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        // var obj = (JObject)JsonConvert.DeserializeObject(s);</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> // 可以一般序列化不指定类型，但是注意Array还是Object</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        var</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> obj</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> JArray.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Parse</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(s); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">WriteLine</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(obj[</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">][</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"profiles"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">][</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Newtonsoft.Json.Tutorial"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">][</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"commandName"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">].</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">ToString</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">());</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br><span class="line-number">50</span><br><span class="line-number">51</span><br><span class="line-number">52</span><br><span class="line-number">53</span><br><span class="line-number">54</span><br><span class="line-number">55</span><br><span class="line-number">56</span><br><span class="line-number">57</span><br><span class="line-number">58</span><br><span class="line-number">59</span><br><span class="line-number">60</span><br><span class="line-number">61</span><br><span class="line-number">62</span><br><span class="line-number">63</span><br><span class="line-number">64</span><br><span class="line-number">65</span><br><span class="line-number">66</span><br><span class="line-number">67</span><br><span class="line-number">68</span><br><span class="line-number">69</span><br><span class="line-number">70</span><br><span class="line-number">71</span><br><span class="line-number">72</span><br><span class="line-number">73</span><br><span class="line-number">74</span><br><span class="line-number">75</span><br><span class="line-number">76</span><br><span class="line-number">77</span><br><span class="line-number">78</span><br><span class="line-number">79</span><br><span class="line-number">80</span><br><span class="line-number">81</span><br><span class="line-number">82</span><br><span class="line-number">83</span><br><span class="line-number">84</span><br><span class="line-number">85</span><br><span class="line-number">86</span><br><span class="line-number">87</span><br><span class="line-number">88</span><br><span class="line-number">89</span><br><span class="line-number">90</span><br><span class="line-number">91</span><br><span class="line-number">92</span><br><span class="line-number">93</span><br><span class="line-number">94</span><br><span class="line-number">95</span><br><span class="line-number">96</span><br><span class="line-number">97</span><br><span class="line-number">98</span><br><span class="line-number">99</span><br><span class="line-number">100</span><br><span class="line-number">101</span><br><span class="line-number">102</span><br><span class="line-number">103</span><br><span class="line-number">104</span><br><span class="line-number">105</span><br><span class="line-number">106</span><br><span class="line-number">107</span><br><span class="line-number">108</span><br><span class="line-number">109</span><br><span class="line-number">110</span><br><span class="line-number">111</span><br><span class="line-number">112</span><br><span class="line-number">113</span><br><span class="line-number">114</span><br><span class="line-number">115</span><br><span class="line-number">116</span><br><span class="line-number">117</span><br><span class="line-number">118</span><br><span class="line-number">119</span><br><span class="line-number">120</span><br><span class="line-number">121</span><br><span class="line-number">122</span><br><span class="line-number">123</span><br><span class="line-number">124</span><br><span class="line-number">125</span><br><span class="line-number">126</span><br><span class="line-number">127</span><br><span class="line-number">128</span><br><span class="line-number">129</span><br><span class="line-number">130</span><br><span class="line-number">131</span><br><span class="line-number">132</span><br><span class="line-number">133</span><br><span class="line-number">134</span><br><span class="line-number">135</span><br><span class="line-number">136</span><br><span class="line-number">137</span><br><span class="line-number">138</span><br><span class="line-number">139</span><br><span class="line-number">140</span><br><span class="line-number">141</span><br><span class="line-number">142</span><br><span class="line-number">143</span><br><span class="line-number">144</span><br><span class="line-number">145</span><br><span class="line-number">146</span><br><span class="line-number">147</span><br><span class="line-number">148</span><br><span class="line-number">149</span><br><span class="line-number">150</span><br><span class="line-number">151</span><br><span class="line-number">152</span><br><span class="line-number">153</span><br><span class="line-number">154</span><br><span class="line-number">155</span><br><span class="line-number">156</span><br><span class="line-number">157</span><br><span class="line-number">158</span><br><span class="line-number">159</span><br><span class="line-number">160</span><br><span class="line-number">161</span><br><span class="line-number">162</span><br><span class="line-number">163</span><br><span class="line-number">164</span><br><span class="line-number">165</span><br><span class="line-number">166</span><br><span class="line-number">167</span><br><span class="line-number">168</span><br><span class="line-number">169</span><br><span class="line-number">170</span><br><span class="line-number">171</span><br><span class="line-number">172</span><br><span class="line-number">173</span><br><span class="line-number">174</span><br><span class="line-number">175</span><br><span class="line-number">176</span><br><span class="line-number">177</span><br><span class="line-number">178</span><br><span class="line-number">179</span><br><span class="line-number">180</span><br><span class="line-number">181</span><br><span class="line-number">182</span><br><span class="line-number">183</span><br><span class="line-number">184</span><br><span class="line-number">185</span><br><span class="line-number">186</span><br><span class="line-number">187</span><br><span class="line-number">188</span><br><span class="line-number">189</span><br><span class="line-number">190</span><br><span class="line-number">191</span><br><span class="line-number">192</span><br><span class="line-number">193</span><br><span class="line-number">194</span><br><span class="line-number">195</span><br><span class="line-number">196</span><br><span class="line-number">197</span><br><span class="line-number">198</span><br><span class="line-number">199</span><br><span class="line-number">200</span><br><span class="line-number">201</span><br><span class="line-number">202</span><br><span class="line-number">203</span><br><span class="line-number">204</span><br><span class="line-number">205</span><br><span class="line-number">206</span><br><span class="line-number">207</span><br><span class="line-number">208</span><br><span class="line-number">209</span><br><span class="line-number">210</span><br><span class="line-number">211</span><br><span class="line-number">212</span><br><span class="line-number">213</span><br><span class="line-number">214</span><br><span class="line-number">215</span><br><span class="line-number">216</span><br><span class="line-number">217</span><br><span class="line-number">218</span><br><span class="line-number">219</span><br><span class="line-number">220</span><br><span class="line-number">221</span><br><span class="line-number">222</span><br><span class="line-number">223</span><br><span class="line-number">224</span><br><span class="line-number">225</span><br><span class="line-number">226</span><br><span class="line-number">227</span><br><span class="line-number">228</span><br><span class="line-number">229</span><br><span class="line-number">230</span><br><span class="line-number">231</span><br><span class="line-number">232</span><br><span class="line-number">233</span><br><span class="line-number">234</span><br><span class="line-number">235</span><br><span class="line-number">236</span><br><span class="line-number">237</span><br><span class="line-number">238</span><br><span class="line-number">239</span><br><span class="line-number">240</span><br><span class="line-number">241</span><br><span class="line-number">242</span><br><span class="line-number">243</span><br><span class="line-number">244</span><br><span class="line-number">245</span><br><span class="line-number">246</span><br><span class="line-number">247</span><br><span class="line-number">248</span><br><span class="line-number">249</span><br><span class="line-number">250</span><br><span class="line-number">251</span><br><span class="line-number">252</span><br><span class="line-number">253</span><br><span class="line-number">254</span><br><span class="line-number">255</span><br><span class="line-number">256</span><br><span class="line-number">257</span><br><span class="line-number">258</span><br><span class="line-number">259</span><br><span class="line-number">260</span><br><span class="line-number">261</span><br><span class="line-number">262</span><br><span class="line-number">263</span><br><span class="line-number">264</span><br><span class="line-number">265</span><br><span class="line-number">266</span><br><span class="line-number">267</span><br><span class="line-number">268</span><br><span class="line-number">269</span><br><span class="line-number">270</span><br><span class="line-number">271</span><br><span class="line-number">272</span><br><span class="line-number">273</span><br><span class="line-number">274</span><br><span class="line-number">275</span><br><span class="line-number">276</span><br><span class="line-number">277</span><br><span class="line-number">278</span><br><span class="line-number">279</span><br><span class="line-number">280</span><br><span class="line-number">281</span><br><span class="line-number">282</span><br><span class="line-number">283</span><br><span class="line-number">284</span><br><span class="line-number">285</span><br><span class="line-number">286</span><br><span class="line-number">287</span><br><span class="line-number">288</span><br><span class="line-number">289</span><br><span class="line-number">290</span><br><span class="line-number">291</span><br><span class="line-number">292</span><br><span class="line-number">293</span><br><span class="line-number">294</span><br><span class="line-number">295</span><br><span class="line-number">296</span><br><span class="line-number">297</span><br><span class="line-number">298</span><br><span class="line-number">299</span><br><span class="line-number">300</span><br><span class="line-number">301</span><br><span class="line-number">302</span><br><span class="line-number">303</span><br><span class="line-number">304</span><br><span class="line-number">305</span><br><span class="line-number">306</span><br><span class="line-number">307</span><br><span class="line-number">308</span><br><span class="line-number">309</span><br><span class="line-number">310</span><br><span class="line-number">311</span><br><span class="line-number">312</span><br><span class="line-number">313</span><br><span class="line-number">314</span><br><span class="line-number">315</span><br><span class="line-number">316</span><br><span class="line-number">317</span><br><span class="line-number">318</span><br><span class="line-number">319</span><br><span class="line-number">320</span><br><span class="line-number">321</span><br><span class="line-number">322</span><br><span class="line-number">323</span><br><span class="line-number">324</span><br><span class="line-number">325</span><br><span class="line-number">326</span><br><span class="line-number">327</span><br><span class="line-number">328</span><br><span class="line-number">329</span><br><span class="line-number">330</span><br><span class="line-number">331</span><br><span class="line-number">332</span><br><span class="line-number">333</span><br><span class="line-number">334</span><br><span class="line-number">335</span><br><span class="line-number">336</span><br><span class="line-number">337</span><br><span class="line-number">338</span><br><span class="line-number">339</span><br><span class="line-number">340</span><br><span class="line-number">341</span><br><span class="line-number">342</span><br><span class="line-number">343</span><br><span class="line-number">344</span><br><span class="line-number">345</span><br><span class="line-number">346</span><br><span class="line-number">347</span><br><span class="line-number">348</span><br><span class="line-number">349</span><br><span class="line-number">350</span><br><span class="line-number">351</span><br><span class="line-number">352</span><br><span class="line-number">353</span><br><span class="line-number">354</span><br><span class="line-number">355</span><br><span class="line-number">356</span><br><span class="line-number">357</span><br><span class="line-number">358</span><br><span class="line-number">359</span><br><span class="line-number">360</span><br><span class="line-number">361</span><br><span class="line-number">362</span><br><span class="line-number">363</span><br><span class="line-number">364</span><br><span class="line-number">365</span><br><span class="line-number">366</span><br><span class="line-number">367</span><br><span class="line-number">368</span><br><span class="line-number">369</span><br></div></div></details>
<p><a href="https://www.newtonsoft.com/json" target="_blank" rel="noreferrer">newtonsoft.json官网</a>
需要注意和说明的参数</p>
<ul>
<li>默认只序列化 <code>public</code> 的<strong>属性</strong>，他不会自动序列化字段，也就是说<code>public int Id;</code>是不行的,要在类上给它加<code>[JsonObject(MemberSerialization.Fields)]</code>或者在字段上加<code>[JsonProperty]</code></li>
<li>假设我有Employee和Student继承自Person,此时使用<code>List&lt;Person&gt;</code>作为反序列化的泛型，会报错，因为他不知道该使用哪个类，此时用<code>TypeNameHandling = TypeNameHandling.Auto</code>设置去反序列化带$type的json即可识别。如果不开启<code>TypeNameHandling</code>属性他会退化成只填充了 <code>Person</code> 有的字段（如 <code>Name</code>）其余字段（如 <code>Company</code> 或 <code>School</code>）会<strong>自动忽略</strong>就不报错了。</li>
<li>处理无限嵌套或者不规则的json,互相嵌套的类(两个类中有属性是对方的类型)序列化失败，使用<code>ReferenceLoopHandling = ReferenceLoopHandling.Ignore</code>，</li>
<li>不明白的就拿出Run来跑一跑调一调</li>
</ul>
<p>unity中打开<code>Window-&gt;PackageManager</code>中<code>Add package from name</code>使用<code>com.unity.nuget.newtonsoft-json</code>安装，有时候直接搜搜不到<br>
在Native AOT的场景下，是不支持反射和动态代码生成的，<code>newtonsoft.json</code>使用了大量反射和动态代码生成，所以要使用<code>System.Text.Json</code>的源生成方式调用。
这个就用到再说不搞那么细了。</p>
<p>#todo<a href="https://chatgpt.com/c/68cc23cc-24f4-8325-a6a8-c236c990b574" target="_blank" rel="noreferrer">最下面有全局的Converter可用</a></p>
<h3 id="protobuf" tabindex="-1">Protobuf <a class="header-anchor" href="#protobuf" aria-label="Permalink to &quot;Protobuf&quot;">&ZeroWidthSpace;</a></h3>
<p><a href="https://protobuf.dev/" target="_blank" rel="noreferrer">文档</a>(<a href="https://protobuf.com.cn/" target="_blank" rel="noreferrer">中文也有</a>)讲的很明白，我用C#+unity。主要使用流程：<strong>写proto的配置文件</strong>；<strong>使用protoc编译成对应语言的类文件</strong>；<strong>在工程中引入protobuf库</strong>。然后就可以正常序列化发送接收了。<br>
Google官方的protobuf:<br>
C#和unity中引用protobuf库可以自己编译也可以使用别人编译好的dll文件，好像没有跨平台限制兼容unity版本就可以，Unity放Plugins里面。或者github项目中的<code>protobuf/csharp/src/Google.Protobuf</code>文件夹放到Assets里面。protoc命令安装不多说。</p>
<div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">protoc</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> --proto_path=StreamingAssets</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> --csharp_out=Scenes/testproto</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> --csharp_opt=base_namespace=example</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> test.proto</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">protoc</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> --proto_path=StreamingAssets</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> --csharp_out=Scenes/testproto</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> test.proto</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br></div></div><ol>
<li>生成命令中使用<code>--csharp_opt=base_namespace=specify_namespace</code>指定此次生成的proto类的命名空间，还有一种方法就是在proto的package关键字中指定多级命名空间以及引用其他命名空间。</li>
<li>可以使用多个<code>--proto_path</code>一次性指定多个目录搜索proto文件，按顺序搜索重名的会使用找到的第一个</li>
<li>生成的代码会根据目标语言的命名约定来调整字段名。在 C# 中，<code>protoc</code>会将消息和字段名转换为首字母大写，并把 串行 小驼峰 转换为 大驼峰。</li>
<li>同时使用<code>user_name</code>和<code>userName</code>编译后结果都是<code>UserName</code>，此时编译会不通过</li>
</ol>
<details class="details custom-block"><summary>proto示例</summary>
<p>roto示例</p>
<div class="language-Csharp vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">Csharp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Start</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    Example</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">User</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> user</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> User</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> //  和构建类一样去构建</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Name </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "小明"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Email </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "j@gmail.com"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Addresses </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> { </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Address</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            City </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "洛杉矶"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            State </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "LA"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            ZipCode </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 10000</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            Street </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "jeans"</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        } }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    };</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    user.Type </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> UserType.Member;</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    Address</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> _addr</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Address</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        City </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "纽约1"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        State </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "NY2"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        ZipCode </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 10003</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Street </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "jeans4"</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    };</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    user.Addresses.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Add</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(_addr); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// repeated可以当数组用</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    user.Tags.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Add</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"标记1"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"值1"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  map可以当字典用</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    user.Phone </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 只有可空类型才允许赋值为空</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    byte</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[] </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">data</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> user.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">ToByteArray</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 转换为字节数组</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    Debug.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">$"序列化字节数组长度: {</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">data</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Length</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">}"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    using</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">MemoryStream</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> stream</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> MemoryStream</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  使用流序列化</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        user.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">WriteTo</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(stream);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Debug.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">$"流长度: {</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">stream</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Length</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">}"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    User</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> parsedUser</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> User.Parser.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">ParseFrom</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(data);</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  从字节数组反序列化，也可以直接从流序列化</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    Debug.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">$"解析用户名字: {</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">parsedUser</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Name</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">}"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br></div></div></details>
<p>反序列化的时候可以从流中读取，Protobuf 本身没有内置消息边界，可以每条消息前写一个 <strong>varint 长度前缀</strong>，用长连接一边发一边接，读取完指定的长度解析一次。这样可以在一个流里面塞一堆消息。<br>
protobuf官方是从.net3.5开始支持的，社区开发了protobuf-net只能在dotnet内部使用，使用protogen而不是protoc，一般一个项目只用这俩中的一个（新的最好</p>
<h3 id="xml" tabindex="-1">XML <a class="header-anchor" href="#xml" aria-label="Permalink to &quot;XML&quot;">&ZeroWidthSpace;</a></h3>
<p><code>XmlDocument</code>,<code>XmlTextReader</code> ,<code>Linq</code>常用的三种，一般无脑用<strong>XmlDocument</strong>和Linq。
基本IO</p>
<details class="details custom-block"><summary>读取XML常用的API</summary>
<p>取XML常用的API</p>
<div class="language-Csharp vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">Csharp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Start</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    XmlDocument</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> xml</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> XmlDocument</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    string</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> xmlPath</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Path.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Combine</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(Application.streamingAssetsPath, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"TestXml.xml"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    string</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> xmlStr</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> File.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">ReadAllText</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(xmlPath);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    xml.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">LoadXml</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(xmlStr); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 加载字符串为xml  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    xml.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">LoadXml</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(xmlPath); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 按路径直接加载文件  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    XmlNode</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> root</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> xml.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">SelectSingleNode</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Root"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 获取根节点(xml有且仅有一个根节点)  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    XmlNode</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> nodeName</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> root.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">SelectSingleNode</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"name"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 通过根节点去获取下面的子节点  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(nodeName.InnerText); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 获取节点文本，默认已经做了CDATA的处理了  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    XmlNode</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> nodeItem</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> root.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">SelectSingleNode</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Item"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    XmlNodeList</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> ChildNodes</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> nodeItem.ChildNodes; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 遍历字节点，字节点支持Name和InnerText属性  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(nodeItem.Attributes[</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"id"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">].Value);   </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 获取属性值  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(nodeItem.Attributes.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetNamedItem</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"num"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">).Value);  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 也可以这样获取  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    XmlNodeList</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> friendList</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> root.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">SelectNodes</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Friend"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 同名节点 获取列表  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(xml);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br></div></div></details>
<details class="details custom-block"><summary>写入修改XML常用API</summary>
<p>入修改XML常用API</p>
<div class="language-Csharp vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">Csharp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Start</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    string</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> xmlPath</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Path.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Combine</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(Application.streamingAssetsPath, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"TestXmlWrite.xml"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    XmlDocument</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> xmlDocument</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> XmlDocument</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    XmlDeclaration</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> xmlDec</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> xmlDocument.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">CreateXmlDeclaration</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"1.0"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"UTF-8"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">""</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  创建固定版本信息  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    xmlDocument.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">AppendChild</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(xmlDec);</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  需要手动添加进去  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    XmlElement</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> root</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> xmlDocument.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">CreateElement</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Root"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  创建根节点  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    xmlDocument.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">AppendChild</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(root);  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    XmlElement</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> name</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> xmlDocument.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">CreateElement</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"name"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  创建子节点  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    name.InnerText </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "小明"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    root.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">AppendChild</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(name); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  需要在对应的节点下Append  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    XmlElement</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> listInt</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> xmlDocument.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">CreateElement</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"listInt"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">int</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> i</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x3C;=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; i</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">++</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 添加多个子节点  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        XmlElement</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> childNode</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> xmlDocument.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">CreateElement</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"int"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        childNode.InnerText </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> i.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">ToString</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  内容为下标  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        childNode.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">SetAttribute</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"id"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, i.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">ToString</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 设置id属性  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        childNode.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">SetAttribute</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"num"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, (i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 10</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">).</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">ToString</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 设置num属性  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        listInt.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">AppendChild</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(childNode);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }    </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    root.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">AppendChild</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(listInt);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    xmlDocument.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Save</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(xmlPath);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    Debug.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"------------------------------"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 写入之后，读取并修改  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    XmlDocument</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> newXml</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> XmlDocument</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    newXml.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Load</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(xmlPath); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  读取刚才创建的那个  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    XmlNode</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> node</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    node </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> newXml.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">SelectSingleNode</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Root"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">).</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">SelectSingleNode</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"name"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    node </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> newXml.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">SelectSingleNode</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Root/name"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  直接用路径也可以  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    XmlNode</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> root2</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> newXml.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">SelectSingleNode</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Root"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//得到父节点  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    root2.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">RemoveChild</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(node); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  移除子节点方法  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    XmlElement</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> moveSpeed</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> newXml.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">CreateElement</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"moveSpeed"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    moveSpeed.InnerText </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "20"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    root2.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">AppendChild</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(moveSpeed); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  给你想加的加上  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    newXml.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Save</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(xmlPath); </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br></div></div><p>运行结果</p>
<div class="language-xml vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">xml</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;?</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">xml</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> version</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"1.0"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> encoding</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"UTF-8"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">?>  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">Root</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  &#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">listInt</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    &#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">int</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> id</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"1"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> num</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"10"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>1&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">int</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    &#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">int</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> id</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"2"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> num</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"20"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>2&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">int</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    &#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">int</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> id</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"3"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> num</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"30"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>3&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">int</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  &#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">listInt</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  &#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">moveSpeed</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>20&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">moveSpeed</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">Root</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br></div></div></details>
<p>序列化 <code>XmlSerializer</code> 接口提供了钩子，可以让一些内容单独处理逻辑，可以在里面单独处理字典<br>
<strong>如果字段为 <code>null</code>这个XML节点会被跳过，空节点都不会生成</strong>。如果有需求在<code>IXmlSerializable.WriteXml</code>中自己写。<br>
#todo  其实没搞完上班看这几个自定义API方式的用法区别</p>
<details class="details custom-block"><summary>XML序列化常用API</summary>
<p>ML序列化常用API</p>
<div class="language-Csharp vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">Csharp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">#</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">define</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> USE_TYPE_1</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// #define USE_TYPE_2</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// #define USE_TYPE_3</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">using</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> System</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">using</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> System</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Collections</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Generic</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">using</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> System</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">IO</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">using</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> System</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Xml</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">using</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> System</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Xml</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Schema</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">using</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> System</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Xml</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Serialization</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">using</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> UnityEngine</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 子节点类</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> ChildNode</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    [</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">XmlAttribute</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Test1"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)] </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 序列化为属性</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> int</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> test1</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    [</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">XmlAttribute</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()]</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> float</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> test2</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1.1f</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    [</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">XmlAttribute</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()]</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> bool</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> test3</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    [</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">XmlIgnore</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">] </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 忽略字段，不序列化</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> string</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> temp</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "不序列化的字段"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">XmlRoot</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"RootNode"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)] </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  指定根节点名字</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> TestXML</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> : </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">IXmlSerializable</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> int</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> testPublic</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    [</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">XmlElement</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"testPublicRenamed"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)]</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> int</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> testPublic2</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> string</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> testPublicStr</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "我是testPublicStr"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> int</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[] </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">arrayInt</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> int</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">] { </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> };</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    [</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">XmlArray</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"IntList"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)] </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  列表节点的名字</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    [</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">XmlArrayItem</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Int32"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)] </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  列表内元素节点的名字</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> List</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">int</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">> </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">listInt</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> List</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">int</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">> { </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">4</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> }; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  一般列表的序列化</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> List</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">ChildNode</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">> </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">listItem</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> List</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">ChildNode</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">> { </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> ChildNode</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(), </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> ChildNode</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">() }; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  类列表的序列化</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    private</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> int</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> testPrivate</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 私有成员不会序列化</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Dictionary</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">int</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">string</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">> </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">testDic</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Dictionary</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">int</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">string</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>() { { </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"123"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> }, { </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"456"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> } }; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 直接序列化字典</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> XmlSchema</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> GetSchema</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=></span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 通常返回 null</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">#</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">if</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> USE_TYPE_1</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    // ------------------------ 方式1 直接写serializer------------------------</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> WriteXml</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">XmlWriter</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> writer</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// XmlWriter：提供顺序写XML文档的API</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> XmlSerializer</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">typeof</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">List</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">int</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>)).</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Serialize</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(writer, listInt); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// Serialize：把对象写到writer</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> XmlSerializer</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">typeof</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">List</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">ChildNode</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>)).</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Serialize</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(writer, listItem);</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        writer.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">WriteStartElement</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"DictList"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// WriteStartElement：写开始标签 &#x3C;DictList></span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        foreach</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">var</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> kv</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> in</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> testDic)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            writer.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">WriteStartElement</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Item"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// &#x3C;Item></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            writer.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">WriteAttributeString</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Key"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, kv.Key.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">ToString</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">());   </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 写属性 Key="1"</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            writer.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">WriteAttributeString</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Value"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, kv.Value);          </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 写属性 Value="123"</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            writer.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">WriteEndElement</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// &#x3C;/Item></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        writer.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">WriteEndElement</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// &#x3C;/DictList></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> ReadXml</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">XmlReader</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> reader</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// XmlReader：提供只进不退的方式读取XML节点</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        reader.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">MoveToContent</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 定位到当前元素的内容（跳过声明/空白）</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        listInt </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">List</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">int</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>)</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> XmlSerializer</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">typeof</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">List</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">int</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>)).</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Deserialize</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(reader); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// Deserialize：从XML生成对象</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        listItem </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">List</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">ChildNode</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>)</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> XmlSerializer</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">typeof</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">List</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">ChildNode</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>)).</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Deserialize</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(reader);</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        testDic.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Clear</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (reader.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">ReadToDescendant</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Item"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// ReadToDescendant：跳到第一个&#x3C;Item></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            do</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">                int</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> key</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> int</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Parse</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(reader.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetAttribute</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Key"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// GetAttribute：读取属性值</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">                string</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> value</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> reader.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetAttribute</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Value"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">                testDic[key] </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> value;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">while</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (reader.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">ReadToNextSibling</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Item"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// ReadToNextSibling：跳到下一个&#x3C;Item></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            reader.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">ReadEndElement</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 离开&#x3C;/DictList></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">#</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">elif</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> USE_TYPE_2</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    // ------------------------ 方式2 手动写属性/节点 ------------------------</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> WriteXml</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">XmlWriter</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> xmlWriter</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        xmlWriter.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">WriteStartElement</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"testPublic"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// &#x3C;testPublic></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        xmlWriter.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">WriteElementString</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Value"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, testPublic.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">ToString</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// &#x3C;Value>1&#x3C;/Value></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        xmlWriter.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">WriteEndElement</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// &#x3C;/testPublic></span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        xmlWriter.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">WriteStartElement</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"testPublicStr"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// &#x3C;testPublicStr></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        xmlWriter.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">WriteElementString</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Value"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, testPublicStr);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        xmlWriter.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">WriteEndElement</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> ReadXml</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">XmlReader</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> xmlReader</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        xmlReader.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">MoveToContent</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (xmlReader.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">MoveToAttribute</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"testPublic"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// MoveToAttribute：尝试移动到指定属性</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            testPublic </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> int</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Parse</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(xmlReader.Value); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// Value：当前节点/属性的值</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (xmlReader.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">MoveToAttribute</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"testPublicStr"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">))</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            testPublicStr </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> xmlReader.Value;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">#</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">elif</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> USE_TYPE_3</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    // ------------------------ 方式3 循环读取NodeType ------------------------</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> WriteXml</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">XmlWriter</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> xmlWriter</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        xmlWriter.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">WriteStartElement</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"testPublic"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        xmlWriter.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">WriteString</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(testPublic.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">ToString</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// WriteString：写文本内容</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        xmlWriter.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">WriteEndElement</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        xmlWriter.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">WriteStartElement</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"testPublicStr"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        xmlWriter.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">WriteString</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(testPublicStr);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        xmlWriter.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">WriteEndElement</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> ReadXml</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">XmlReader</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> xmlReader</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        xmlReader.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">MoveToContent</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        while</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (xmlReader.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Read</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// Read：前进到下一个节点</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (xmlReader.NodeType </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">==</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> XmlNodeType.Element) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// NodeType：当前节点类型（Element/Text/EndElement）</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">                switch</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (xmlReader.Name) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// Name：节点名称</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">                {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">                    case</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "testPublic"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">                        xmlReader.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Read</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 移动到&#x3C;testPublic>的内容</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">                        testPublic </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> int</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Parse</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(xmlReader.Value); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// Value：当前文本节点的值</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">                        break</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">                    case</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "testPublicStr"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">                        xmlReader.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Read</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">                        testPublicStr </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> xmlReader.Value;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">                        break</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">                }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">#</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">else</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">#</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">endif</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> XMLExample</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> : </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">MonoBehaviour</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Start</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        string</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> path</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Application.persistentDataPath </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "/TestXMLSerialize.xml"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        TestXML</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> obj</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> TestXML</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  构造一个默认数据的类</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"XML存储路径："</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> +</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> path);</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        // ---------------- 序列化 ----------------</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        using</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">StreamWriter</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> writer</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> StreamWriter</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(path)) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// StreamWriter有他就打开没有他会新建。</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        {</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">            XmlSerializer</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> serializer</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> XmlSerializer</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">typeof</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">TestXML</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">));</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            serializer.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Serialize</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(writer, obj); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  落盘</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        // ---------------- 反序列化 ----------------</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        using</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">StreamReader</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> reader</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> StreamReader</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(path)) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  读不到会System.IO.FileNotFoundException</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        {</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">            XmlSerializer</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> serializer</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> XmlSerializer</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">typeof</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">TestXML</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">));</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">            TestXML</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> deserialized</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">TestXML</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)serializer.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Deserialize</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(reader);</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">            print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"反序列化 testPublic: "</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> +</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> deserialized.testPublic);</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">            print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"反序列化 testPublic2: "</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> +</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> deserialized.testPublic2);</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">            print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"反序列化 testPublicStr: "</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> +</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> deserialized.testPublicStr);</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">            print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"反序列化 listInt[0]: "</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> +</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> deserialized.listInt[</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]);</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">            print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"反序列化 listItem[0].test1: "</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> +</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> deserialized.listItem[</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">].test1);</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br><span class="line-number">50</span><br><span class="line-number">51</span><br><span class="line-number">52</span><br><span class="line-number">53</span><br><span class="line-number">54</span><br><span class="line-number">55</span><br><span class="line-number">56</span><br><span class="line-number">57</span><br><span class="line-number">58</span><br><span class="line-number">59</span><br><span class="line-number">60</span><br><span class="line-number">61</span><br><span class="line-number">62</span><br><span class="line-number">63</span><br><span class="line-number">64</span><br><span class="line-number">65</span><br><span class="line-number">66</span><br><span class="line-number">67</span><br><span class="line-number">68</span><br><span class="line-number">69</span><br><span class="line-number">70</span><br><span class="line-number">71</span><br><span class="line-number">72</span><br><span class="line-number">73</span><br><span class="line-number">74</span><br><span class="line-number">75</span><br><span class="line-number">76</span><br><span class="line-number">77</span><br><span class="line-number">78</span><br><span class="line-number">79</span><br><span class="line-number">80</span><br><span class="line-number">81</span><br><span class="line-number">82</span><br><span class="line-number">83</span><br><span class="line-number">84</span><br><span class="line-number">85</span><br><span class="line-number">86</span><br><span class="line-number">87</span><br><span class="line-number">88</span><br><span class="line-number">89</span><br><span class="line-number">90</span><br><span class="line-number">91</span><br><span class="line-number">92</span><br><span class="line-number">93</span><br><span class="line-number">94</span><br><span class="line-number">95</span><br><span class="line-number">96</span><br><span class="line-number">97</span><br><span class="line-number">98</span><br><span class="line-number">99</span><br><span class="line-number">100</span><br><span class="line-number">101</span><br><span class="line-number">102</span><br><span class="line-number">103</span><br><span class="line-number">104</span><br><span class="line-number">105</span><br><span class="line-number">106</span><br><span class="line-number">107</span><br><span class="line-number">108</span><br><span class="line-number">109</span><br><span class="line-number">110</span><br><span class="line-number">111</span><br><span class="line-number">112</span><br><span class="line-number">113</span><br><span class="line-number">114</span><br><span class="line-number">115</span><br><span class="line-number">116</span><br><span class="line-number">117</span><br><span class="line-number">118</span><br><span class="line-number">119</span><br><span class="line-number">120</span><br><span class="line-number">121</span><br><span class="line-number">122</span><br><span class="line-number">123</span><br><span class="line-number">124</span><br><span class="line-number">125</span><br><span class="line-number">126</span><br><span class="line-number">127</span><br><span class="line-number">128</span><br><span class="line-number">129</span><br><span class="line-number">130</span><br><span class="line-number">131</span><br><span class="line-number">132</span><br><span class="line-number">133</span><br><span class="line-number">134</span><br><span class="line-number">135</span><br><span class="line-number">136</span><br><span class="line-number">137</span><br><span class="line-number">138</span><br><span class="line-number">139</span><br><span class="line-number">140</span><br><span class="line-number">141</span><br><span class="line-number">142</span><br><span class="line-number">143</span><br><span class="line-number">144</span><br><span class="line-number">145</span><br><span class="line-number">146</span><br><span class="line-number">147</span><br><span class="line-number">148</span><br><span class="line-number">149</span><br><span class="line-number">150</span><br><span class="line-number">151</span><br><span class="line-number">152</span><br><span class="line-number">153</span><br><span class="line-number">154</span><br><span class="line-number">155</span><br><span class="line-number">156</span><br><span class="line-number">157</span><br><span class="line-number">158</span><br><span class="line-number">159</span><br><span class="line-number">160</span><br><span class="line-number">161</span><br><span class="line-number">162</span><br><span class="line-number">163</span><br><span class="line-number">164</span><br><span class="line-number">165</span><br><span class="line-number">166</span><br><span class="line-number">167</span><br><span class="line-number">168</span><br><span class="line-number">169</span><br><span class="line-number">170</span><br><span class="line-number">171</span><br><span class="line-number">172</span><br><span class="line-number">173</span><br><span class="line-number">174</span><br><span class="line-number">175</span><br><span class="line-number">176</span><br></div></div></details>
<h3 id="binary和基本io" tabindex="-1">Binary和基本IO <a class="header-anchor" href="#binary和基本io" aria-label="Permalink to &quot;Binary和基本IO&quot;">&ZeroWidthSpace;</a></h3>
<p>C#内置二进制序列化不多讲直接看API</p>
<details class="details custom-block"><summary>基本IO常用API</summary>
<p>本IO常用API</p>
<div class="language-Csharp vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">Csharp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Start</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    string</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> path</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Application.streamingAssetsPath;  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(File.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Exists</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(path </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "/t0.txt"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">));  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    FileStream</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> fsc</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> File.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Create</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(path </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "/t1.txt"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);fsc.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Close</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  注意这个会覆盖已有文件  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    File.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Delete</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(path </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "/t1.dest.txt"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  不存在不管存在就删  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    File.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Copy</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(path </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "/t1.txt"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, path </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "/t1.dest.txt"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 最后参数控制有就覆盖，false则有就报错  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    File.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Replace</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(path </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "/t1.txt"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, path </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "/t1.dest.txt"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, path </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "/t1.back.txt"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 前俩参数必须存在 第三个参数只备份内容  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    FileStream</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> fso</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> File.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Open</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(path </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "/t1.txt"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, FileMode.OpenOrCreate, FileAccess.ReadWrite); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// FileMode控制打开时的行为  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    //  其实上面两个打开的操作占了俩文件描述符  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    byte</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[] </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">bytes</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> BitConverter.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetBytes</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">999</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 转字节  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    byte</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[] </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">sbytes</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Encoding.UTF8.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetBytes</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"测试写字符串数组"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    byte</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[] </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Lenbytes</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> BitConverter.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetBytes</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(sbytes.Length); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 获取字符串数组多长,固定返回一个int4字节  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    File.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">WriteAllBytes</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(path </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "/t2.t"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, bytes);</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  这三个不存在就抛错DirectoryNotFoundException  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    File.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">WriteAllText</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(path </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "/t3.txt"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"我测"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    File.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">WriteAllLines</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(path </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "/t4.txt"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">new</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> string</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[]{</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"a"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"b"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 一行一个写入字符串数组  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    // 打开文件流的三种方式（茴的四种写法？  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    FileStream</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> fs1</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> FileStream</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(path </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "/fs1"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, FileMode.Create, FileAccess.ReadWrite);  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    FileStream</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> fs2</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> File.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Create</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(path </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "/fs2"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">2048</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  相当于一个简化工厂方法，默认 FileMode.Create、FileAccess.Write 只写不读  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    FileStream</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> fs3</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> File.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Open</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(path </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "/fs3"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, FileMode.OpenOrCreate);</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  也是相当于工厂方法，需要传 FileMode，可选 FileAccess 和 FileShareif(fs3.CanSeek)print("可寻址");  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(fs3.Length); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 文件流里有多少字节 不可寻址的文件句柄会报System.NotSupportedException: Stream does not support seeking  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    fs3.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Write</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(Lenbytes,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,Lenbytes.Length); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 字节数组文件指针开始和结束  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    fs3.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Write</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(sbytes,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,sbytes.Length);  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(fs3.CanSeek)</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"可移动文件指针"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(fs3.CanRead)</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"可读"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(fs3.CanWrite)</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"可写"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    fs3.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Flush</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  落盘  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    fs3.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Close</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 关闭描述符  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    fs3.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Dispose</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 自动fs3.Close()并回收缓冲区和其他资源  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    //  测试读取  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    FileStream</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> fs4</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> FileStream</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(path </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "/fs3"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, FileMode.Open, FileAccess.Read);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    Lenbytes </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> byte</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">4</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  重置  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    int</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> bytesReadLength</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> fs4.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Read</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(Lenbytes,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">4</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// Read会返回这次读取了多长（字节数）  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    int</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> _length</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> BitConverter.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">ToInt32</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(Lenbytes);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    sbytes </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=new</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> byte</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[_length]; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  重置  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    int</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> offset</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  文件指针  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    byte</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[] </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">buffer</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> byte</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 每次读取 2 字节  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    int</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> bytesRead</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"分块读取："</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    while</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (offset </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x3C;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> _length </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x26;&#x26;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (bytesRead </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> fs4.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Read</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(buffer, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, buffer.Length)) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">></span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 注意按字节读取是怎么读的  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Array.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Copy</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(buffer, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, sbytes, offset, bytesRead);</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 拷贝读取的数据到目标数组  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        offset </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> bytesRead; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 移动文件指针  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    string</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> result</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Encoding.UTF8.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetString</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(sbytes, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, _length); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 完整读取后，转换为字符串  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"成功读取："</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">result);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    fs4.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Dispose</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br></div></div></details>
<ul>
<li>打开文件会占用系统文件描述符，如果打开的FileStream没有手动关闭，则会在GC的时候尝试调用<code>Finalize</code>，但是多久才会GC掉是未知的，最好记得关。</li>
<li>文件描述符被占用的时候重复打开<code>IOException: Sharing violation on path /Assets/StreamingAssets/t1.txt</code></li>
<li>如果操作的不是普通文件句柄（比如 socket、管道、标准输入输出等）那就不是CanSeek，fs.Length会报<code>System.NotSupportedException: Stream does not support seeking</code></li>
<li>写入的内容传入必须符合<code>ReadOnlySpan&lt;byte&gt; buffer</code> 是一种 结构化的只读内存视图</li>
<li>写入字符串等不知道多长的，建议开头先写一个长度，读的时候读出知道多长再读内容
<ul>
<li>写入长度的时候，<code>fs.Write(lenBytes, 0, lenBytes.Length);</code>长度是可以接收Long的，但是超过int范围大小的<code>sbytes.Length</code>会获取报错，使用<code>sbytes.LongLength</code>获取Long类型的大小，读的时候也用Long的长度读</li>
<li>超过int的时候大约是2GB，这时候该考虑分块写入了</li>
</ul>
</li>
<li>FileStream是Strean它在内部只维护一个 文件句柄和缓冲区(通常 4KB ~ 8KB)<code>Read</code> 或 <code>Write</code> 时从磁盘读取/写入对应部分的数据</li>
<li><code>File.ReadAllBytes()</code> 或 <code>File.ReadAllText()</code>会一次性把整个文件读到内存大文件会 OOM
<ul>
<li>如果想对大文件随机访问用<code>MemoryMappedFile</code>它只把访问的部分映射到内存</li>
</ul>
</li>
<li>UTF-8 是 <strong>可变长度编码</strong>，每个字符占 1~4 个字节，按照字节读取不一定读到字符边界，需要读完之后整体转码。如果很大建议按块读然后按块转</li>
</ul>
<table tabindex="0">
<thead>
<tr>
<th>FileMode行为</th>
<th>文件存在</th>
<th>文件不存在</th>
</tr>
</thead>
<tbody>
<tr>
<td>Create</td>
<td>覆盖</td>
<td>创建</td>
</tr>
<tr>
<td>CreateNew</td>
<td>IOException</td>
<td>创建</td>
</tr>
<tr>
<td>Open</td>
<td>打开</td>
<td>FileNotFoundException</td>
</tr>
<tr>
<td>OpenOrCreate</td>
<td>打开</td>
<td>创建</td>
</tr>
<tr>
<td>Truncate</td>
<td>打开并清空</td>
<td>FileNotFoundException</td>
</tr>
<tr>
<td>Append</td>
<td>只写打开指针移到末尾</td>
<td>创建</td>
</tr>
</tbody>
</table>
<p>最好记一下每种变量占几个字节;<a href="https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/integral-numeric-types?utm_source=chatgpt.com" target="_blank" rel="noreferrer">Integral numeric types</a>; <a href="https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/floating-point-numeric-types" target="_blank" rel="noreferrer">Floating-point numeric types</a></p>
<details class="details custom-block"><summary>文件夹和Path常用API</summary>
<p>件夹和Path常用API</p>
<div class="language-Csharp vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">Csharp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Start</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    string</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> path</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Application.streamingAssetsPath;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    Directory.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Exists</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(path</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"/dir1"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    DirectoryInfo</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> dirInfo</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Directory.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">CreateDirectory</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(path </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "/dir1"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 可以按照路径递归创建，已存在会直接返回文件夹信息  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    Directory.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">CreateDirectory</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(path </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "/dir2"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    string</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[] </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">dirs</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Directory.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetDirectories</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(path); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 返回绝对路径  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    Directory.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Delete</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(path </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "/dir1"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  删非空报错，加第二个参数相当于rm -rf 如果某些文件被锁定或无权限，仍然会抛异常  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    string</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[] </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">files</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Directory.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetFiles</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(path);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    Directory.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Move</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(path </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "/dir2"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,path </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "/dir3"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  dest已经存在报错  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(dirInfo.Name);</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// Name文件夹名字；FullName带名全路径；Parent父文件夹名字(根目录返回 null)；Extension点分割的后缀；Root始终返回根目录;  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    DirectoryInfo</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> parentDir</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Directory.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetParent</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(path </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "/dir3"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  获得目标的父文件夹  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    DirectoryInfo</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[] </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">dirsDetail</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> parentDir.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetDirectories</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  更详细一些，支持搜索默认*  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    FileInfo</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[] </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">filesDetail</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> parentDir.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetFiles</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(filesDetail[</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">].Length); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// FileInfo可以获得Length  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    string</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> filePath</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> path</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"/demo.txt"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;File.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Create</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(filePath);  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    string</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> dirPath</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> path</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"/dir3"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  先创建示例  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    string</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> combined</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Path.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Combine</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(dirPath, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"subfolder"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"file.txt"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(combined); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 合并后 /Users/jack/code/dotnet/demobase/CoreProject/Assets/StreamingAssets/dir3/subfolder/file.txt 注意后面是怎么合并的  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(Path.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetFileName</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(filePath));  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// demo.txt  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(Path.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetFileNameWithoutExtension</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(filePath)); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// demo  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(Path.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetDirectoryName</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(filePath)); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// /Users/jack/code/dotnet/demobase/CoreProject/Assets/StreamingAssets  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(Path.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetExtension</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(filePath)); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// .txt  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(Environment.CurrentDirectory); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 当前工作目录 unity默认是项目根目录，可以通过更改这个值改掉  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(Path.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetFullPath</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">@"../demo.txt"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 返回此路径的绝对路径，依赖当前工作目录/Users/jack/code/dotnet/demobase/demo.txt  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(Path.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetTempPath</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">());  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 系统临时目录  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(Path.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetTempFileName</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">());  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 临时文件（会创建一个空文件）  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    string</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> newFile</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Path.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">ChangeExtension</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(filePath, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">".log"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(newFile);  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(Path.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">IsPathRooted</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(filePath)); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 判断是否是绝对路径  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(Path.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetRandomFileName</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 随机文件名，不会真创建(x4z1ab2f.tmp)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br></div></div></details>
<ul>
<li>路径Win不区分大小写Linux/macOS区分大小写</li>
<li>支持相对路径，操作基于当前工作目录</li>
<li><code>Path.Combine</code><strong>会从第一个绝对路径开始覆盖前面的路径</strong></li>
</ul>
<table tabindex="0">
<thead>
<tr>
<th>Path属性</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>Path.DirectorySeparatorChar</code></td>
<td>当前系统目录分隔符 <code>\</code> 或 <code>/</code></td>
</tr>
<tr>
<td><code>Path.AltDirectorySeparatorChar</code></td>
<td>替代分隔符 <code>/</code>（在 Windows 可用）</td>
</tr>
<tr>
<td><code>Path.PathSeparator</code></td>
<td>路径列表分隔符 <code>;</code></td>
</tr>
<tr>
<td><code>Path.InvalidPathChars</code></td>
<td>不允许出现在路径中的字符数组</td>
</tr>
<tr>
<td><code>Path.MaxPath</code></td>
<td>Windows 最大路径长度（260 字节，.NET Core 可以超长）</td>
</tr>
</tbody>
</table>
<details class="details custom-block"><summary>二进制常用API</summary>
<p>进制常用API</p>
<div class="language-Csharp vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">Csharp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> BinarySerialize</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> : </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">MonoBehaviour</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    [</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">System</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Serializable</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Person</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> string</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Name</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "jack"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> int</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> i</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Start</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        Person</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> person</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Person</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        using</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">MemoryStream</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> memoryStream</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> MemoryStream</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">())</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        {</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">            BinaryFormatter</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> binaryFormatter</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> BinaryFormatter</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            binaryFormatter.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Serialize</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(memoryStream, person);</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            byte</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[] </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">_bytes</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> memoryStream.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetBuffer</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 对象的二进制数组拿到可以做很多事</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            File.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">WriteAllBytes</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(Application.streamingAssetsPath </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "/person"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, _bytes);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            memoryStream.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Close</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        }</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        using</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">FileStream</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> fileStream</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> FileStream</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(Application.streamingAssetsPath </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "/person.cp"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, FileMode.OpenOrCreate, FileAccess.Write))</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        {</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">            BinaryFormatter</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> binaryFormatter</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> BinaryFormatter</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            binaryFormatter.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Serialize</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(fileStream, person); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 序列化完直接写到一个打开的流中</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            fileStream.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Flush</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            fileStream.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Close</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        }</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        byte</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[] </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">bytes</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> File.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">ReadAllBytes</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(Application.streamingAssetsPath </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "/person"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        using</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">MemoryStream</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> memoryStream</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> MemoryStream</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(bytes))</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        {</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">            BinaryFormatter</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> binaryFormatter</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> BinaryFormatter</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">            Person</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> personRestore</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> binaryFormatter.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Deserialize</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(memoryStream) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">as</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Person</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 反正传个打开的Stream就行</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            memoryStream.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Close</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">            print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"还原Person："</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> +</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> personRestore.Name);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br></div></div></details>
<p>使用的是内置的BinaryFormatter，类上加<code>[System.Serializable]</code>特性进行序列化</p>
<ul>
<li>支持内置的常用类型， Unity 支持<code>Vector3</code>, <code>Quaternion</code>, <code>Color</code> 等内置 <code>[Serializable]</code> 类型</li>
<li>
<ul>
<li>字段必须是 <code>public</code> 或 <code>[SerializeField]</code> 才能被序列化，不支持字典、接口、抽象类、委托、事件、循环引用</li>
</ul>
</li>
<li>属性不会被序列化（只有字段）静态字段不会被序列化</li>
<li><code>[NonSerialized]</code> 可以显式排除字段</li>
<li>不支持循环引用</li>
<li><strong>反序列化的时候类一定要有而且一定要一致！</strong></li>
<li>其实他我没有全试，到时候用到再说，能用MemoryPack替代的时候先替代</li>
</ul>
<h3 id="memorypack" tabindex="-1">MemoryPack <a class="header-anchor" href="#memorypack" aria-label="Permalink to &quot;MemoryPack&quot;">&ZeroWidthSpace;</a></h3>
<p>C#中的高性能二进制序列化，不跨语言，dotnet10(unity2021.3+)支持，需要额外安装，定位是替代C#内置二进制序列化，提供了生命周期hook函数。</p>
<ul>
<li>默认不支持多态，需要手动实现</li>
<li>字段顺序按类代码顺序决定
<ul>
<li>默认序列化公共实例属性或字段,使用<code>[MemoryPackIgnore]</code>来移除序列化目标，<code>[MemoryPackInclude]</code>将私有成员提升为序列化目标，所有成员都需要是可以被序列化的不然报错。</li>
</ul>
</li>
<li>值类型需要标记可空，引用类型自动支持 null</li>
<li>如下实现零分配（重要优势，在 序列化 / 反序列化过程中不额外产生新的对象或临时数组，避免动态数组更容易触发GC，对CPU缓存更友好。我这里好像没法测试0分配
#todo 说实话搞不太明白了，回头有机缘了再弄,这东西应该能写到文件流中，试一下用网络流和本地文件流 <a href="https://www.bilibili.com/video/BV17MtUzJEM5/" target="_blank" rel="noreferrer">安装要两步</a></li>
</ul>
<details class="details custom-block"><summary>MemoryPack序列化API</summary>
<p>emoryPack序列化API</p>
<div class="language-Csharp vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">Csharp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">using</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> System</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Collections</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">using</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> System</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Collections</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Generic</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">using</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> TMPro</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">using</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> UnityEngine</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">using</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> MemoryPack</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">using</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> System</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> MemoryP</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> : </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">MonoBehaviour</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Start</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        // 创建测试对象，包含多态引用</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        User</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> user</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> User</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> { Id </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1001</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, Name </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "Jack"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, Email </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "jack@example.com"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            Pet </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Dog</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> { Name </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "Buddy"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, HasTail </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> } }; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 使用Union特性实现多态</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        // 预分配缓冲区，实现零分配（我的Mono好像不支持）</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        byte</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[] </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">buffer</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> byte</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1024</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">];</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        int</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> bytesWritten</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> MemoryPackSerializer.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Serialize</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">User</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>(user, buffer);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Debug.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">$"序列化字节长度: {</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">bytesWritten</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">}"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        // 反序列化用户对象</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        User</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> deserializedUser</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> MemoryPackSerializer.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Deserialize</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">User</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>(buffer, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, bytesWritten);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Debug.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">$"反序列化结果: Id={</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">deserializedUser</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Id</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">}, Name={</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">deserializedUser</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Name</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">}"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        // 直接序列化到新分配的字节数组（简便但有内存分配）</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        byte</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[] </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">data</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> MemoryPackSerializer.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Serialize</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">User</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>(user);</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        User</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> deserializedUser2</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> MemoryPackSerializer.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Deserialize</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">User</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>(data);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">MemoryPackable</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> partial</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> User</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> int</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">? </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Id</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> { </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">get</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">set</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; }     </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 支持可空类型</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> string</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Name</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> { </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">get</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">set</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; } </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 支持字符串</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> string</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Email</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> { </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">get</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">set</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; }</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Animal</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Pet</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> { </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">get</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">set</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; }  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 多态属性，使用Union特性实现</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">MemoryPackable</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">] </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 使用MemoryPackUnion在抽象基类或接口上保证编译时 Source Generator 生效</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">MemoryPackUnion</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">typeof</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Dog</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">))] </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 使用索引0标识Dog类型</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">MemoryPackUnion</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">typeof</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Cat</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">))] </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 使用索引1标识Cat类型</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> abstract</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> partial</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Animal</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> string</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Name</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> { </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">get</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">set</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">MemoryPackable</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> partial</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Dog</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> : </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Animal</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> bool</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> HasTail</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> { </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">get</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">set</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; } </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 特有属性</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">MemoryPackable</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> partial</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Cat</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> : </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Animal</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> int</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Lives</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> { </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">get</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">set</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; } </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 特有属性</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br><span class="line-number">50</span><br><span class="line-number">51</span><br><span class="line-number">52</span><br><span class="line-number">53</span><br><span class="line-number">54</span><br><span class="line-number">55</span><br><span class="line-number">56</span><br><span class="line-number">57</span><br></div></div></details>
<h3 id="scriptableobject" tabindex="-1">ScriptableObject <a class="header-anchor" href="#scriptableobject" aria-label="Permalink to &quot;ScriptableObject&quot;">&ZeroWidthSpace;</a></h3>
<p>Unity内置的可配置的对象可以理解为一个数据模板类，优势是可以直接在Inscpetor中编辑，在Editor下是持久化的，runtime停止之后也是会丢失的。<br>
性能其实没有xml二进制json高<br>
类似MonoBehaviour，需要继承<code>ScriptableObject</code>类，inspector中的可见性和MonoBehaviour一样，直接关联ScriptableObject相当于设置默认值，会记录在对应的.meta文件中<br>
可以注册<code>[CreateAssetMenu()]</code>特性（ScriptableObject特有的）在右键在菜单创建，也可以在方法中调用创建，一般是在菜单栏静态方法里用</p>
<details class="details custom-block"><summary>创建ScriptableObject</summary>
<p>建ScriptableObject
右键菜单创建</p>
<div class="language-Csharp vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">Csharp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 参数为创建出来的数据文件默认名字，右键菜单显示名字，排序优先级（升序）  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">CreateAssetMenu</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">fileName</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"jackData"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">menuName</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"ScriptableObject/我的数据"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">order</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)]</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> MyData</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">ScriptableObject</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> int</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> i</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> float</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> f</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> bool</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> b</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> GameObject</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> gobj</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Material</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> m</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> AudioClip</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> auCliper</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> VideoClip</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> vidCliper</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br></div></div><p>注册到工具栏菜单的示例调用，ScriptableObject保存成<code>.asset</code>文件：只能在Editor下（非运行时），最常用的就是<code>AssetDatabase</code>API，这些通常会配合<code>[MenuItem]</code>写在静态方法里。</p>
<div class="language-Csharp vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">Csharp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> ScriptableObjectTool</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    [</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">MenuItem</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"ScriptableObject/CreateMyData"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)]  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> static</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> CreateMyData</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">() </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  MenuItem必须加到静态方法上  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        //书写创建数据资源文件的代码 &#x3C;T>中一定要继承ScriptableObject  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        MyData</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> myDataAsset</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> ScriptableObject.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">CreateInstance</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">MyData</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>();  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        AssetDatabase.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">CreateAsset</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(myDataAsset, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Assets/Resources/MyDataTest.asset"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//通过编辑器API 根据数据scrpitableobj创建一个数据资源文件  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        AssetDatabase.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">SaveAssets</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//保存创建的资源  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        AssetDatabase.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Refresh</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//刷新界面  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br></div></div></details>
<p>在MonoBehaviour中声明对应的ScriptableObject变量，Inspector中用拖<strong>数据资源文件</strong>关联上去。<br>
这东西也支持使用Rsources和AB包加载。<strong>文件被多个对象加载是共享状态的</strong>大部分对象都是线程不安全的，而且在线程中不能访问Monobehaviour和ScriptableObjcet对象</p>
<details class="details custom-block"><summary>使用ScriptableObject</summary>
<p>用ScriptableObject</p>
<div class="language-Csharp vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">Csharp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> SoTest</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> : </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">MonoBehaviour</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> MyData</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> myData</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 可以在Inspector关联  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Start</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {        </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        myData </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Resources.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Load</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">MyData</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"jackData"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  使用Resource加载  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        myData.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">PrintInfo</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br></div></div></details>
<p>场景比如怪物数值模板，可以在里面写一些类型什么的，然后在创建的时候在怪物的Awake中把ScriptableObjcet对象上的数值复制到普通类中</p>
<details class="details custom-block"><summary>ScriptableObject不常用的生命周期</summary>
<p>criptableObject不常用的生命周期
和MonoBehaviour类似，它也有生命周期函数数量较少一般不常用。</p>
<ul>
<li>Awake：在数据文件创建时调用。</li>
<li>OnDestroy：在 ScriptableObject 对象将被销毁时调用。</li>
<li>OnDisable：在 ScriptableObject 对象销毁时、即将重新加载脚本程序集时调用。</li>
<li>OnEnable：在 ScriptableObject 创建或加载对象时调用。</li>
<li>OnValidate：这是一个仅在编辑器下调用的函数，在 Unity 加载脚本或者在 Inspector 窗口中更改值时会被调用。</li>
</ul>
</details>
<div class="warning custom-block"><p class="custom-block-title">[⚠️Warning]</p>
<p>这东西在Editor中的行为是持久化的，但是打包出去就不会持久化了。<br/>
这东西其实不是设计来持久化游戏数据的，非要做可以结合其他的IO文件格式做</p>
</div>
<ul>
<li>可以做配置文件更方便（非纯文本真的更好吗</li>
<li>用作公共数据解耦省内存，多个GameObject挂同一个数据资源文件，不会在内存中复制多份（只用不更改的数据用共用这一个节省一些，改变会影响到所有使用数据文件的对象</li>
<li>方便处理数据带来的多态
<ul>
<li>使用继承ScriptObject的基类，提供抽象方法，用里氏替换在脚本中挂载子类的数据文件，实现多态。</li>
</ul>
</li>
</ul>
<p>非持久化数据:<br>
上面是创建了一个资源文件去关联，本地已经有一个持久化的文件了，所以更改会被应用。在runtime使用<code>ScriptableObject.CreateInstance&lt;MyData&gt;()</code>创建的文件是在运行中动态创建的，特点：</p>
<ul>
<li>运行完随着进程销毁，可以被GC，相当于只是继承了<code>UnityEngine.Object</code></li>
<li>指定的泛型不会带默认值过来，ScriptableObject的构造函数是Unity内部处理的，不是普通 C# 构造函数
<ul>
<li>解决办法是在ScriptableObject的<code>OnEnable()</code>中初始化</li>
</ul>
</li>
</ul>
<details class="details custom-block"><summary>ScriptableObject实现多态简单示例</summary>
<p>criptableObject实现多态简单示例</p>
<div class="language-Csharp vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">Csharp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 声明一个抽象类AudioPlayBase，继承自ScriptableObject类</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> abstract</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> AudioPlayBase</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> : </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">ScriptableObject</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> abstract</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Play</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">AudioSource</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> source</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">CreateAssetMenu</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()]</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> RandomPlayAudio</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> : </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">AudioPlayBase</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> List</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">AudioClip</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">> </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">clips</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> override</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Play</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">AudioSource</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> source</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (clips.Count </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">==</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        int</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> randomIndex</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Random.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Range</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, clips.Count); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 随机播放其中一个</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        AudioClip</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> randomClip</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> clips[randomIndex];</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        source.clip </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> randomClip;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        source.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Play</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">CreateAssetMenu</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()]</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> PlayerAudio</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> : </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">AudioPlayBase</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> AudioClip</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> clip</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> override</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Play</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">AudioSource</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> source</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 播放单个</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        source.clip </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> clip;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        source.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Play</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> SoTest</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> : </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">MonoBehaviour</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    public</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> AudioPlayBase</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> audioPlay</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 这个就可以挂载不同类型的PlayAudio实现多态</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    private</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Start</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        audioPlay.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Play</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">this</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetComponent</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">AudioSource</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>());</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br></div></div></details>
<p>#todo ScriptableObject保存和加载 <a href="https://chatgpt.com/c/68cc23cc-24f4-8325-a6a8-c236c990b574" target="_blank" rel="noreferrer">最下面有全局的Converter可用</a><br/>
<a href="https://www.bilibili.com/video/BV15144zDExA/" target="_blank" rel="noreferrer">深入理解ScriptableObject-不只是数据容器_哔哩哔哩_bilibili</a></p>
<h3 id="操作excel" tabindex="-1">操作Excel <a class="header-anchor" href="#操作excel" aria-label="Permalink to &quot;操作Excel&quot;">&ZeroWidthSpace;</a></h3>
<p>其实就是一种文件格式，没什么新奇的，我用pandas不是天天干这个吗。<code>.xlsx</code> 本质上是一个压缩包所以需要Zip功能去解压，一般是在Editor模式下去读写Excel进行操作，所以依赖dll很多时候也会放到Editor下。<br>
使用这两个库<a href="https://www.nuget.org/packages/sharpziplib/" target="_blank" rel="noreferrer">SharpZipLib</a>；<a href="https://www.nuget.org/packages/ExcelDataReader/" target="_blank" rel="noreferrer">ExcelDataReader</a>（较新版本的需要把<code>ExcelDataReader.DataSet.dll</code> <a href="https://www.nuget.org/packages/exceldatareader.dataset/" target="_blank" rel="noreferrer">ExcelDataReader.DataSet</a>一块安装）</p>
<div class="danger custom-block"><p class="custom-block-title">[❌Failure] 啊我草ExcleDataReader怎么这么坏啊😭</p>
<p>我草ExcleDataReader怎么这么坏啊😭
这俩库自己放DLL<code>ExcelDataReader.DataSet.dll</code>死活读不出来，但是使用NugetForUnity就没问题，里面不知道做了什么不为人知的邪恶py交易，除非单文件DLLL以后尽量能少自己凑。<br/>（unity2022.3 dll3.7.0）</p>
</div>
<details class="details custom-block"><summary>Excel常用API</summary>
<p>xcel常用API</p>
<div class="language-Csharp vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">Csharp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Start</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    string</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> excelPath</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Application.streamingAssetsPath </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "/PlayerInfo.xlsx"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    FileStream</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> fileStream</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> File.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Open</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(excelPath, FileMode.Open, FileAccess.Read);</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    // xlsx 用 CreateOpenXmlReader，xls 用 CreateBinaryReader</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    IExcelDataReader</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> reader</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> ExcelReaderFactory.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">CreateOpenXmlReader</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(fileStream);</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    DataSet</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> dataSet</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> reader.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">AsDataSet</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 转成 DataSet，里面包含所有表</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">int</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> i</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x3C;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> dataSet.Tables.Count; i</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">++</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Debug.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"表名："</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> +</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> dataSet.Tables[i].TableName);  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 表名</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Debug.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"行数："</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> +</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> dataSet.Tables[i].Rows.Count);  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  行数</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Debug.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"列数："</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> +</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> dataSet.Tables[i].Columns.Count);  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//  列数</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        foreach</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">DataRow</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> row</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> in</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> dataSet.Tables[i].Rows)  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 遍历行</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            foreach</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">var</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> cell</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> in</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> row.ItemArray)  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 遍历列</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">                print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(cell.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">ToString</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">());</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    fileStream.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Dispose</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br></div></div></details>
<p>牢唐的工具类思路就是，按照既定格式读取Excel，字符串拼接生成类型CS文件；按照顺序写入二进制到bin文件；读取二进制获得类和字段名，利用反射复赋值存到单例的字典中去。</p>
<hr>
<h2 id="常见打包设置" tabindex="-1">常见打包设置 <a class="header-anchor" href="#常见打包设置" aria-label="Permalink to &quot;常见打包设置&quot;">&ZeroWidthSpace;</a></h2>
<p>关注Resolution and Presentation</p>
<ul>
<li>Fullscreen Mode
<ul>
<li>FullscreenWindow使用显示器的分辨率进行全屏显示，如果游戏分辨率低于显示器分辨率，可能会出现黑边</li>
<li>Exclusive Fullscreen 修改显示器分辨率以匹配项目,全屏</li>
<li>Maximized Window 最大化窗口</li>
<li>Windowed窗口模式</li>
</ul>
</li>
<li>Resolution
<ul>
<li>Default Is Native Resolution 使用显示器分辨率，不勾使用设置的分辨率 Windowed模式才有用</li>
<li>Default Screen Height 游戏画面默认高度，Windowed模式才有用</li>
<li>Mac Retina Support启用MacOS高DPI支持</li>
<li>Run In background程序失去焦点可以继续运行而不暂停</li>
</ul>
</li>
</ul>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Unity环境搭建]]></title>
            <link>http://ooowl.fun/blogs/Game/Unity/Unity-%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA.html</link>
            <guid isPermaLink="false">http://ooowl.fun/blogs/Game/Unity/Unity-%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA.html</guid>
            <pubDate>Wed, 28 Feb 2024 22:32:18 GMT</pubDate>
            <description><![CDATA[[📝Note] 这是我为自己做的选择。]]></description>
            <content:encoded><![CDATA[<h1 id="unity环境搭建" tabindex="-1">Unity环境搭建 <a class="header-anchor" href="#unity环境搭建" aria-label="Permalink to &quot;Unity环境搭建&quot;">&ZeroWidthSpace;</a></h1><p class="article-meta">创建于 2024年2月29日 06:32:18 · 约2,093字</p>
<div class="info custom-block"><p class="custom-block-title">[📝Note] 这是我为自己做的选择。</p>
<p>是我为自己做的选择。
白鸟白鸟不要回头望<br/>
你要替我飞去那地方<br/>
一去那地方<br/>
那是你我共同故乡<br/></p>
</div>
<p>No Game，No Life<br>
已经习惯了使用mac和jetbrains全家桶开发，这次换了新电脑也继续用吧，开箱即用不用操心真不错。<br>
基本的开发环境dotnet，git之类的都跳过了，这些太基础</p>
<h2 id="摆脱中国特供版unity" tabindex="-1">摆脱中国特供版Unity <a class="header-anchor" href="#摆脱中国特供版unity" aria-label="Permalink to &quot;摆脱中国特供版Unity&quot;">&ZeroWidthSpace;</a></h2>
<p><a href="https://www.nounitycn.top/" target="_blank" rel="noreferrer">Unity国际版下载站 - 让游戏开发更加简单</a> 类似itellyou
首先代理是必须的<br>
中国特供版会让你填手机号，不要访问unity.cn,也不要访问unity.com的中文版面，要访问英文界面的官网。<br>
然后注册你的unity帐号，找个镜像之类的下载unity hub国外的版本，不是中国特供版，不然会让你跳到国内版网站去验证。<br>
如果有已安装的UnityHub版本，先卸载，为以防万一，卸载之后删除 <code>~/AppData/Roaming</code> 这个目录下的UnityHub和Unity Hub目录。然后再安装，mac直接删除UnityHub就行</p>
<p>windows上的启动脚本为</p>
<div class="language-bat vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">bat</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">@echo</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> off</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">set</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> HTTP_PROXY</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">http://127.0.0.1:1080</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">set</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> HTTPS_PROXY</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">http://127.0.0.1:1080</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">start</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> ""</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "C:\Program Files\Unity Hub\Unity Hub.exe"</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br></div></div><p>mac的为</p>
<div class="language-sh vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#!/bin/bash</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">export</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> HTTP_PROXY</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">http://127.0.0.1:1080</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">export</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> HTTPS_PROXY</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">http://127.0.0.1:1080</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">nohup</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "/Applications/Unity Hub.app/Contents/MacOS/Unity Hub"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> &#x26;</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">/dev/null &#x26;</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br></div></div><p>原理就是先在命令行里走代理，然后启动程序就会全走命令行的代理，打开之后是不能关掉命令行的session的。<br>
如果是程序老手，平时肯定就已经挂上了，直接使用最后一句启动就行<br>
<strong>一定要使用上面的脚本启动！否则UnityHub启动时不会读取系统代理，在登陆时会跳转到<a href="https://id.unity.cn/" target="_blank" rel="noreferrer">https://id.unity.cn/</a></strong></p>
<h2 id="设置rider为编辑器" tabindex="-1">设置Rider为编辑器 <a class="header-anchor" href="#设置rider为编辑器" aria-label="Permalink to &quot;设置Rider为编辑器&quot;">&ZeroWidthSpace;</a></h2>
<p>Rider 代替 VisualStudio</p>
<ol>
<li>打开Unity项目选择：Window &gt; Package Manager &gt; 搜索 <code>Rider</code> 点击 Install（安装）</li>
<li>安装完毕后，选择 Edit &gt; Preferences &gt; External Tools &gt; 选择 External Scriot Editor 为你的Rider版本</li>
<li>若在你的 Package Manager 窗口中搜索不到 <code>JetBrains Rider Editor</code>，那么请检查 Packages 是否选择了 <code>Unity Registry</code>，选择 <code>In Project</code>就是在你自己的工程里搜索，如果你没有安装的话是搜不到的</li>
</ol>
<div class="warning custom-block"><p class="custom-block-title">[⚠️Warning] 不要直接浏览选择Rider</p>
<p>要直接浏览选择Rider
这里有坑， External Scriot Editor 的时候千万不要从你的文件目录里面选择你安装的 Rider.exe，如果不修改这个地方就一直不能把 Unity 和 Rider 联系起来！！  <br/>
因为这个版本的 Unity 本身自带了 Rider 工具，如果不修改这个地方就一直不能把 Unity 和 Rider 联系起来！！ 因为这个版本的 Unity 本身自带了 Rider 工具，官网有<a href="https://docs.unity3d.com/cn/2020.3/Manual/com.unity.ide.rider.html" target="_blank" rel="noreferrer">文章</a></p>
</div>
<p><strong>看源代码的时候使用Rider-&gt;Settings-&gt;ColorSchema-&gt;General-&gt;FoldingText 可以调整折叠代码的颜色，便于查看源代码模式。</strong> 同时把warn的斜体去掉。<br>
我把颜色调成<code>#4B576E</code>这样折叠起来的就不碍眼了，然后拉高函数定义的颜色亮度，更好查找。这样不会找影响自己写代码中折叠起来的块<br>
设置Unity中Prefence-&gt;Color-&gt;PlayMode tint为<code>#E0FDDF</code>运行模式的时候更显眼不容易忘<br>
之后双击就是在Rider中打开项目了。</p>
<h3 id="关闭自动编译" tabindex="-1">关闭自动编译 <a class="header-anchor" href="#关闭自动编译" aria-label="Permalink to &quot;关闭自动编译&quot;">&ZeroWidthSpace;</a></h3>
<p>每次修改脚本自己就编译，很卡，尤其是项目大的。<br>
Edit-&gt;Prefrence-&gt;Asset Pipeline-&gt;AutoRefersh（Disable）<br>
Settings-&gt;Languages&amp;Frameworks-&gt;Unity Engine-&gt;Automatically refresh assets in Unity取消<br>
修改完脚本之后Menu-&gt;Asset-&gt;Refersh Assetss手动刷新</p>
<p>如果脚本是有问题的，有可能进不去编辑器，打开Unity就卡死。一般打开的时候会进入安全模式，不运行用户写的托管代码，此时可以进去调整代码解决卡死。</p>
<h2 id="c-的特点" tabindex="-1">C#的特点 <a class="header-anchor" href="#c-的特点" aria-label="Permalink to &quot;C#的特点&quot;">&ZeroWidthSpace;</a></h2>
<ul>
<li>没有多重继承</li>
<li>提供了GC和内存管理</li>
<li><strong>编译</strong> 为中间代语言CIL，使用.NetFramwork虚拟机CLR Common Language Runtime通用语言运行库<strong>解释</strong>执行</li>
<li>沙币微软dotNet早期不开源，只能在windows运行，所以unity用mono把CIL直接用JIT编译成汇编运行</li>
<li>Mono是微软.Net Framework的开源实现，基于C#语言的ECMA标准，包含C#编译器和CLR</li>
<li>最开始不是开源的，但是后来开源了，dotnet库非常大，很多包是内部提供的，微软也赞助了基金会托管</li>
</ul>
<div class="tip custom-block"><p class="custom-block-title">[💡Tip] 复习一下概念</p>
<p>习一下概念
当前运行环境本地指令的提前编译（AOT就是传统理解的编译过程，编译一次就不需要再编译）或即时编译（JIT），Mono会有一部分代码通过AOT静态编译，以降低在程序运行时JIT动态编译在效率上的问题。<br/>
<strong>在iOS平台中Mono无法使用JIT引擎，而是以Full AOT模式运行的，所以此处说的即时编译不包括IOS，这也是U3D官方没有提供热更新的原因</strong> <br/>
Ahead of Time<br/>
AOT编译在应用程序执行前进行，并且通常在不同计算机上（需要运行的平台）执行，用于转换成对应平台的指令。<br/>
iOS平台是禁止使用JIT的，可Mono的AOT模式仍然会保留一部分代码会在程序运行时动态编译。<br/>
为了破解这个问题，Mono提供了一个被称为Full AOT的模式。即预先对程序集中的所有CIL代码进行AOT编译生成一个本地代码映像，然后在运行时直接加载这个映像而不再使用JIT引擎。<br/>
<strong>iOS无法dll热更新的根本原因</strong><br/>
实际上，iOS并非直接把JIT禁止了，而是IOS封了JIT内存（或者堆）的可执行权限，相当于变相的封锁了JIT这种编译方式。<sup class="footnote-ref"><a href="#fn1" id="fnref1">[1]</a></sup></p>
</div>
<div class="language-mermaid vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">mermaid</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">graph TD</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    A[C#源文件&#x3C;br/>&#x3C;运行时>]--> |C#编译器&#x3C;br/>&#x3C;运行时>| B[公共程序集 CIL 类型信息&#x3C;br/>&#x3C;运行时,编译时>]</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    C[VB源文件&#x3C;br/>&#x3C;运行时>] --> |VB.NET编译器&#x3C;br/>&#x3C;运行时>| B</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    D[Xyz.NET源文件&#x3C;br/>&#x3C;运行时>] --> |Xyz.NET编译器&#x3C;br/>&#x3C;运行时>| B</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    B --> |JIT编译器|E[公共语言运行库CLR&#x3C;br/>&#x3C;编译时>]</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    E -->  F[本机代码->操作系统服务&#x3C;br/>&#x3C;编译时>]</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br></div></div><p>dotnet不是编程语言，但它能通过<code>CLR</code>（公共语言运行库）的<code>JIT编译器</code>将<code>CIL</code>Common Intermediate Language（公共中间语言）编译成<code>本机代码</code>，<code>本机代码</code>包括<code>托管代码</code>和<code>非托管代码</code>。</p>
<ul>
<li>托管代码：为DOTNET框架编写的代码，需要CLR。</li>
<li>非托管代码：是指直接编译成目标计算机的机器码，比如<code>Win32 C/C++ DLL</code>。不在CLR控制下以运行。
本机代码可以在操作系统上执行，在执行的过程中<code>CLR</code>（公共语言运行库）会对<code>托管代码</code>进行内存管理、垃圾收集和异常处理等管理。并不是编译完就没事了</li>
</ul>
<h3 id="配置和程序集" tabindex="-1">配置和程序集 <a class="header-anchor" href="#配置和程序集" aria-label="Permalink to &quot;配置和程序集&quot;">&ZeroWidthSpace;</a></h3>
<h3 id="unity的程序集" tabindex="-1">Unity的程序集 <a class="header-anchor" href="#unity的程序集" aria-label="Permalink to &quot;Unity的程序集&quot;">&ZeroWidthSpace;</a></h3>
<ul>
<li>程序集Assembly是编译输出的.dll或.exe文件。每个程序集内部包含 类 结构体 接口 元数据 IL 等，相当于jar包可被加载、引用、反射、执行。
<ul>
<li>一个<code>.csproj</code>对应生成一个程序集，但是Unity的程序集额外由<code>.asmdef</code>控制</li>
</ul>
</li>
<li>Unity在某文件夹中创建程序集的时候，Unity会自动把该文件夹下面的所有cs文件归属到这个程序集。当修改了某个程序集的cs文件Unity编译对应的程序集就可以不用整体编译。不同程序集下的类互相引用必须要在Inspector下指明引用关系后才能使用。</li>
<li>Unity 2017.3 开始，引入了<code>AssemblyDefinition 文件(.asmdef)</code>它让你可以手动划分程序集边界，而不是所有脚本都进 Assembly-CSharp.dll。每个 .asmdef 会生成一个独立的程序集DLL。Unity 会自动在构建时生成对应的 .csproj 文件
<ul>
<li>记得如果更改了程序集的名字，除了文件名要在Inspector中Name也改掉，否则很容易找不到引用。</li>
<li>OverrideReferences 手动指定依赖的DLL，不然就全部引用上</li>
<li>RootNamespace 相当于整个自定义程序集的Namespace</li>
<li>DefineConstrains 预定义宏存在的话才会编译此DLL</li>
</ul>
</li>
<li>Unity中默认带的程序集（其实他们几个互相是有引用关系的，但是一般不用管
<ul>
<li><code>Assembly-CSharp.csproj</code> 包含所有游戏cs文件的脚本</li>
<li><code>Assembly-CSharp-Editor.csproj</code> 包含Editor文件夹下的脚本(非Plugins文件夹)</li>
<li><code>Assembly-CSharp-firstpass.csproj</code> Plugins/Standard Assets/Pro Standard Assets`下的(非Editor文件夹)</li>
<li><code>Assembly-CSharp-Editor-firstpass.csproj</code> Editor下的Plugins/Standard Assets/Pro Standard Assets文件夹</li>
<li>当使用<code>.asmdef</code>时，此<code>.asmdef</code>定义的文件夹默认规则失效。</li>
<li>放在项目里的第三方dll其优先级均低于自定义asmdef，可以在自定义asmdef中放心使用</li>
</ul>
</li>
</ul>
<h2 id="unity跨平台" tabindex="-1">Unity跨平台 <a class="header-anchor" href="#unity跨平台" aria-label="Permalink to &quot;Unity跨平台&quot;">&ZeroWidthSpace;</a></h2>
<p>Unity的C#是先编译成 CIL 然后再解释执行，跨平台本质是解释器解释执行的问题，mono都支持，CLR以JIT为主但也支持AOT，.net5+使用RyuJIT，Unity使用什么取决于平台。因为IOS封锁了JIT，所以L2CPP 会把 IL 转成 C++，再用 Clang 编译成机器码（AOT）此时传统的热更就不能用了。所以用解释器方式热更（如 xlua、tolua、ILRuntime）或者HybridCLR 这种结合 AOT 和解释器的方式做热更</p>
<p>选择自己的版本以查看<a href="https://docs.unity3d.com/2022.3/Documentation/Manual/CSharpCompiler.html" target="_blank" rel="noreferrer">Unity版本和C#版本对应特性支持</a></p>
<h3 id="零散补充" tabindex="-1">零散补充 <a class="header-anchor" href="#零散补充" aria-label="Permalink to &quot;零散补充&quot;">&ZeroWidthSpace;</a></h3>
<p>C#中没有对象的deepcopy方法，几种方法:</p>
<ul>
<li>json序列化深拷贝 适合<strong>复杂对象</strong>，不用自己写每个字段，但是 Unity的 <code>JsonUtility</code> 要求对象是<code>[Serializable]</code>，而且只支持简单字段，复杂引用类型比如 <code>Dictionary</code> 不能直接支持，也比较浪费性能</li>
<li>手动在类中实现clone方法把数据复制一份</li>
</ul>
<table tabindex="0">
<thead>
<tr>
<th><a href="https://learn.microsoft.com/en-us/dotnet/standard/design-guidelines/naming-guidelines" target="_blank" rel="noreferrer">MS推荐的代码规范</a></th>
<th>命名风格</th>
<th>示例</th>
</tr>
</thead>
<tbody>
<tr>
<td>类 / 接口 / 方法 / 属性</td>
<td>PascalCase</td>
<td><code>UserManager</code></td>
</tr>
<tr>
<td>变量 / 参数 / 字段</td>
<td>camelCase</td>
<td><code>userId</code></td>
</tr>
<tr>
<td>私有字段（有些风格）</td>
<td><code>_camelCase</code></td>
<td><code>_userName</code></td>
</tr>
</tbody>
</table>
<p>C#支持顶级语句直接写在文件里，但是全局只能有一个文件直接使用顶级语句，编译器会自动帮你生成文件同名的类和<code>Main</code>方法，<strong>只有顶级语句</strong>（如变量定义、表达式、方法调用等）会被编译器<strong>自动放进 <code>Main()</code> 方法</strong>中，<br>
<strong>类、结构、枚举、接口等声明</strong>则是<strong>正常全局作用域</strong>，<strong>不会被包含进 <code>Main</code></strong>，而是像平时一样单独存在于程序集里。</p>
<p>在Unity中复制的变量经常带个<code>m_xxx</code> 底层用 <strong>C++ 引擎 + C# 脚本</strong>，序列化时需要把对象字段保存到 <code>.prefab</code>、<code>.unity</code>、<code>.asset</code> 这类 YAML 文件里。<strong>内部引擎字段</strong>（通常是 private 或 protected）会加前缀 <code>m_</code>，表示 <strong>member field（成员变量）</strong> 于是用户可见的属性/变量就不带，序列化出来的底层字段带。</p>
<p>unity和C#中版本对应的关系，源生成器等东西</p>
<hr class="footnotes-sep">
<section class="footnotes">
<ol class="footnotes-list">
<li id="fn1" class="footnote-item"><p><a href="https://chebincarl.github.io/2019/10/19/%E4%B8%BA%E4%BB%80%E4%B9%88iOS%E6%97%A0%E6%B3%95%E5%8A%A8%E6%80%81%E5%8A%A0%E8%BD%BDDll%EF%BC%9F/" target="_blank" rel="noreferrer">为什么iOS无法动态加载Dll？ | 车斌的博客</a> <a href="#fnref1" class="footnote-backref">↩︎</a></p>
</li>
</ol>
</section>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[用户和验权]]></title>
            <link>http://ooowl.fun/blogs/Web%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/%E9%80%9A%E7%94%A8%E6%A8%A1%E5%9D%97/%E7%94%A8%E6%88%B7%E5%92%8C%E9%AA%8C%E6%9D%83.html</link>
            <guid isPermaLink="false">http://ooowl.fun/blogs/Web%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/%E9%80%9A%E7%94%A8%E6%A8%A1%E5%9D%97/%E7%94%A8%E6%88%B7%E5%92%8C%E9%AA%8C%E6%9D%83.html</guid>
            <pubDate>Wed, 11 Oct 2023 00:28:10 GMT</pubDate>
            <content:encoded><![CDATA[<h1 id="用户和验权" tabindex="-1">用户和验权 <a class="header-anchor" href="#用户和验权" aria-label="Permalink to &quot;用户和验权&quot;">&ZeroWidthSpace;</a></h1><p class="article-meta">创建于 2023年10月11日 08:28:10 · 约195字</p>
<h2 id="基础的概念" tabindex="-1">基础的概念 <a class="header-anchor" href="#基础的概念" aria-label="Permalink to &quot;基础的概念&quot;">&ZeroWidthSpace;</a></h2>
<h3 id="cookie" tabindex="-1">cookie <a class="header-anchor" href="#cookie" aria-label="Permalink to &quot;cookie&quot;">&ZeroWidthSpace;</a></h3>
<h3 id="session" tabindex="-1">session <a class="header-anchor" href="#session" aria-label="Permalink to &quot;session&quot;">&ZeroWidthSpace;</a></h3>
<h3 id="token验权" tabindex="-1">token验权 <a class="header-anchor" href="#token验权" aria-label="Permalink to &quot;token验权&quot;">&ZeroWidthSpace;</a></h3>
<h3 id="jwt验权" tabindex="-1">JWT验权 <a class="header-anchor" href="#jwt验权" aria-label="Permalink to &quot;JWT验权&quot;">&ZeroWidthSpace;</a></h3>
<h3 id="oauth2权限验证" tabindex="-1">OAuth2权限验证 <a class="header-anchor" href="#oauth2权限验证" aria-label="Permalink to &quot;OAuth2权限验证&quot;">&ZeroWidthSpace;</a></h3>
<p><a href="https://datatracker.ietf.org/doc/html/rfc6749" target="_blank" rel="noreferrer">RFC 6749 - The OAuth 2.0 Authorization Framework</a></p>
<h3 id="sso单点登录" tabindex="-1">SSO单点登录 <a class="header-anchor" href="#sso单点登录" aria-label="Permalink to &quot;SSO单点登录&quot;">&ZeroWidthSpace;</a></h3>
<div class="language-mermaid vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">mermaid</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">sequenceDiagram</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    participant 用户</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    participant A系统 as A系统(A.abc.com)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    participant SSO as SSO服务器(cas.dustin.com)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    participant B系统 as B系统(B.bcd.com)</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    用户->>A系统: 1. 用户访问地址 A.abc.com/home，想进入系统</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    A系统->>A系统: 2. 发现未登录，重定向到SSO登录页面</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    A系统->>SSO: 请求服务 A 登录</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    SSO->>A系统: 3. SSO返回服务地址</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    用户->>SSO: 4. 用户登录成功，返回SSO的登录页面</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    SSO->>A系统: 5. SSO验证通过，返回 Ticket</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    A系统->>SSO: 6. A系统使用 Ticket 校验</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    SSO->>A系统: 7. SSO校验 Ticket 成功</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    A系统->>用户: 8. 返回 A 系统登录成功页面</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    用户->>B系统: 1. 用户访问 B.bcd.com/home</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    B系统->>B系统: 2. 发现未登录，重定向到SSO登录页面</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    B系统->>SSO: 请求服务 B 登录</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    SSO->>B系统: 3. SSO返回服务地址</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    用户->>SSO: 4. 用户登录成功，返回SSO的登录页面</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    SSO->>B系统: 5. SSO验证通过，返回 Ticket</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    B系统->>SSO: 6. B系统使用 Ticket 校验</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    SSO->>B系统: 7. SSO校验 Ticket 成功</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    B系统->>用户: 8. 返回 B 系统登录成功页面</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br></div></div><p>实际上已经写过一遍单体的了，没时间整理
<a href="https://www.cnblogs.com/al6nlee/p/16860734.html#django%E7%9A%84%E5%86%85%E7%BD%AErbac%E5%85%AD%E8%A1%A8" target="_blank" rel="noreferrer">DRF访问控制(RBAC)、JWT认证 - 爱learn - 博客园</a><br/>
<a href="https://www.woshipm.com/pd/5576757.html" target="_blank" rel="noreferrer">万字长文：深入浅出RBAC权限设计 | 人人都是产品经理</a><br/>
<a href="https://zhuanlan.zhihu.com/p/63769951" target="_blank" rel="noreferrer">RBAC权限设计</a><br/>
<a href="https://www.cnblogs.com/bossma/p/15812037.html" target="_blank" rel="noreferrer">手机验证码登录原理、风险和应对策略 - 萤火架构 - 博客园</a><br/>
<a href="https://blog.csdn.net/seoyundu/article/details/91139075/" target="_blank" rel="noreferrer">单点登录SSO、OAuth、LDAP、CAS的流程与应用_ldap oauth-CSDN博客</a><br/>
<a href="https://www.cnblogs.com/sandaman2019/p/15076108.html" target="_blank" rel="noreferrer">Fetching Title#8oec</a>
【Cookie、Session、Token、JWT一次性讲完-哔哩哔哩】 <a href="https://b23.tv/MOwQGTK" target="_blank" rel="noreferrer">https://b23.tv/MOwQGTK</a>
<a href="https://casbin.org/zh/" target="_blank" rel="noreferrer">Casbin</a><br/>
<a href="https://www.jianshu.com/p/ce0944b4a903" target="_blank" rel="noreferrer">权限系统设计模型分析（DAC，MAC，RBAC，ABAC） - 简书</a></p>
<p>无密码登录
Passkeys（通行密钥）/ FIDO2 (WebAuthn)</p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>理论上登录应该走oauth，客户端生成ed25519公钥私钥，然后把公钥+用户信息+设备信息注册到服务器上每次登陆的时候服务器下发一个challenge，客户端用私钥对challenge签名发给服务器服务器公钥验签+比对设备信息是否一致通过后下发短token用于后续请求流程我要比对三个，客户端传来的challenge、签名还有设备信息</span></span>
<span class="line"><span>win有credential manager</span></span>
<span class="line"><span>安卓我记得叫keystore</span></span>
<span class="line"><span>iOS叫keychain</span></span>
<span class="line"><span></span></span>
<span class="line"><span>给我一个好的登录方案</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br></div></div><p>验权
通用模板
基础设施</p>
<p>#todo
验证码注册和限流</p>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[异步任务模块]]></title>
            <link>http://ooowl.fun/blogs/Web%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/%E9%80%9A%E7%94%A8%E6%A8%A1%E5%9D%97/%E5%BC%82%E6%AD%A5%E4%BB%BB%E5%8A%A1%E6%A8%A1%E5%9D%97.html</link>
            <guid isPermaLink="false">http://ooowl.fun/blogs/Web%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/%E9%80%9A%E7%94%A8%E6%A8%A1%E5%9D%97/%E5%BC%82%E6%AD%A5%E4%BB%BB%E5%8A%A1%E6%A8%A1%E5%9D%97.html</guid>
            <pubDate>Wed, 11 Oct 2023 00:27:58 GMT</pubDate>
            <content:encoded><![CDATA[<h1 id="异步任务模块" tabindex="-1">异步任务模块 <a class="header-anchor" href="#异步任务模块" aria-label="Permalink to &quot;异步任务模块&quot;">&ZeroWidthSpace;</a></h1><p class="article-meta">创建于 2023年10月11日 08:27:58 · 约263字</p>
<h2 id="概述" tabindex="-1">概述 <a class="header-anchor" href="#概述" aria-label="Permalink to &quot;概述&quot;">&ZeroWidthSpace;</a></h2>
<p>异步任务执行中心也是一个常见的模块，不同规模的设计也不太一样，这里我参考的是大搜车的，但是他们是分布式大的任务中心，我是按照单体做的缩减了一些东西，但是可以提供一个思路。</p>
<ul>
<li>任务持久化，使用redis作为存储中间件</li>
<li>集成fastapi，使用APScheduler</li>
<li>可以动态地添加执行器</li>
<li>合理的任务分配负载</li>
<li>重试机制，超时机制，可以自己配置超时时间和重试次数</li>
<li>日志格式规定</li>
<li>状态管理，规定状态码空间</li>
<li>幂等性支持</li>
<li>任务唯一ID支持</li>
<li>任务状态管理，提供管理后台</li>
<li>屏蔽掉实现细节，API友好</li>
<li>代码执行错误上报，任务执行错误打到日志里</li>
</ul>
<p><a href="https://www.cnblogs.com/JentZhang/p/17684914.html" target="_blank" rel="noreferrer">FastAPI如何集成celery实现定时任务和异步任务并且使用docker-compose部署 - JentZhang - 博客园</a></p>
<p><a href="https://www.bilibili.com/video/BV1TD421u7S7/" target="_blank" rel="noreferrer">新系统设计(五) Design Task Scheduler_哔哩哔哩_bilibili</a></p>
<h2 id="异步消息推送" tabindex="-1">异步消息推送 <a class="header-anchor" href="#异步消息推送" aria-label="Permalink to &quot;异步消息推送&quot;">&ZeroWidthSpace;</a></h2>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[通用数据库执行器]]></title>
            <link>http://ooowl.fun/blogs/Web%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/%E9%80%9A%E7%94%A8%E6%A8%A1%E5%9D%97/%E9%80%9A%E7%94%A8%E6%95%B0%E6%8D%AE%E5%BA%93%E6%89%A7%E8%A1%8C%E5%99%A8.html</link>
            <guid isPermaLink="false">http://ooowl.fun/blogs/Web%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/%E9%80%9A%E7%94%A8%E6%A8%A1%E5%9D%97/%E9%80%9A%E7%94%A8%E6%95%B0%E6%8D%AE%E5%BA%93%E6%89%A7%E8%A1%8C%E5%99%A8.html</guid>
            <pubDate>Wed, 11 Oct 2023 00:27:49 GMT</pubDate>
            <content:encoded><![CDATA[<h1 id="通用数据库执行器" tabindex="-1">通用数据库执行器 <a class="header-anchor" href="#通用数据库执行器" aria-label="Permalink to &quot;通用数据库执行器&quot;">&ZeroWidthSpace;</a></h1><p class="article-meta">创建于 2023年10月11日 08:27:49 · 约308字</p>
<h2 id="概述" tabindex="-1">概述 <a class="header-anchor" href="#概述" aria-label="Permalink to &quot;概述&quot;">&ZeroWidthSpace;</a></h2>
<p>现在项目中需要一个统一的执行器，输入对应的数据库信息和sql语句，就可以获得session并且在指定的数据库上执行。这样就可以执行非orm绑定的数据库了<br>
首先从以下几个角度考虑</p>
<ol>
<li><strong>数据库支持</strong>:<br>
暂时只有pg用到，其他的用到了再说</li>
<li><strong>连接管理</strong>:<br>
单例模式使用sqlalchemy的session池</li>
<li><strong>安全性</strong>:<br>
内部使用，凭证访问</li>
<li><strong>错误处理</strong>:<br>
暂时先不考虑</li>
<li><strong>查询语法检查</strong>:<br>
使用sqlparse库做简单的语法格式检查</li>
<li><strong>查询结果的格式化</strong>:<br>
查询类的可以使用pandas查询然后json格式化返回结果<br>
其他的返回执行后的响应就可以了</li>
<li><strong>执行器接口设计</strong>:<br>
最主要的就是两个，凭证以及语句</li>
<li><strong>监控和日志</strong>:<br>
使用日志模块打日志，执行状态直接通过查看指定类型的日志来确定，返回查询的结果</li>
<li><strong>限流和性能</strong>:<br>
限制查询时超时30s，也可以自己传入</li>
</ol>
<p>先写一个函数，然后有时间了再来构思</p>
<h2 id="结构" tabindex="-1">结构 <a class="header-anchor" href="#结构" aria-label="Permalink to &quot;结构&quot;">&ZeroWidthSpace;</a></h2>
<h2 id="使用" tabindex="-1">使用 <a class="header-anchor" href="#使用" aria-label="Permalink to &quot;使用&quot;">&ZeroWidthSpace;</a></h2>
<h2 id="其他" tabindex="-1">其他 <a class="header-anchor" href="#其他" aria-label="Permalink to &quot;其他&quot;">&ZeroWidthSpace;</a></h2>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[日志模块设计]]></title>
            <link>http://ooowl.fun/blogs/Web%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/%E9%80%9A%E7%94%A8%E6%A8%A1%E5%9D%97/%E6%97%A5%E5%BF%97%E6%A8%A1%E5%9D%97%E8%AE%BE%E8%AE%A1.html</link>
            <guid isPermaLink="false">http://ooowl.fun/blogs/Web%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/%E9%80%9A%E7%94%A8%E6%A8%A1%E5%9D%97/%E6%97%A5%E5%BF%97%E6%A8%A1%E5%9D%97%E8%AE%BE%E8%AE%A1.html</guid>
            <pubDate>Wed, 11 Oct 2023 00:26:57 GMT</pubDate>
            <content:encoded><![CDATA[<h1 id="日志模块设计" tabindex="-1">日志模块设计 <a class="header-anchor" href="#日志模块设计" aria-label="Permalink to &quot;日志模块设计&quot;">&ZeroWidthSpace;</a></h1><p class="article-meta">创建于 2023年10月11日 08:26:57 · 约741字</p>
<h2 id="模块说明" tabindex="-1">模块说明 <a class="header-anchor" href="#模块说明" aria-label="Permalink to &quot;模块说明&quot;">&ZeroWidthSpace;</a></h2>
<p>此模块使用的是责任链模式和简单工厂,注册即可用，主要用来监控所有的请求和日常项目中的日志打印。</p>
<p>系统日志中记录了请求的头，参数响应，请求的信息等，每个请求都有唯一ID;手动日志中记录了请求方法ip地址，有唯一ID可以关联系统日志查询<br>
模块记录参数和响应只记录JSON格式的，其他的不做记录</p>
<p>日志的查询模块可以单独写，模块可能损耗性能的地方在于响应序列化和反序列化，生成uuid，以及pipline的处理。<br>
如果pipline性能瓶颈可以将pipline都关闭，然后写一个队列pipline把数据放MQ使用worker处理</p>
<p>日志目录</p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>.</span></span>
<span class="line"><span>├── README.md</span></span>
<span class="line"><span>├── __init__.py</span></span>
<span class="line"><span>├── custom_logger.py</span></span>
<span class="line"><span>├── logpiplines</span></span>
<span class="line"><span>│   ├── __init__.py</span></span>
<span class="line"><span>│   ├── logs</span></span>
<span class="line"><span>│   │   ├── manual_65844_log.log</span></span>
<span class="line"><span>│   │   └── system_65844_log.log</span></span>
<span class="line"><span>│   ├── sql_pipline.py</span></span>
<span class="line"><span>│   └── std_out_pipline.py</span></span>
<span class="line"><span>├── middleware_reg.py</span></span>
<span class="line"><span>└── persistence.py</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br></div></div><p><strong>目前还没有错误日志采集</strong></p>
<h2 id="日志模块用法" tabindex="-1">日志模块用法 <a class="header-anchor" href="#日志模块用法" aria-label="Permalink to &quot;日志模块用法&quot;">&ZeroWidthSpace;</a></h2>
<ol>
<li>模块引入之后，先在app中注册中间件</li>
</ol>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> app.logcollection </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> CustomMiddleware </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 注意包路径</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">app.add_middleware(CustomMiddleware)</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br></div></div><ol start="2">
<li>使用的时候在logpiplines文件夹下创建python文件，像下面所说实现Handler类即可自动引入调用。
默认已经使用loguru实现的是系统日志和手动日志打印控制台以及单个文件(logs文件夹，也可以手动指定LOGFILEPATH 应该是WORKDIR的相对路径，注意)，以及注释起来的，让手动日志分模块写入<br>
在模块中使用<code>from app.logcollection import logger</code> 调用logger对象的方法即可打印手动日志</li>
<li>日志分两类:
<ul>
<li>系统日志</li>
</ul>
</li>
</ol>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">       logobj </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"level"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"INFO"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 固定INFO</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">                 "logtype"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Inbound"</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> or</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "Outbound"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">                 "request_id"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: uuid4:</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">str</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">                 "url"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: 字符串,</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">                 "req_path"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:请求路径,</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">                 "client_ipport"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"127.0.0.1:80"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 请求者ip端口</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">                 "http_method"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: 此次请求的方法,</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">                 "logtime"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: datetime.now(),</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">                 "timeconsume"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: 请求耗时 Inbound为None,</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">                 "response_data"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:response_data, </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 响应数据 Inbound为None</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">                 "path_params"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:path_params, </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 路径参数</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">                 "query_params"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:query_params, </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 关键字参数</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">                 "request_body"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:body_json </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 携带的请求体，默认就{}</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">                 }</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br></div></div><ul>
<li>手动日志</li>
</ul>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        logobj </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"level"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: CustomLogger中规定[</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"DEBUG"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"INFO"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"WARNING"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"ERROR"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"CRITICAL"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">], </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">                  "logtype"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Manual"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">                  "logtime"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: datetime.now()  ,</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">                  "message"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: 字符串, </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">                  "extra_data"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: 任意字典,</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">                  "request_id"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: uuid4:</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">str</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">                  "url"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: 字符串,</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">                  "req_path"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:请求路径,</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">                  "client_ipport"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"127.0.0.1:80"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 请求者ip端口</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">                  "http_method"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: 此次请求的方法</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">                  }</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br></div></div><p>对应Handler分两个，一类是ManualLogHandler,SystemLogHandler,继承了哪个Handler就会加入责任链处理对应type的日志</p>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> ..persistence </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> log_persister, ManualLogHandler, SystemLogHandler</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">@log_persister</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  # 用这个装饰器装饰</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> InfoHandler</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">ManualLogHandler</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">):  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 继承Handler类</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __init__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self):</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">       super</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">().</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">__init__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 指定pipline的处理优先级，不定义此方法默认都是-1随机，越大越早处理</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> process</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self, message):  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 必须实现的实现处理函数</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">f</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"日志对象为: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">{</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">message</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">}</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br></div></div><ol start="4">
<li>如果在PIPLINE中使用loguru全局的sink是共享的，一定要注意，也就是如果你原先有loguru在处理，可能导致写入乱七八糟的日志</li>
<li>日志模块的uuid功能是使用ContextVar实现，这个模块只在py3.7以上内置，并且在一些上下文被切换掉的情况下不能用
<ul>
<li>在多线程环境中运行异步代码,如果你使用多线程库（例如，concurrent.futures.ThreadPoolExecutor）在一个独立的线程中运行代码，这段代码是无法访问在主线程（处理 HTTP 请求的线程）中设置的 ContextVar 变量的。</li>
<li>使用外部系统的回调,比如MQ的时候</li>
<li>在不同的事件循环或不同的 Task 中，如果你创建一个与请求处理完全解耦的新任务（例如，使用 asyncio.create_task()），那么这个任务就不会自动继承当前请求的 ContextVar 变量。</li>
<li>理论上来说可以在async和非asyncAPI中混着用，但是一般async方法是用来执行后台任务的，时间过长ID会被其他的请求重置，<strong>所以使用logger的get_request_var获得变量手动方法传递到handler处理</strong></li>
</ul>
</li>
</ol>
<h2 id="模块开发者" tabindex="-1">模块开发者 <a class="header-anchor" href="#模块开发者" aria-label="Permalink to &quot;模块开发者&quot;">&ZeroWidthSpace;</a></h2>
<ul>
<li>jack <s>and his miku</s></li>
</ul>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[README]]></title>
            <link>http://ooowl.fun/blogs/Web%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/%E9%80%9A%E7%94%A8%E6%A8%A1%E5%9D%97/README.html</link>
            <guid isPermaLink="false">http://ooowl.fun/blogs/Web%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/%E9%80%9A%E7%94%A8%E6%A8%A1%E5%9D%97/README.html</guid>
            <pubDate>Tue, 10 Oct 2023 21:08:13 GMT</pubDate>
            <content:encoded><![CDATA[<h1 id="readme" tabindex="-1">README <a class="header-anchor" href="#readme" aria-label="Permalink to &quot;README&quot;">&ZeroWidthSpace;</a></h1><p class="article-meta">创建于 2023年10月11日 05:08:13 · 约380字</p>
<p>大致说一下这系列是干什么的。<br>
设计一个系统，有结合业务进行设计的地方也有通用的模块，比如绝大部分的系统都会有的用户和权限模块IAM(Identity and Access Management)，异步任务中心，日志等等。<br>
虽然不同规模的系统，同样的模块设计也不相同，现在我心里也没有一个合适的标准，大致就按照自己经验来划分吧，现在是为了适应这个项目，暂时就照这个规模的做。</p>
<h2 id="常见指标" tabindex="-1">常见指标 <a class="header-anchor" href="#常见指标" aria-label="Permalink to &quot;常见指标&quot;">&ZeroWidthSpace;</a></h2>
<p><a href="https://help.adjust.com/zh/article/understanding-dau-wau-and-mau-metrics" target="_blank" rel="noreferrer">Understanding DAU, WAU &amp; MAU metrics | Adjust Help Center</a></p>
<h2 id="一些生产规范" tabindex="-1">一些生产规范 <a class="header-anchor" href="#一些生产规范" aria-label="Permalink to &quot;一些生产规范&quot;">&ZeroWidthSpace;</a></h2>
<h3 id="配置写入环境变量" tabindex="-1">配置写入环境变量 <a class="header-anchor" href="#配置写入环境变量" aria-label="Permalink to &quot;配置写入环境变量&quot;">&ZeroWidthSpace;</a></h3>
<p>配置文件最好写入环境变量，环境变量通常存储在系统级别的配置文件中，并且这些文件的访问权限受到严格控制。这样可以防止敏感信息（如数据库密码、API 密钥）被泄露或被不当访问。可以将配置和代码分离开来。这意味着在不同的环境中（开发、测试、生产），可以使用不同的配置，而无需更改代码。环境变量可以在运行时动态改变，而无需重新部署应用。例如，可以在不停止应用的情况下更新某些配置信息。在大多数编程语言和框架中，<code>dotenv</code> 都有相应的库或包。</p>
<div class="language-txt vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">txt</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span># pip install python-dotenv</span></span>
<span class="line"><span></span></span>
<span class="line"><span></span></span>
<span class="line"><span>import os</span></span>
<span class="line"><span>from dotenv import load_dotenv</span></span>
<span class="line"><span></span></span>
<span class="line"><span># 加载 .env 文件</span></span>
<span class="line"><span>load_dotenv()</span></span>
<span class="line"><span></span></span>
<span class="line"><span># 读取环境变量</span></span>
<span class="line"><span>database_url = os.getenv('DATABASE_URL')</span></span>
<span class="line"><span>debug_mode = os.getenv('DEBUG')</span></span>
<span class="line"><span>secret_key = os.getenv('SECRET_KEY')</span></span>
<span class="line"><span></span></span>
<span class="line"><span>print("Database URL:", database_url)</span></span>
<span class="line"><span>print("Debug mode:", debug_mode)</span></span>
<span class="line"><span>print("Secret Key:", secret_key)</span></span>
<span class="line"><span></span></span>
<span class="line"><span>```txt</span></span>
<span class="line"><span></span></span>
<span class="line"><span>放在读取env的同级目录下</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br></div></div><p>my_project/
├── .env
├── main.py # 在这里(workdir)读取
├── requirements.txt
└── README.md</p>
<p>DATABASE_URL=postgresql://user:password@localhost:5432/mydatabase
DEBUG=True
SECRET_KEY=mysecretkey</p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span></span></span>
<span class="line"><span></span></span>
<span class="line"><span>订单线程安全状态机</span></span>
<span class="line"><span>假删</span></span>
<span class="line"><span>多租户</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br></div></div>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[mongodb]]></title>
            <link>http://ooowl.fun/blogs/Web%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/%E5%AD%98%E5%82%A8%E6%8A%80%E6%9C%AF/Mongodb.html</link>
            <guid isPermaLink="false">http://ooowl.fun/blogs/Web%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/%E5%AD%98%E5%82%A8%E6%8A%80%E6%9C%AF/Mongodb.html</guid>
            <pubDate>Fri, 15 Sep 2023 16:19:59 GMT</pubDate>
            <content:encoded><![CDATA[<h1 id="mongodb" tabindex="-1">mongodb <a class="header-anchor" href="#mongodb" aria-label="Permalink to &quot;mongodb&quot;">&ZeroWidthSpace;</a></h1><p class="article-meta">创建于 2023年9月16日 00:19:59 · 约56字</p>
<h2 id="mongo" tabindex="-1">mongo <a class="header-anchor" href="#mongo" aria-label="Permalink to &quot;mongo&quot;">&ZeroWidthSpace;</a></h2>
<p><a href="https://mp.weixin.qq.com/s/rvUevw1n89VUrW_uK-sZHw" target="_blank" rel="noreferrer">https://mp.weixin.qq.com/s/rvUevw1n89VUrW_uK-sZHw</a></p>
<p><a href="https://www.cnblogs.com/poloyy/category/1981545.html" target="_blank" rel="noreferrer">测试高级进阶技能系列 - MongoDB - 随笔分类 - 小菠萝测试笔记 - 博客园</a></p>
<p>mongodb 5 之后需要AVX指令集，在某些老的CPU，虚拟机等地方可能会无法启动</p>
<h2 id="polodb" tabindex="-1">polodb <a class="header-anchor" href="#polodb" aria-label="Permalink to &quot;polodb&quot;">&ZeroWidthSpace;</a></h2>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[minio对象存储]]></title>
            <link>http://ooowl.fun/blogs/Web%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/%E9%98%9F%E5%88%97%E5%92%8C%E5%AF%B9%E8%B1%A1%E5%AD%98%E5%82%A8/Minio%E5%AF%B9%E8%B1%A1%E5%AD%98%E5%82%A8.html</link>
            <guid isPermaLink="false">http://ooowl.fun/blogs/Web%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/%E9%98%9F%E5%88%97%E5%92%8C%E5%AF%B9%E8%B1%A1%E5%AD%98%E5%82%A8/Minio%E5%AF%B9%E8%B1%A1%E5%AD%98%E5%82%A8.html</guid>
            <pubDate>Fri, 15 Sep 2023 16:16:32 GMT</pubDate>
            <content:encoded><![CDATA[<h1 id="minio对象存储" tabindex="-1">minio对象存储 <a class="header-anchor" href="#minio对象存储" aria-label="Permalink to &quot;minio对象存储&quot;">&ZeroWidthSpace;</a></h1><p class="article-meta">创建于 2023年9月16日 00:16:32 · 约1,454字</p>
<h2 id="基本使用" tabindex="-1">基本使用 <a class="header-anchor" href="#基本使用" aria-label="Permalink to &quot;基本使用&quot;">&ZeroWidthSpace;</a></h2>
<h3 id="应用场景" tabindex="-1">应用场景 <a class="header-anchor" href="#应用场景" aria-label="Permalink to &quot;应用场景&quot;">&ZeroWidthSpace;</a></h3>
<p>一个亚马逊S3的云存储接口，适合存储非结构化数据，支持TB级别的对象存储OSS<sup class="footnote-ref"><a href="#fn1" id="fnref1">[1]</a></sup><br>
<a href="https://min.io/docs/minio/container/index.html" target="_blank" rel="noreferrer">文档在这里</a>，尽量参考英文网站，中文网站更新不是很及时，有可能版本不对导致错误<br>
<a href="https://help.aliyun.com/zh/oss/" target="_blank" rel="noreferrer">对象存储 OSS-阿里云帮助中心</a> 关于OSS的概念<br>
<a href="https://java.isture.com/arch/minio/minio-oos-overview.html" target="_blank" rel="noreferrer">Minio基础 - 对象存储OSS概述 | Java学习笔记</a></p>
<p>::: note [💬Quote]
Minio使用纠删码erasure code和校验和checksum来保护数据免受硬件故障和无声数据损坏。 即便您丢失一半数量（N/2）的硬盘，您仍然可以恢复数据。纠删码是一种恢复丢失和损坏数据的数学算法， Minio采用Reed-Solomon code将对象拆分成N/2数据和N/2 奇偶校验块。 这就意味着如果是12块盘，一个对象会被分成6个数据块、6个奇偶校验块，你可以丢失任意6块盘（不管其是存放的数据块还是奇偶校验块），你仍可以从剩下的盘中的数据进行恢复。
:::</p>
<h3 id="结构" tabindex="-1">结构 <a class="header-anchor" href="#结构" aria-label="Permalink to &quot;结构&quot;">&ZeroWidthSpace;</a></h3>
<p>Bucket是顶层的单元，所有的操作都是在Bucket中进行的，Bucket里面有东西是删不掉的，可以强制递归删除，在Bucket中存储的是Object<br>
Object可以是文件字节流等等任何东西。Drive是使用的磁盘，可以在启动的时候指定多块磁盘映射进去。<br>
Set算是一组磁盘的集合，当使用分布式的存储使用了很多块磁盘的时候， minio会自动分组，Set中包含几个几个磁盘是根据集群规模自动计算的，一个Set的Drive会尽量分布在不同的节点上。在使用多块盘的时候会自动启用纠删码模式，1M以下不会生成part</p>
<p>多节点部署，分布式部署的时候可以防止宕机和位腐化bit rot，至少需要4个硬盘。</p>
<p><strong>高可用:</strong>
单机Minio服务存在单点故障，相反，如果是一个有N块硬盘的分布式Minio，只要有N／2硬盘在线，你的数据就是安全的。不过你需要至少有N／2＋1个硬盘来创建新的对象。例如，一个16节点的Minio集群，每个节点16块硬盘，就算8台服務器宕机，这个集群仍然是可读的，不过你需要9台服務器才能写数据。Minio在分布式和单机模式下，所有读写操作都严格遵守 read-after-write 一致性模型。 #todo 查查这个模型</p>
<p>==分布式minio的时间节点时间差不能超过3s！！！==太细了，而且要映射的盘里面必须没有数据，所有节点必须要有相同的 <code>ACCESS_KEY</code> <code>SECRET KEY</code> or? <code>MINIO_ROOT_USER</code>和<code>MINIO_ROOT_PASSWORD</code><br>
如果是分布式多节点的部署，需要使用Nginx做负载均衡做入口，控制台用其中一个就行了，上传用负载均衡的ip-hash</p>
<div class="tip custom-block"><p class="custom-block-title">[💡Tip]</p>
<p>如果我们在minio 启动的数据目录中直接创建文件夹，就会直接暴露为s3 bucket，比较适合的场景是系统部署的时候<br>
需要依赖一个s3 bucket，我们可以直接先创建好<br>
如果是使用volume那就使用脚本提前创建
单机版存在这样一个问题如果一个文件夹 a/下面有多个object(100万个全放 a/下面)，list 性能会非常低，单机版似乎是以源文件方式直接存到磁盘的。<br>
建议不要放太多的 object ，应该分开放。比如以日期，或者文件 hash 取几位建目录再把 object 放进去。</p>
</div>
<p>创建bucket的元数据操作：对于Erasure Set(2+2)为例：创建一个bucket，对应底层文件系统的4次目录创建。创建一个文件，需要对应底层4次目录创建，8次文件创建操作。对于小文件，数据和元数据都保存在meta文件中，也需要4次文件创建操作。<strong>由此可知，minio对应大量小文件的性能非常差。</strong></p>
<p>ceph</p>
<h3 id="用户和权限" tabindex="-1">用户和权限 <a class="header-anchor" href="#用户和权限" aria-label="Permalink to &quot;用户和权限&quot;">&ZeroWidthSpace;</a></h3>
<p>#todo 前面的区域，以后再来探索吧</p>
<h3 id="docker部署" tabindex="-1">docker部署 <a class="header-anchor" href="#docker部署" aria-label="Permalink to &quot;docker部署&quot;">&ZeroWidthSpace;</a></h3>
<p>单机版直接一条命令</p>
<div class="language-bash vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">docker</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> run</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -d</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> \</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">   -p</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 9000:9000</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> \</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">   -p</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 9001:9001</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> \</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">   --name</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> minio</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> \</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">   -v</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> ~/minio/data:/data</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> \</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">   -e</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "MINIO_ROOT_USER=ROOTNAME"</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> \</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">   -e</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "MINIO_ROOT_PASSWORD=CHANGEME123"</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> \</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">   quay.io/minio/minio</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> server</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> /data</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> --console-address</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> ":9001"</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br></div></div><p>官方给的集群compose</p>
<details class="details custom-block"><summary>Click to see more</summary>
<p>nginx的配置</p>
<div class="language-bash vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">user</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> root</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">worker_processes</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> auto</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">pid</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> /run/nginx.pid</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">events</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> {</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">   worker_connections</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 16384</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">http</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> {</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    # 基础配置我就不写了</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    upstream</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> minio</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> {</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        server</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> minio1:9000</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        server</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> minio2:9000</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        server</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> minio3:9000</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        server</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> minio4:9000</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    upstream</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> console</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> {</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        ip_hash</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        server</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> minio1:9001</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        server</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> minio2:9001</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        server</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> minio3:9001</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        server</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> minio4:9001</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    server</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> {</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        listen</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">       9000</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        listen</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  [::]:9000;  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        server_name</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">  localhost</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        # To allow special characters in headers  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        ignore_invalid_headers</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> off</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        # Allow any size file to be uploaded.  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        # Set to a value such as 1000m; to restrict file size to a specific value    client_max_body_size 0;  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        # To disable buffering  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        proxy_buffering</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> off</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        proxy_request_buffering</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> off</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        location</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> /</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> {</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">            proxy_set_header</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> Host</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> $http_host;  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">            proxy_set_header</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> X-Real-IP</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> $remote_addr;  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">            proxy_set_header</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> X-Forwarded-For</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> $proxy_add_x_forwarded_for;  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">            proxy_set_header</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> X-Forwarded-Proto</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> $scheme;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">            proxy_connect_timeout</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 300</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">            # Default is HTTP/1, keepalive is only enabled in HTTP/1.1  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">            proxy_http_version</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1.1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">            proxy_set_header</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> Connection</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> ""</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">            chunked_transfer_encoding</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> off</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">            proxy_pass</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> http://minio</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        }  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    server</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> {</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        listen</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">       9001</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        listen</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  [::]:9001;  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        server_name</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">  localhost</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        # To allow special characters in headers  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        ignore_invalid_headers</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> off</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        # Allow any size file to be uploaded.  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        # Set to a value such as 1000m; to restrict file size to a specific value    client_max_body_size 0;  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        # To disable buffering  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        proxy_buffering</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> off</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        proxy_request_buffering</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> off</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        location</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> /</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> {</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">            proxy_set_header</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> Host</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> $http_host;  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">            proxy_set_header</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> X-Real-IP</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> $remote_addr;  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">            proxy_set_header</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> X-Forwarded-For</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> $proxy_add_x_forwarded_for;  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">            proxy_set_header</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> X-Forwarded-Proto</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> $scheme;  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">            proxy_set_header</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> X-NginX-Proxy</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">            # This is necessary to pass the correct IP to be hashed  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">            real_ip_header</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> X-Real-IP</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">            proxy_connect_timeout</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 300</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">            # To support websocket  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">            proxy_http_version</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1.1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">            proxy_set_header</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> Upgrade</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> $http_upgrade;  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">            proxy_set_header</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> Connection</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "upgrade"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">            chunked_transfer_encoding</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> off</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">            proxy_pass</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> http://console</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        }  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br><span class="line-number">50</span><br><span class="line-number">51</span><br><span class="line-number">52</span><br><span class="line-number">53</span><br><span class="line-number">54</span><br><span class="line-number">55</span><br><span class="line-number">56</span><br><span class="line-number">57</span><br><span class="line-number">58</span><br><span class="line-number">59</span><br><span class="line-number">60</span><br><span class="line-number">61</span><br><span class="line-number">62</span><br><span class="line-number">63</span><br><span class="line-number">64</span><br><span class="line-number">65</span><br><span class="line-number">66</span><br><span class="line-number">67</span><br><span class="line-number">68</span><br><span class="line-number">69</span><br><span class="line-number">70</span><br><span class="line-number">71</span><br><span class="line-number">72</span><br><span class="line-number">73</span><br><span class="line-number">74</span><br><span class="line-number">75</span><br><span class="line-number">76</span><br><span class="line-number">77</span><br><span class="line-number">78</span><br><span class="line-number">79</span><br><span class="line-number">80</span><br><span class="line-number">81</span><br><span class="line-number">82</span><br><span class="line-number">83</span><br><span class="line-number">84</span><br><span class="line-number">85</span><br><span class="line-number">86</span><br><span class="line-number">87</span><br><span class="line-number">88</span><br><span class="line-number">89</span><br></div></div><p>docker-compose文件</p>
<div class="language-yaml vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">yaml</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">version</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"3.8"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">x-minio-common</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x26;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">minio-common</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">  image</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">quay.io/minio/minio:latest</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">  command</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">server --console-address ":9001" http://minio{1...4}/data{1...2}</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">  expose</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    - </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"9000"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    - </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"9001"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">  environment</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">    MINIO_ROOT_USER</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">minioadmin</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">    MINIO_ROOT_PASSWORD</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">minioadmin</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">  healthcheck</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">    test</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: [</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"CMD"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"curl"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"-f"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"http://localhost:9000/minio/health/live"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]  </span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">    interval</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">30s</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">    timeout</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">20s</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">    retries</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">services</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">  minio1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    &#x3C;&#x3C;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">minio-common  </span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">    hostname</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">minio1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">    volumes</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      - </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">data1-1:/data1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      - </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">data1-2:/data2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">  minio2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    &#x3C;&#x3C;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">minio-common  </span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">    hostname</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">minio2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">    volumes</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      - </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">data2-1:/data1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      - </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">data2-2:/data2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">  minio3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    &#x3C;&#x3C;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">minio-common  </span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">    hostname</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">minio3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">    volumes</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      - </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">data3-1:/data1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      - </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">data3-2:/data2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">  minio4</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    &#x3C;&#x3C;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">minio-common  </span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">    hostname</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">minio4</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">    volumes</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      - </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">data4-1:/data1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      - </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">data4-2:/data2</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br></div></div></details>
<h3 id="版本控制" tabindex="-1">版本控制 <a class="header-anchor" href="#版本控制" aria-label="Permalink to &quot;版本控制&quot;">&ZeroWidthSpace;</a></h3>
<p>#todo 前面的区域，以后再来探索吧</p>
<h2 id="sdk和上传下载" tabindex="-1">SDK和上传下载 <a class="header-anchor" href="#sdk和上传下载" aria-label="Permalink to &quot;SDK和上传下载&quot;">&ZeroWidthSpace;</a></h2>
<h3 id="常用上传下载" tabindex="-1">常用上传下载 <a class="header-anchor" href="#常用上传下载" aria-label="Permalink to &quot;常用上传下载&quot;">&ZeroWidthSpace;</a></h3>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">MINIO_ENDPOINT</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "192.168.123.175:9000"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">MINIO_ACCESS_KEY</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "ROOTNAME"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">MINIO_SECRET_KEY</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "CHANGEME123"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">BUCKET_NAME</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "demo"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">minioClient </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Minio(  </span></span>
<span class="line"><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">    endpoint</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">MINIO_ENDPOINT</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,  </span></span>
<span class="line"><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">    access_key</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">MINIO_ACCESS_KEY</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,  </span></span>
<span class="line"><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">    secret_key</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">MINIO_SECRET_KEY</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,  </span></span>
<span class="line"><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">    secure</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">False</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 根据你的MinIO服务器配置选择是否启用安全连接  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> put_data_minio</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">():  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    f </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> open</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"sql基础知识.pdf"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">mode</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"rb"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    filename </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "sql基础知识.pdf"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    content </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> f.read()  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 这里是字节数据  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    result </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> minioClient.put_object(  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        BUCKET_NAME</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        filename,  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        io.BytesIO(content),  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 这里是字节数据  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        len</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(content),  </span></span>
<span class="line"><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">        content_type</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"application/octet-stream"</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  # 这个头是做什么的  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    )  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(result)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    f.close()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> load_data_minio</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">():  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    data </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> minioClient.get_object(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">BUCKET_NAME</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"sql基础知识.pdf"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    with</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> open</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"sql基础知识1.pdf"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'wb'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">as</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> file_data:  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> d </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> data.stream(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">32</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> *</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1024</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">):  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            file_data.write(d)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> data.data  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">put_data_minio()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">load_data_minio()</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 从Minio获取文件  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">response </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> minioClient.get_object(ftype, file_name)</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># fastapi使用的时候返回文件使用流式响应</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> StreamingResponse(response.stream(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">32</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> *</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1024</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">), </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">media_type</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"application/octet-stream"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br></div></div><h3 id="自带的分片上传" tabindex="-1">自带的分片上传 <a class="header-anchor" href="#自带的分片上传" aria-label="Permalink to &quot;自带的分片上传&quot;">&ZeroWidthSpace;</a></h3>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> multipart_upload</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(object_name, file_path):  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 传入的对象名称，文件路径  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    headers </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Content-Type"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"application/octet-stream"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    part_size </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 50</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> *</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1024</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> *</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1024</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  # 上传的文件大于5MiB时启动分片上传  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    upload_id </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> minioClient._create_multipart_upload(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">BUCKET_NAME</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, object_name, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">headers</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">headers)  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 1. 初始化一个新的分片上传并获得upload_id  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    parts </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> []  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    with</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> open</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(file_path, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'rb'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">as</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> file_data:  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 2. 上传每个分片  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        part_number </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        while</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> True</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            data </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> file_data.read(part_size)  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># warn 注意这里是按照分片大小直接读取的文件流数据  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            if</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> not</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> data:  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">                break</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            etag </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> minioClient._upload_part(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">BUCKET_NAME</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, object_name, data, headers, upload_id, part_number)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            parts.append(Part(part_number, etag))  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            part_number </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    minioClient._complete_multipart_upload(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">BUCKET_NAME</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, object_name, upload_id, parts)  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 3. 完成分片上传,应该是合并</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br></div></div><p>分片上传的大小可能影响效率，5MB大小和50MB分片大小，分别是17s和15s，可以考虑的方面有文件的io，网络io，上传开销。小于分片的大小会直接报错<br>
使用fastapi的时候，分成三个接口，一个申请，一个上传，一个校验结束，可以自己加一些自己的校验。</p>
<h3 id="断点续下载" tabindex="-1">断点续下载 <a class="header-anchor" href="#断点续下载" aria-label="Permalink to &quot;断点续下载&quot;">&ZeroWidthSpace;</a></h3>
<p>#todo 直接配合fastapi的路由实现断点续传</p>
<h2 id="自己实现分片上传" tabindex="-1">自己实现分片上传 <a class="header-anchor" href="#自己实现分片上传" aria-label="Permalink to &quot;自己实现分片上传&quot;">&ZeroWidthSpace;</a></h2>
<p>分片上传需要并发，主流浏览器对HTTP 1.1和HTTP 1.0的最大并发连接数目，可以参考如下表格：</p>
<p>分片上传，断点续传，断点续下，秒传流程图</p>
<div class="language-mermaid vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">mermaid</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">graph TD</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    Start((开始上传)) --> VerifyMD5{从客户端\n获得文件MD5\n和分片列表}</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    VerifyMD5 -->|MD5不存在于Redis| CheckTempFolder1{临时文件夹\n是否存在?}</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    CheckTempFolder1 -->|不存在| ReturnFileNotExist1[返回\n文件不存在]</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    CheckTempFolder1 -->|存在| DeleteTempContent1[删除临时文件夹]</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    DeleteTempContent1 --> ReturnFileNotExist1</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    VerifyMD5 -->|MD5存在于Redis| CheckTempFolder2{临时文件夹\n是否存在?}</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    CheckTempFolder2 -->|不存在| VerifyMD5File{校验文件\n是否存在}</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    VerifyMD5File -->|上传完成\n标志True| ReturnFileURL[返回文件URL]</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    VerifyMD5File -->|不存在| ReturnFileNotExist2[删除RedisMD5\n返回文件不存在]</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    CheckTempFolder2 -->|存在| ReturnLastChunkName[返回最后\n一个分片名称]</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    ReturnLastChunkName-->Return[返回结果]</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    ReturnFileNotExist1-->Return[返回结果]</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    ReturnFileNotExist2-->Return[返回结果]</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    ReturnFileURL-->Return[返回结果]</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br></div></div><div class="language-mermaid vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">mermaid</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">graph TD</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    Start((文件不存在)) --> </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    ReturnLastChunkName[获得MD5与分片列表] -->a[Redis加入MD5 完成标志位False\n创建MD5命名的临时文件夹]</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    a --> |第一个分片| UploadChunk{上传分片}</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    UploadChunk -->CallUploadAPI[调用上传分片]</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    CallUploadAPI --> UploadResult[返回上传结果]</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    UploadResult --> CheckRemainingChunk{还有未上\n传的分片?}</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    CheckRemainingChunk -->|有| UploadChunk</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    CheckRemainingChunk -->|没有| MergeChunks[调用合并分片接口]</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br></div></div><div class="language-mermaid vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">mermaid</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">graph TD</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    Start((合并分片)) --> MergeFilesInTempFolder{合并临时\n文件夹\n中的文件}</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    MergeFilesInTempFolder -->|失败| DeleteTempFolder[删除临时文件夹]</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    DeleteTempFolder --> ReturnMergeFail[返回失败]</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    MergeFilesInTempFolder -->|成功| VerifyMergedFileMD5{校验合并后\n文件MD5}</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    VerifyMergedFileMD5 -->|相同| SaveToRedis[修改上传完成标志位True]</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    SaveToRedis --> DeleteTempContent2[删除临时文件夹]</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    DeleteTempContent2 --> ReturnURL[获取URL并返回]</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    VerifyMergedFileMD5 -->|不同| DeleteMergedFile[删除合并的文件]</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    DeleteMergedFile --> DeleteTempFolder</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    ReturnMergeFail --> return[返回]</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    ReturnURL --> return[返回]</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    return[返回]</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br></div></div><p>如果要使用多线程下载，那就不要删除MD5文件夹，上面做一点小改动，开多个线程读取分片即可</p>
<p>#todo 前面的区域，以后再来探索吧ceph存储原理
<a href="https://www.bilibili.com/video/BV11H4y1J7NR/" target="_blank" rel="noreferrer">mq和kafka选型场景_哔哩哔哩_bilibili</a></p>
<h2 id="踩坑记录" tabindex="-1">踩坑记录 <a class="header-anchor" href="#踩坑记录" aria-label="Permalink to &quot;踩坑记录&quot;">&ZeroWidthSpace;</a></h2>
<hr class="footnotes-sep">
<section class="footnotes">
<ol class="footnotes-list">
<li id="fn1" class="footnote-item"><p><a href="https://learnku.com/articles/57684" target="_blank" rel="noreferrer">MINIO 了解及使用 | Server 运维论坛</a> <a href="#fnref1" class="footnote-backref">↩︎</a></p>
</li>
</ol>
</section>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[docker常用知识]]></title>
            <link>http://ooowl.fun/blogs/Web%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/%E5%AE%B9%E5%99%A8%E6%8A%80%E6%9C%AF/Docker%E5%B8%B8%E7%94%A8%E7%9F%A5%E8%AF%86.html</link>
            <guid isPermaLink="false">http://ooowl.fun/blogs/Web%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/%E5%AE%B9%E5%99%A8%E6%8A%80%E6%9C%AF/Docker%E5%B8%B8%E7%94%A8%E7%9F%A5%E8%AF%86.html</guid>
            <pubDate>Wed, 06 Sep 2023 15:19:59 GMT</pubDate>
            <content:encoded><![CDATA[<h1 id="docker常用知识" tabindex="-1">docker常用知识 <a class="header-anchor" href="#docker常用知识" aria-label="Permalink to &quot;docker常用知识&quot;">&ZeroWidthSpace;</a></h1><p class="article-meta">创建于 2023年9月6日 23:19:59 · 约4,064字</p>
<p>先放一波资料，我目标是能日常使用，排查一些常见错误，自己打包dockerfile编排compose，大致知道imspect各个项是什么含义，管理容器镜像网络仓库转移。</p>
<ul>
<li><a href="https://dockertips.readthedocs.io/en/latest/" target="_blank" rel="noreferrer">docker 笔记</a></li>
<li><a href="https://www.runoob.com/docker/docker-command-manual.html" target="_blank" rel="noreferrer">Docker 命令大全 | 菜鸟教程</a></li>
<li><a href="https://docs.docker.com/get-started/" target="_blank" rel="noreferrer">Overview of the get started guide | Docker Docs</a></li>
<li><a href="https://docs.docker.com/engine/reference/builder/" target="_blank" rel="noreferrer">Dockerfile reference | Docker Docs</a></li>
<li><a href="https://www.composerize.com/?utm_source=appinn.com" target="_blank" rel="noreferrer">Composerize</a> 把docker命令转为compose文件，好用！
这个是属于半笔记的半提示的，自己默认会的就不往上写，是不断维护的，主要作用是快速帮自己想起来，而不是事无巨细抄文档，那样没有什么意义。<br>
命令主要整理不常用但是能用到的命令</li>
</ul>
<h2 id="前置工作" tabindex="-1">前置工作 <a class="header-anchor" href="#前置工作" aria-label="Permalink to &quot;前置工作&quot;">&ZeroWidthSpace;</a></h2>
<p>不同的系统架构，dockerimages打包出来的镜像是不一样的，所以打包之前要注意。可以跨平台dan但我自己平时用不需要所以直接跳过这个<br>
<a href="https://docs.docker.com/engine/install/" target="_blank" rel="noreferrer">安装docker</a>，<a href="https://docs.docker.com/compose/install/" target="_blank" rel="noreferrer">安装docker-compose</a><br>
安装完成之后运行一个demo的容器测试行不行</p>
<div class="language-bash vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">sudo</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> docker</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> run</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> hello-world</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p>镜像不包含动态数据，镜像以基础镜像构建时，不会改变先前的底层基础镜像，即使是删除操作也是标记，所以体积不会减小。容器不应该向其存储层内写入任何数据，容器存储层要保持无状态化。所有的文件写入操作，都应该使用。仓库名经常以 两段式路径 形式出现，比如 <code>jwilder/nginx-proxy</code>，前者往往意味着 Docker Registry 多用户环境下的用户名，后者则往往是对应的软件名。</p>
<div class="danger custom-block"><p class="custom-block-title">[🚨Danger]  docker的网络是越过防火墙的</p>
<p>docker的网络是越过防火墙的
docker的网络是越过防火墙的，使用firewall或者iptables是无法限制docker打开的端口的。</p>
</div>
<p>列一下自己常用的命令，已经嵌入潜意识那种</p>
<div class="language-bash vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">docker</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -v</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 查看版本</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">docker</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> run</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 基础的运行容器</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">docker</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> stop</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> f0b935ae9277</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">docker</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> rm</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> f0b935ae9277</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">docker</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> ps</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">docker</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> images</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">docker</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> port</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> demo</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 查看demo的所有端口映射</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">docker</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> rmi</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> f0b935ae9277</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">docker</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> exec</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -it</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> f0b935ae9277</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> /bin/bash</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 进入某个容器，ctrl+p+q or ctrl+d 退出而不关闭</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">docker</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> inspect</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> f0b935ae9277</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">docker</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> logs</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> f0b935ae9277</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">docker-compose</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> stop</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">docker-compose</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> up</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -d</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">docker-compose</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> down</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # down会把容器停止并删除</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br></div></div><p>几个命令常用参数：</p>
<div class="language-bash vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">docker</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> run</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -d</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -p</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 8085:8000</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -v</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> ./dicom_sets:/app/dicom_sets</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> --name</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> dicom_viewer</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">  dicom_viewer</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># -d 表示运行完不退出容器</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># -p 外部端口:内部端口</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># -v 外部目录:内部目录</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># --name 容器名字</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">docker</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> ps</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 默认情况下只显示正在运行的容器</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">docker</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> ps</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -a</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 显示所有的容器</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">docker</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> ps</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -aq</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 显示所有的容器的id</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">docker</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> stop</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> `</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">docker</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> ps </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">-aq</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">`</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 使用id停止所有的容器，同理也可以start</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">docker</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> ps</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> --filter</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "name=web"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 显示名称包含 "web" 的容器</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">docker</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> ps</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> --filter</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "status=exited"</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 显示状态为 "exited" 的容器</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br></div></div><p>docker是引擎和client结构，你的client可以连接任意的引擎。</p>
<h2 id="镜像" tabindex="-1">镜像 <a class="header-anchor" href="#镜像" aria-label="Permalink to &quot;镜像&quot;">&ZeroWidthSpace;</a></h2>
<p><code>docker pull ubuntu:18.04</code> 默认的Registry是library也就是docker官方的镜像库docker.io，完整的URI名字应该是<code>docker.io/library/ubuntu:18.04</code></p>
<p>镜像拉取的时候并不是单文件而是多层的文件系统构成的，所以多个镜像可以共享相同的底层文件，中间的依赖回收也是引用计数，docker image获取的是顶层可以使用的镜像，中间的依赖镜像和文件并不会显示。删除行为分为两类，一类是 <code>Untagged</code>，另一类是 <code>Deleted</code>，镜像是多层依赖构成的，先把所有的tag都取消掉，然后引用计数回收。因为有时候是多images同时引用一个，所以有可能不会全删除</p>
<div class="language-bash vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">docker</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> system</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> df</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 查看镜像、容器、数据卷所占用的空间</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">docker</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> images</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -f</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> dangling=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">true</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 查看所有name&#x26;tags是none的镜像</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">docker</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> image</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> prune</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 清除所有none的镜像</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">docker</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> diff</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 容器</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 对照容器做了哪些更改</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">docker</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> run</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -it</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> --name</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> container_name</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> image_name:tag</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> /bin/bash</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">docker</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> commit</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> --author</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "nobody"</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> --message</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "修改了什么"</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> container_name[hash]</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> image_name:tag</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 修改了哪些东西，搞成一个新镜像</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">docker</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> tag</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 5e50574fb696</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> ooowl/nginx:1.0</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 有些镜像导入之后没名字，记得手动修改</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br></div></div><div class="tip custom-block"><p class="custom-block-title">[💡Tip]</p>
<p><code>docker commit</code> 命令除了学习之外，还有一些特殊的应用场合，比如被入侵后保存现场等。但是，不要使用 <code>docker commit</code> 定制镜像，应使用 <code>Dockerfile</code> 来完成。
由于各种对镜像的命令执行，还有很多文件被改动或添加了。如果是安装软件包、编译构建，那会有大量的无关内容被添加进来，将会导致镜像极为臃肿。</p>
</div>
<h3 id="离线导出导入" tabindex="-1">离线导出导入 <a class="header-anchor" href="#离线导出导入" aria-label="Permalink to &quot;离线导出导入&quot;">&ZeroWidthSpace;</a></h3>
<p>开导！<br>
命令很固定，可以一次性保存多个</p>
<div class="language-bash vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">docker</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> save</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> redis:7</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> mongo:6</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> |</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> 7z</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> a</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -si</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> images.tar.7z</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  # 导出镜像</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">7z</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> x</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -so</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> images.tar.7z</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">   |</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> docker</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> load</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 导入镜像</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 不使用7z</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">docker</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> save</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -o</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> nginx.tar</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> nginx:latest</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">docker</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> load</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -i</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> nginx.tar</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 直接一条命令转移镜像</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">docker</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> save</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> &#x3C;</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">镜像</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">名</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">></span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> |</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> bzip2</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> |</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> pv</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> |</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> ssh</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> &#x3C;</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">用户</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">名</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">></span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">@</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x3C;</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">主机</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">名</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">></span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 'cat | docker load'</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br></div></div><p><strong>注意：如果导出的文件同名则会覆盖（没有警告）</strong></p>
<p>docker save和docker export的区别，一般都是导入导出镜像，然后再做部署工作</p>
<ul>
<li>对于Docker Save方法，会保存该镜像的所有历史记录</li>
<li>对于Docker Export 方法，不会保留历史记录，即没有commit历史</li>
<li>docker save保存的是镜像（image），docker export保存的是容器（container）；</li>
<li>docker load用来载入镜像包，docker import用来载入容器包，但两者都会恢复为镜像；</li>
<li>docker load不能对载入的镜像重命名，而docker import可以为镜像指定新名称。</li>
</ul>
<h3 id="dockerfile" tabindex="-1">dockerfile <a class="header-anchor" href="#dockerfile" aria-label="Permalink to &quot;dockerfile&quot;">&ZeroWidthSpace;</a></h3>
<p>这是菜鸟列出来的<a href="https://www.runoob.com/docker/docker-dockerfile.html" target="_blank" rel="noreferrer">所有命令</a><br>
<a href="https://yeasy.gitbook.io/docker_practice/image/dockerfile/copy" target="_blank" rel="noreferrer"><strong>dockerfile构建的一些命令</strong></a> 当手册可以查</p>
<p>Dockerfile 中每一个指令都会建立一层，每一个 <code>RUN</code> 的行为就会新建立一层，在其上执行这些命令结束后<code>commit</code> 这一层的修改，构成新的镜像。所以为了减少冗余，最好是RUN个大的而不是多次RUN（指令也是）。</p>
<div class="tip custom-block"><p class="custom-block-title">[💡Tip]</p>
<p>Union FS 是有最大层数限制的，比如 AUFS，曾经是最大不得超过 42 层，现在是不得超过 127 层，也就是说dockerfile过程产生的数量就不能超过此层数。<br>
而且每层构建都会永久的跟着镜像，所以打包编译之类的工作最后应该clean并删除不需要的文件保持干净。</p>
</div>
<p>在 <code>Dockerfile</code> 文件所在目录执行<code>docker build -t images:tag .</code> 注意最后的目录，此目录是表明构建时候的<strong>工作目录</strong>，dockerfile中COPY命令等涉及文件路径操作的，都是基于此目录操作。因为有可能是连接的其他的engine，会把client进行build的时候的目录全都传送过去，所以不要随便找个地方build，最好整个空的干净目录，把需要的都放在这个目录里面。一般来说大部分情况都是本地的build，所以找个新目录用 <code>.</code> 就可以了。<br>
默认读取指定的工作目录名为的Dockerfile的文件作为构建文件，可以使用<code>-f ../Dockerfile.php</code> 指定dockerfile。</p>
<p>.dockerignore 文件应该位于构建上下文的根目录中，无论它是否与 Dockerfile 放置在同一个文件夹中。</p>
<p>给出一个dockerfile的示例</p>
<div class="language-dockerfile vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">dockerfile</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">FROM</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> library/nginx:latest  </span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">LABEL</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> maintainer=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"none &#x3C;none@gmail.com>"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># stdout 无缓冲，直接输出  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">ENV</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> PYTHONUNBUFFERED 1  </span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">WORKDIR</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> /app  </span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">COPY</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> app/static/comparison_worker.py /app  </span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">ENV</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> PYTHONPATH=/app  </span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">RUN</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br></div></div><p>一般来说，步骤大致包括指定基础镜像和维护人， 配置环境变量，复制需要的文件进去，指定工作目录，使用compose最后运行启动命令</p>
<h3 id="远程仓库" tabindex="-1">远程仓库 <a class="header-anchor" href="#远程仓库" aria-label="Permalink to &quot;远程仓库&quot;">&ZeroWidthSpace;</a></h3>
<p>可以使用<code>docker search centos</code>进行搜索镜像，查找的时候通过 <code>--filter=stars=N</code> 参数可以指定仅显示收藏数量为 <code>N</code> 以上的镜像<br>
<code>docker login</code>和<code>docker logout</code>登入登出，如果要推送镜像的话。<br>
<code>docker tag 5e50574fb696 ooowl/textmodel:1.0</code>  注意先修改你的用户名才能推送到你的账户底下。<br>
<code>docker push ooowl/textmodel:1.0</code> 推送到了ooowl的用户名下</p>
<p><strong>如果你使用了私有的hub</strong> 那就把路径前加上hub的地址就可以了(假设hub的地址是5000)</p>
<ul>
<li>先用tag修改名字<code>tag ubuntu:latest 127.0.0.1:5000/ubuntu:latest</code></li>
<li>push上去<code>docker push 127.0.0.1:5000/ubuntu:latest</code></li>
</ul>
<h2 id="容器" tabindex="-1">容器 <a class="header-anchor" href="#容器" aria-label="Permalink to &quot;容器&quot;">&ZeroWidthSpace;</a></h2>
<p>常用的参数
<code>-t</code> 选项让Docker分配一个伪终端（pseudo-tty）并绑定到容器的标准输入上， <code>-i</code> 则让容器的标准输入保持打开。
<code>docker run -it nginx:1.0 /bin/echo 'Hello world'</code> 也可以直接运行bash来操作，不过你detect的时候容器就结束了，可以用-d来后台运行
当利用 <code>docker run</code> 来创建容器时，Docker 在后台运行的标准操作包括：</p>
<ul>
<li>检查本地是否存在指定的镜像，不存在就从registry下载</li>
<li>利用镜像创建并启动一个容器</li>
<li>分配一个文件系统，并在只读的镜像层外面挂载一层可读写层</li>
<li>从宿主主机配置的网桥接口中桥接一个虚拟接口到容器中去</li>
<li>从地址池配置一个 ip 地址给容器</li>
<li>执行用户指定的应用程序</li>
<li>执行完毕后容器被终止</li>
</ul>
<p><code>docker attach</code> 和docker exec是一样的功能，但是退出终端后容器就会退出</p>
<h2 id="数据卷" tabindex="-1">数据卷 <a class="header-anchor" href="#数据卷" aria-label="Permalink to &quot;数据卷&quot;">&ZeroWidthSpace;</a></h2>
<h3 id="一般映射" tabindex="-1">一般映射 <a class="header-anchor" href="#一般映射" aria-label="Permalink to &quot;一般映射&quot;">&ZeroWidthSpace;</a></h3>
<p>通过 <code>-v 外部目录:内部目录</code> 来映射目录，映射的时候要注意权限问题，比如在pg数据库映射data的时候自动生成的文件权限就是1001:1001这个权限会被带到里面，不对的话数据库启动不了。<br>
<strong>映射的时候目录最好使用绝对路径</strong>。<br>
如果使用路径了，比如带点或者带杠的，那就会尝试使用目录，挂不上就是报错。<br>
如果只是单纯打个名字，那就会自动创建一个卷。<br>
映射的时候如果<strong>外部或者内部</strong>没有这个目录那就会被创建，<strong>前提是目录为绝对目录</strong><br>
-v详细的写法可以写成如下，可以配置是否为只读<br>
<code>--mount type=bind,source=/src/webapp,target=/usr/share/nginx/html,readonly</code></p>
<p>拷贝文件(夹)进去或者出来，文件夹也行<br>
<code>docker cp source destnation</code>，其中源和目的地，本机上的都是绝对路径，镜像内的路径表达是<code>container:/root/abspath</code></p>
<h3 id="使用数据卷" tabindex="-1">使用数据卷 <a class="header-anchor" href="#使用数据卷" aria-label="Permalink to &quot;使用数据卷&quot;">&ZeroWidthSpace;</a></h3>
<p>数据卷 是一个可供一个或多个容器使用的特殊目录，它绕过 UnionFS，可提供很多有用的特性：</p>
<ul>
<li>可以在容器之间共享和重用</li>
<li>修改会立马生效</li>
<li>更新，不会影响镜像</li>
<li>默认会一直存在，即使容器被删除</li>
</ul>
<div class="language-bash vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">docker</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> volume</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> create</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> my-vol</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 创建一个新的卷</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">docker</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> volume</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> ls</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 查看所有的卷</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">docker</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> volume</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> inspect</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> v_name</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 查看卷详细信息</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">docker</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> volume</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> prune</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 批量清除没在用的</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">docker</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> volume</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> rm</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 删除</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br></div></div><p>数据卷相当于一个docker管理起来的文件夹，可以让多个docker共用，如果使用目录就不能共享<br>
数据卷的迁移，比较麻烦。 Docker并未提供官方的简单方案，所以用到了再去查</p>
<h2 id="网络" tabindex="-1">网络 <a class="header-anchor" href="#网络" aria-label="Permalink to &quot;网络&quot;">&ZeroWidthSpace;</a></h2>
<h3 id="基本使用" tabindex="-1">基本使用 <a class="header-anchor" href="#基本使用" aria-label="Permalink to &quot;基本使用&quot;">&ZeroWidthSpace;</a></h3>
<p>容器要想访问外部网络，需要本地系统的转发支持。在Linux 系统中，检查转发是否打开。</p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>$sysctl net.ipv4.ip_forward</span></span>
<span class="line"><span>net.ipv4.ip_forward = 1</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br></div></div><p>如果为 0，说明没有开启转发，则需要手动打开。</p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>$sysctl -w net.ipv4.ip_forward=1</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p>如果在启动 Docker 服务的时候设定 <code>--ip-forward=true</code>, Docker 就会自动设定系统的 <code>ip_forward</code> 参数为 1。</p>
<div class="language-bash vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">docker</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> network</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> create</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> network_name</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  # 一般默认的就是bridge</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">docker</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> network</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> ls</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">docker</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> network</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> connect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">disconnect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">网络</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 容器</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 将运行中的容器加入某一个网络</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">docker</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> network</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> inspect</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> network_name</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 探查某个网络</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#创建网络的时候指定网络的参数</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">docker</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> network</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> create</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> \</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">  --driver</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> bridge</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> \ </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">             # 指定网络驱动程序为 bridge</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">  --subnet</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 192.168.1.0/24</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> \ </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    # 指定子网</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">  --gateway</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 192.168.1.1</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> \ </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">      # 指定网关</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">  --ip-range</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 192.168.1.128/25</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> \ </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">#</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 指定</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> IP</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 范围</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">  --dns</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 8.8.8.8</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> \ </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">              # 指定 DNS 服务器</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">  --dns</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 8.8.4.4</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> \ </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">              # 可以指定多个 DNS 服务器</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">  my-custom-network</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">             # 指定网络名称</span></span>
<span class="line"></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># run的时候指定静态ip地址和容器名，如果加入了网络可以使用容器名通信，如果是默认那可以使用ip地址通信</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">docker</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> run</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> --network=my-custom-network\ </span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"># 这里空格等号都行</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">           --ip</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 192.168.1.10</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> \</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">           --name=container1</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> \</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">           -d</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> my-image</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br></div></div><p>如果在同一个Docker Compose 文件或 Docker Swarm 集群中Docker 会自动设置 DNS 记录镜像可以使用容器名进行通信。一般都是划分到共同的网络里容器名通信就完事了。</p>
<h3 id="原理与配置" tabindex="-1">原理与配置 <a class="header-anchor" href="#原理与配置" aria-label="Permalink to &quot;原理与配置&quot;">&ZeroWidthSpace;</a></h3>
<p>以后遇到网络问题可以慢慢积累高级的网络知识<br>
网络映射使用-p的话除了指定之外可以把外部随机一个端口映射。<br>
创建network之后，让容器共同加入一个网络才能互相访问，否则只能过一遍宿主机网络访问。<br>
<code>docker network create -d bridge my-net</code>
<code>-d</code> 参数指定 Docker 网络类型，有 <code>bridge</code> <code>overlay</code>。其中 <code>overlay</code> 网络类型用于swarm，所以直接不看
<img src="./static/Docker常用知识_images_1.png" alt="网络的基本结构|500"></p>
<p>docker在安装完之后会生成一个docker0网络，它在内核层连通了其他的物理或虚拟网卡，这就将所有容器和本地主机都放到同一个物理网络,使用ifconfig查看网络可得网络其中有一个，172网段内部网络</p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>docker0: flags=4099&#x3C;UP,BROADCAST,MULTICAST>  mtu 1500</span></span>
<span class="line"><span>        inet 172.17.0.1  netmask 255.255.0.0  broadcast 172.17.255.255</span></span>
<span class="line"><span>        inet6 fe80::42:b7ff:fe9a:598c  prefixlen 64  scopeid 0x20&#x3C;link></span></span>
<span class="line"><span>        ether 02:42:b7:9a:59:8c  txqueuelen 0  (Ethernet)</span></span>
<span class="line"><span>        RX packets 3927  bytes 920130 (920.1 KB)</span></span>
<span class="line"><span>        RX errors 0  dropped 0  overruns 0  frame 0</span></span>
<span class="line"><span>        TX packets 5476  bytes 29518426 (29.5 MB)</span></span>
<span class="line"><span>        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br></div></div><p>docker在自己的内部会创建三个网络分别是bridge，host，none，这三个网络是不能删除的，创建容器的时候网络类型都是依据这三个来创建的，默认的网络就是bridge</p>
<p>Docker 创建一个容器的时候，会执行如下操作：</p>
<ol>
<li>创建一对虚拟接口，分别放到本地主机和新容器中；</li>
<li>本地主机一端桥接到默认的 docker0 或指定网桥上，并具有一个唯一的名字，如 veth65f9；</li>
<li>容器端放到新容器中，并修改名字作为 eth0，这个接口只在容器的命名空间可见；</li>
<li>从网桥可用地址段中获取一个空闲地址分配给容器的 eth0，并配置默认路由到桥接网卡 veth65f9。</li>
<li>桥接不能使用name解析bridge中的ip地址</li>
</ol>
<p>可以在 <code>docker run</code> 的时候通过 <code>--network</code> 参数来指定容器的网络配置，有4个可选值：</p>
<ul>
<li><code>--network bridge</code> 这个是默认值,不配置就是他，连接到默认的网桥，实际上是NAT会消耗一点CPU。</li>
<li><code>--network my-net</code> 这需要你提前创建一个bridge网络，自建的brigge可以使用容器名通信，而且和其他的网络栈隔离</li>
<li><code>--network host</code>  容器直接接入host的网络，拥有完全的host接口访问权限，甚至可以重启。如果进一步的使用 <code>--privileged=true</code>，容器会被允许直接配置主机的网络堆栈。</li>
<li><code>--network none</code> 让 Docker 不设置任何网络，之后自己配置不然上不了网，用的少除非容器只本地用</li>
<li><code>--network container:NAME_or_ID</code> 俩容器用一个网卡，此时他俩不过是一个ip下的连体婴儿罢了。</li>
</ul>
<p>不管哪种方式，端口访问控制其实也是在本地的 <code>iptable</code> 的 nat 表中添加相应的规则</p>
<h2 id="docker-compose" tabindex="-1">docker-compose <a class="header-anchor" href="#docker-compose" aria-label="Permalink to &quot;docker-compose&quot;">&ZeroWidthSpace;</a></h2>
<p>docker stack是docker原生支持的编排工具，被定义为适用于生产环境的编排工具，强化了（ 复制集、 容器重启策略、回滚策略、服务更新策略 ）等生产特性（虽然我都用不着<br>
在portainer中可以看到有哪些stack，一般来说一个compose文件就会创建一个stack，并且创建一个bridge网络，并把编排的容器放进去。</p>
<p>常用的命令，一般的命令就不提了，天天用。：</p>
<div class="language-bash vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">docker-compose</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> up</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -d</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">docker-compose</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> down</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 注意和stop的区别</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">docker-compose</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> stop/start</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">docker-compose</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> build</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 重新构建服务</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">docker-compose</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> config</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 检测是不是有语法错误</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">docker-compose</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> images</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 查看stack需要的镜像</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">docker-compose</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> logs</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> |</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> less</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> +G</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 从底下开始查看日志，不同的容器会给你用不同颜色混杂显示</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br></div></div><p>一个compose内的容器的名称默认是这样规定的:</p>
<ol>
<li>项目名称：默认情况下，这是你的 <code>docker-compose.yml</code> 文件所在文件夹的名称。</li>
<li>服务名称：这是在 <code>docker-compose.yml</code> 文件中定义的服务名称。</li>
<li>实例编号：这是一个数字，表示这是该服务的第几个实例。</li>
<li>如果你不写名字，那每一个都会自动编号为<code>project-container-1</code></li>
<li><code>docker-compose -p custom_name up</code> 可以自定义前缀而不是使用项目名称</li>
</ol>
<p><a href="https://yeasy.gitbook.io/docker_practice/compose/compose_file" target="_blank" rel="noreferrer">常用的命令</a>，可以浏览几遍。<br>
几个需要注意的：</p>
<ul>
<li>虽然<code>depends_on</code>确保了依赖关系，但它并不会等待依赖的服务完全就绪，而是只等待依赖的服务启动。这意味着，在某些情况下，即使依赖的服务已经启动，它们可能还没有完全初始化或准备好接受连接，比如db的容器已经启动，但是容器内的数据库还没起来，这样你就得自己想办法延时或者重试。</li>
<li>当您尝试创建一个网络并指定已经被使用的子网时，网络创建请求会失败，因为Docker会检测到子网冲突并阻止网络的创建。</li>
<li>指定network的时候<code>external: true</code>会尝试找已经存在的网络加入，如果没有就创建</li>
<li><code>command: &quot;sleep infinity&quot;</code> # 调试用的停住不退出镜像</li>
<li><code>pull_policy: never</code>  有时候本地有镜像他还去拉，可强制使用本地镜像
尝试自己写一个elk:</li>
</ul>
<div class="language-yaml vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">yaml</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">回去看看无聊的时候给搭起来，现在内存不是很多。</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">Docker Compose部署ELK – 爱拼才会赢</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">(https://xuyongsheng.cn/docker-composebushuelk/)</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br></div></div><h2 id="镜像打包" tabindex="-1">镜像打包 <a class="header-anchor" href="#镜像打包" aria-label="Permalink to &quot;镜像打包&quot;">&ZeroWidthSpace;</a></h2>
<p>当然这里是作为一个主要是平时开发和单机部署打包的必要知识，详细的东西不如直接去文档找<br>
官方文档上说的<a href="https://docs.docker.com/build/building/best-practices/" target="_blank" rel="noreferrer">最佳实践</a>，Docker镜像是由很多镜像层（Layers）组成的（最多127层）， Dockerfile 中的每条指定都会创建镜像层，不过<strong>只有 <code>RUN</code>, <code>COPY</code>, <code>ADD</code> 会使镜像的体积增加</strong>。这个可以通过命令 <code>docker history image_id</code> 来查看每一层的大小。<a href="https://zhuanlan.zhihu.com/p/161685245" target="_blank" rel="noreferrer">别人的最佳实践</a>，等碰到打包瓶颈了再去找这个最佳实践<br>
推送之前需要先登录docker login。</p>
<p>打包的命令：``
<code>docker build -f ./worker.dockerfile -t library/worker .</code> 指定使用某dockerfile打包，指定tag，在当前目录下进行打包，默认的标签为latest。
之后就可以docker push
修改镜像后打包。</p>
<div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#在container中重新打包</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">docker</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> run</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> --rm</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -it</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> Image:latest</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">  /bin/bash</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">docker</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> commit</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> imghash</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> Image:latest</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">docker</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> push</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> Image:latest</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#dcokerfile重新打包</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">FROM</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> Image:latest</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">RUN</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> pip</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> install</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> some-package==</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1.2.3</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#打包</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">docker</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> build</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -t</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> Image:latest</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> .</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">docker</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> push</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> Image:latest</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br></div></div><h2 id="日志收集" tabindex="-1">日志收集 <a class="header-anchor" href="#日志收集" aria-label="Permalink to &quot;日志收集&quot;">&ZeroWidthSpace;</a></h2>
<p>#TODO 挖坑docker的日志收集，日志时间同步，程序的时区同步，log输出的日志时间会减8h
纵览当前容器日志收集的场景，无非就是两种方式：一是直接采集Docker标准输出，容器内的服务将日志信息写到标准输出，这样通过Docker的log driver可以发送到相应的收集程序中；二是延续传统的日志写入方式，容器内的服务将日志直接写到普通文件中，通过Docker volume将日志文件映射到Host上，日志采集程序就可以收集它。</p>
<p>第一种方式足够简单，直接配置相关的Log Driver就可以，但是这种方式也有些劣势：</p>
<ol>
<li>当主机的容器密度比较高的时候，对Docker Engine的压力比较大，毕竟容器标准输出都要通过Docker Engine来处理。</li>
<li>尽管原则上，我们希望遵循一容器部署一个服务的原则，但是有时候特殊情况不可避免容器内有多个业务服务，这时候很难做到所有服务都向标准输出写日志，这就需要用到前面所说的第二种场景模式。</li>
<li>虽然我们可以先选择很多种Log Driver，但是有些Log Driver会破坏Docker原生的体验，比如docker logs无法直接看到容器日志。</li>
</ol>
<p>Docker处理日志的方法&amp;日志收集工具比较
<a href="https://blog.51cto.com/u_12890843/5347071" target="_blank" rel="noreferrer">https://blog.51cto.com/u_12890843/5347071</a></p>
<h2 id="踩坑记录" tabindex="-1">踩坑记录 <a class="header-anchor" href="#踩坑记录" aria-label="Permalink to &quot;踩坑记录&quot;">&ZeroWidthSpace;</a></h2>
<p>使用223机器的时候出现docker虚拟网卡频繁插拔，Ubuntu20.04LTS VMware，docker用一段时间之后巨卡，查看systemctl日志发现此问题。<br>
没有找到办法，换了CentOS就好了。</p>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Nginx-EP2]]></title>
            <link>http://ooowl.fun/blogs/Web%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/%E7%BD%91%E5%85%B3/Nginx-EP2.html</link>
            <guid isPermaLink="false">http://ooowl.fun/blogs/Web%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/%E7%BD%91%E5%85%B3/Nginx-EP2.html</guid>
            <pubDate>Wed, 26 Jul 2023 00:29:31 GMT</pubDate>
            <description><![CDATA[使用#来注释 一般来说分三大块]]></description>
            <content:encoded><![CDATA[<h1 id="nginx-ep2" tabindex="-1">Nginx-EP2 <a class="header-anchor" href="#nginx-ep2" aria-label="Permalink to &quot;Nginx-EP2&quot;">&ZeroWidthSpace;</a></h1><p class="article-meta">创建于 2023年7月26日 08:29:31 · 约4,644字</p>
<h2 id="配置文件" tabindex="-1">配置文件 <a class="header-anchor" href="#配置文件" aria-label="Permalink to &quot;配置文件&quot;">&ZeroWidthSpace;</a></h2>
<p>使用#来注释<br>
一般来说分三大块</p>
<ul>
<li>全局块，社设置nginx运行的时候软件的相关的变量</li>
<li>events块，和nginx服务器网络相关的内容，和性能相关比较大</li>
<li>http块，日志服务第三方等都在这个块中配置
<ul>
<li>server块，在http里面配置每一个供访问的资源路径，可以配置多个</li>
</ul>
</li>
</ul>
<div class="language-nginx vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">nginx</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 这是把注释了的都删掉的nginx配置文件，可以当原型看待</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">worker_processes </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">events</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    worker_connections </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1024</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">http</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    include </span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      mime.types;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    default_type </span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> application/octet-stream;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    sendfile </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">       on</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    keepalive_timeout </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 65</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    server</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        listen </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">      80</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        server_name </span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> localhost;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        location</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> / </span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            root </span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  html;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            index </span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> index.html index.htm;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        }</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        error_page </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">  500</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 502</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 503</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 504</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  /50x.html;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        location</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#032F62;--shiki-dark:#DBEDFF"> /50x.html </span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            root </span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  html;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br></div></div><h2 id="配置命令" tabindex="-1">配置命令 <a class="header-anchor" href="#配置命令" aria-label="Permalink to &quot;配置命令&quot;">&ZeroWidthSpace;</a></h2>
<div class="tip custom-block"><p class="custom-block-title">[💡Tip]</p>
<p>尽量记下来配置不对的时候会报的常见错误，这样出了问题好排查，指令和问题这里记一下，后面也会有专门的问题记录<br>
不同层级的块会互相覆盖，更细粒度的块配置会覆盖更粗的，可以</p>
</div>
<h3 id="全局块" tabindex="-1">全局块 <a class="header-anchor" href="#全局块" aria-label="Permalink to &quot;全局块&quot;">&ZeroWidthSpace;</a></h3>
<table tabindex="0">
<thead>
<tr>
<th>语法</th>
<th>默认值</th>
<th>位置</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>user user_name [user_group];</code></td>
<td>nobody</td>
<td>全局块</td>
<td>用户组默认使用用户名的组权限启动进程运行，此指令指定的用户访问无权限的目录比如html文件夹指定到了没权限的文件夹，页面会直接403</td>
</tr>
<tr>
<td><code>master_process on;</code></td>
<td>on</td>
<td>全局块</td>
<td>如果设为off 表示禁用主进程，而是直接以单进程模式运行。只会使用一个 worker 进程来处理所有请求。在这种情况下，Nginx 将无法平滑地重启或重新加载配置文件</td>
</tr>
<tr>
<td><code>worker_process auto;</code></td>
<td>auto</td>
<td>全局块</td>
<td>auto自己获取处理器核心数量，配置 worker 进程的数量可以是数字指定几个</td>
</tr>
<tr>
<td><code>daemon on;</code></td>
<td>on</td>
<td>全局块</td>
<td>是否守护进程运行</td>
</tr>
<tr>
<td><code>pid file_name;</code></td>
<td>/var/run/nginx.pid</td>
<td>全局块</td>
<td>默认是指定pid文件存放在哪</td>
</tr>
<tr>
<td><code>error_log logs/error.log error;</code></td>
<td>/var/log/nginx/error.log error</td>
<td>全局块、http、server、location</td>
<td>警报级别<code>debug info notice warn error crit alert emerg</code>最好不要设置info以下，写入太多了会占用IO导致性能下降</td>
</tr>
<tr>
<td><code>include file;</code></td>
<td></td>
<td>any</td>
<td>包含其他的子配置文件，便于管理，子文件的内容会被按照块的顺序完全继承</td>
</tr>
</tbody>
</table>
<h3 id="events块" tabindex="-1">events块 <a class="header-anchor" href="#events块" aria-label="Permalink to &quot;events块&quot;">&ZeroWidthSpace;</a></h3>
<div class="tip custom-block"><p class="custom-block-title">[💡Tip]</p>
<p>&quot;惊群&quot;问题 大致意思是在某一个时刻，客户端发来一个请求连接，Nginx后台是以多进程的工作模式，也就是说有多个worker进程会被同时唤醒，但是最终只会有一个进程可以获取到连接，如果每次唤醒的进程数目太多，就会影响Nginx的整体性能。如果将accept_mutex值设置为on(开启状态)，将会对多个Nginx进程接收连接进行序列号，一个个来唤醒接收，就防止了多个进程对连接的争抢</p>
</div>
<table tabindex="0">
<thead>
<tr>
<th>语法</th>
<th>默认值</th>
<th>位置</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>accept_mutex on;</code></td>
<td>on</td>
<td>events</td>
<td>解决&quot;惊群&quot;问题，</td>
</tr>
<tr>
<td><code>multi_accept on</code></td>
<td>on</td>
<td>events</td>
<td></td>
</tr>
<tr>
<td><code>worker_connections 512;</code></td>
<td>512</td>
<td>events</td>
<td>这里的连接数不仅仅包括和前端用户建立的连接数，而是包括所有可能的连接数。另外，其值不能大于操作系统支持打开的最大文件句柄数量</td>
</tr>
<tr>
<td><code>use method;</code></td>
<td>select/poll/epoll/kqueue</td>
<td>events</td>
<td>此值会根据操作系统自己获得,就是使用什么样的事件驱动</td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
<h3 id="http块" tabindex="-1">http块 <a class="header-anchor" href="#http块" aria-label="Permalink to &quot;http块&quot;">&ZeroWidthSpace;</a></h3>
<table tabindex="0">
<thead>
<tr>
<th>语法</th>
<th>默认值</th>
<th>位置</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>include mime.types;</code></td>
<td></td>
<td>http</td>
<td>nginx需要区分不同的请求携带的内容类型，这些类型是通过MIME来指定的，这些东西被存放到mime.types，http直接引用就可以了</td>
</tr>
<tr>
<td><code>default_type text/plain;</code></td>
<td>text/plain</td>
<td>http、server、location</td>
<td>某些接口需要返回固定的文本字符串或者json，如果逻辑非常简单或者干脆是固定的字符串，可以直接使用nginx实现这样速度会快</td>
</tr>
<tr>
<td><code>sendfile off;</code></td>
<td>off</td>
<td>http、server、location</td>
<td>是否使用sendfile()传输文件，可大大提高Nginx处理静态资源的性能，会额外消耗一些内存，无法传输动态文件，因为是跨过用户态直接从内核态复制文件，注意权限问题</td>
</tr>
<tr>
<td><code>tcp_nopush off;</code></td>
<td>off</td>
<td>http、server、location</td>
<td>sendfile打开才会生效，包在缓存区满了才会发</td>
</tr>
<tr>
<td><code>tcp_nodelay on;</code></td>
<td>on</td>
<td>http、server、location</td>
<td>keep-alive打开才会生效，有包就发</td>
</tr>
<tr>
<td><code>keepalive_timeout 75s;</code></td>
<td>75s</td>
<td>http、server、location</td>
<td>tcp长连接超时时间</td>
</tr>
<tr>
<td><code>keepalive_requests 100;</code></td>
<td>100</td>
<td>http、server、location</td>
<td>每个tcp长连接的复用次数</td>
</tr>
</tbody>
</table>
<div class="info custom-block"><p class="custom-block-title">[🧪Example]</p>
<p>直接返回简单的字符</p>
<div class="language-txt vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">txt</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>location /get_text {</span></span>
<span class="line"><span>	#这里也可以设置成text/plain</span></span>
<span class="line"><span>    default_type text/html;</span></span>
<span class="line"><span>    return 200 "This is nginx's text";</span></span>
<span class="line"><span>}</span></span>
<span class="line"><span>location /get_json{</span></span>
<span class="line"><span>    default_type application/json;</span></span>
<span class="line"><span>    return 200 '{"name":"TOM","age":18}';</span></span>
<span class="line"><span>}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br></div></div></div>
<h3 id="server块" tabindex="-1">server块 <a class="header-anchor" href="#server块" aria-label="Permalink to &quot;server块&quot;">&ZeroWidthSpace;</a></h3>
<div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">server</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> {</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    listen</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">       80</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 监听什么端口</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    server_name</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">  localhost</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 监听哪个域名</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    location</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> /</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> {</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 访问的哪个资源</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        root</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">   html</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 资源的根目录</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        index</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">  index.html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> index.htm</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 从前往后找，优先返回</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">   </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    error_page</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">   500</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 502</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 503</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 504</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 404</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">  /50x.html</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 捕捉状态码进行处理</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    location</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> =</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> /50x.html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> {</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 直接访问500页面的时候会返回首页</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        root</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">   html</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br></div></div><p><code>listen</code>只能在server块里面设置后面参数有很多，使用的时候可以去<a href="http://nginx.org/en/docs/http/ngx_http_core_module.html" target="_blank" rel="noreferrer">文档</a>看</p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>listen 127.0.0.1:8000; 监听指定的IP和端口</span></span>
<span class="line"><span>listen 127.0.0.1;	监听指定IP的所有端口</span></span>
<span class="line"><span>listen 8000;	监听指定端口上的连接</span></span>
<span class="line"><span>listen *:8000;	监听指定端口上的连接</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br></div></div><p>一般配合<code>server_name</code>使用， 唯一确定访问host</p>
<div class="warning custom-block"><p class="custom-block-title">[⚠️Warning]</p>
<p><code>listen 8080 default_server;</code>default_server 标志此为一个默认服务期<br>
当匹配不到指定的server_name的时候，会使用以下策略(不指定服务器 <code>server_name __;</code> )</p>
<ul>
<li>没有匹配的 <code>server_name</code> 时，会使用默认服务器处理该请求。</li>
<li>没有匹配的 <code>server_name</code> 且没有指定默认服务器，Nginx 将选择配置文件中的第一个 <code>server</code> 块来处理请求。</li>
</ul>
</div>
<p><code>server_name  name</code> 配置可以匹配多个用空格隔开，精确匹配通配符正则表达式都支持<br>
使用通配符的时候， 可以出现在前缀和后缀，<code>*.name.*</code> 但是不能<code>www.name.c*</code><br>
使用<code>~</code>作为正则表达式字符串的开始标记，比如<code>~^www\.(\w+)\.com$</code></p>
<p><code>server_name</code>的优先级问题</p>
<ol>
<li>精确匹配server_name</li>
<li>通配符在前缀匹配server_name成功</li>
<li>通配符在后缀匹配server_name成功</li>
<li>正则表达式匹配server_name成功</li>
<li>被默认的default_server处理，如果没有指定默认找第一个server</li>
</ol>
<h3 id="location块" tabindex="-1">location块 <a class="header-anchor" href="#location块" aria-label="Permalink to &quot;location块&quot;">&ZeroWidthSpace;</a></h3>
<p>单独拿出来好看</p>
<div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">location</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> /</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> {</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 访问的哪个资源</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    root</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">   html</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 资源的根目录</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    index</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">  index.html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> index.htm</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 从前往后找，优先返回</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br></div></div><p>匹配路径:<br>
默认匹配路径是只要是按照这个开头的就行，相当于<code>/url(.*)</code><br>
= 用于不包含正则表达式的uri前，必须与指定的模式精确匹配，带后缀斜杠关键字参数都不行<br>
<code>~</code> 表示使用正则表达式，并且区分大小写换<code>~*</code>不区分</p>
<p>root 和 alias 都是指定资源路径，root在找不到指定的绝对路径的时候会使用nginx的安装的root路径+资源相对路径，alias只接受绝对路径而且会<mark>无视location的规定</mark>直接访问alias中指定的资源，一般来会和location指定的完全相同，斜杠也是</p>
<table tabindex="0">
<thead>
<tr>
<th>语法</th>
<th>默认值</th>
<th>位置</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>index index.html index2.html</code></td>
<td>index.html</td>
<td>http、server、location</td>
<td>从前往后找，第一个为止</td>
</tr>
<tr>
<td><code>error_page 500=200 http://www.google.com;</code></td>
<td>_</td>
<td>http、server、location</td>
<td>可以配置多个，也是从上往下找匹配，等于号可以更改状态码</td>
</tr>
</tbody>
</table>
<h2 id="日志" tabindex="-1">日志 <a class="header-anchor" href="#日志" aria-label="Permalink to &quot;日志&quot;">&ZeroWidthSpace;</a></h2>
<table tabindex="0">
<thead>
<tr>
<th>语法</th>
<th>默认值</th>
<th>位置</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>access_log /var/log/nginx/access.log name buffer=32k;</code></td>
<td>/var/log/nginx/access.log</td>
<td>http、server、location</td>
<td>日志的拦截规则，main是此日志规则的名字，可与log_format配合，指定日志的格式</td>
</tr>
<tr>
<td><code>log_format name escape=default 'format' ;</code></td>
<td></td>
<td>http</td>
<td>规定日志输出的格式，配合上面使用</td>
</tr>
<tr>
<td>escape用于指定日志中的特殊字符的转义方式。它有三个可选值：</td>
<td></td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
<ul>
<li><code>default</code>: 使用默认转义方式，将特殊字符转义为它们的可见ASCII码表示，比如将换行符转义为<code>\n</code>。</li>
<li><code>json</code>: 将日志转义为JSON格式，这样可以方便地在日志分析工具中解析和使用。</li>
<li><code>none</code>: 不进行任何转义，特殊字符将以原始形式输出。
format中规定了日志具体的每行输出格式，示例<code>'$remote_addr - $remote_user [$time_local] &quot;$request&quot; $status $body_bytes_sent &quot;$http_referer&quot; &quot;$http_user_agent&quot;'</code></li>
</ul>
<h2 id="静态压缩" tabindex="-1">静态压缩 <a class="header-anchor" href="#静态压缩" aria-label="Permalink to &quot;静态压缩&quot;">&ZeroWidthSpace;</a></h2>
<p>算力换带宽</p>
<p><code>ngx_http_gzip_module</code> 会自己启用 <code>ngx_http_gzip_static_module</code>，<code>ngx_http_gunzip_module</code> 需要自己添加，模块引入之后就有新命令可以用了</p>
<table tabindex="0">
<thead>
<tr>
<th>语法</th>
<th>默认值</th>
<th>位置</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>gzip off;</code></td>
<td>off</td>
<td>http、server、location</td>
<td>开启静态资源压缩，只有开启了此模块的其他指令才会起效</td>
</tr>
<tr>
<td><code>gzip_types mime-type;</code></td>
<td>text/html</td>
<td>http、server、location</td>
<td>对指定的类型开启压缩，建议直接指定mime-type就行了，多个值空格分开也可以用 * 来表示都压缩</td>
</tr>
<tr>
<td><code>gzip_comp_level 1;</code></td>
<td>1</td>
<td>http、server、location</td>
<td>压缩率越大越文件越小CPU占用越高自己权衡</td>
</tr>
<tr>
<td><code>gzip_vary off;</code></td>
<td>off</td>
<td>http、server、location</td>
<td>header中携带Vary:Accept-Encoding;告诉此响应已压缩过</td>
</tr>
<tr>
<td><code>gzip_buffers 23k</code></td>
<td></td>
<td>http、server、location</td>
<td>缓冲区参数，不用自己设置，会根据系统自动设置</td>
</tr>
<tr>
<td><code>gzip_disable -;</code></td>
<td>-</td>
<td>http、server、location</td>
<td>设置一个正则，UA符合此正则的就不启用gzip，此举是为了低版本浏览器不支持gzip时可禁用,或者移动端压缩pc不压缩节省流量。不建议自己设置</td>
</tr>
<tr>
<td><code>gzip_http_version 1.1;</code></td>
<td>1.1</td>
<td>http、server、location</td>
<td>使用gzip的最低http版本</td>
</tr>
<tr>
<td><code>gzip_min_length 20;</code></td>
<td>20(Bytes)</td>
<td>http、server、location</td>
<td>小于此字节的不压缩</td>
</tr>
<tr>
<td><code>gzip_proxied off;</code></td>
<td>off</td>
<td>http、server、location</td>
<td>作为反向代理服务器的时候是否对服务器返回至此的内容压缩再返回</td>
</tr>
</tbody>
</table>
<div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">gzip_proxied的选项值</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">off</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 不启用</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">any</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 启用压缩</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">expired</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # header头中包含 "Expires" 的时候启用压缩</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">no-cache</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # header头中包含 "Cache-Control:no-cache" 的时候启用压缩</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">no-store</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # header头中包含 "Cache-Control:no-store" 的时候启用压缩</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">private</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # header头中包含 "Cache-Control:private" 的时候启用压缩</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">no_last_modified</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # header头中不包含 "Last-Modified" 的时候启用压缩</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">no_etag</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # header头中不包含 "ETag" 的时候启用压缩</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">auth</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # header头中包含 "Authorization" 的时候启用压缩</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br></div></div><div class="warning custom-block"><p class="custom-block-title">[⚠️Warning]</p>
<p>sendfile()跨过用户态直接从内核态复制文件,但是Gzip要想对资源压缩，是需要经过用户进程进行操作的，会冲突。
如果响应的内容是可压缩的（如文本文件），NGINX会将内容进行gzip压缩，否则就正常通过sendfile发送包。<br>
如果要解决这个冲突需要在编译的时候指定插件，配置<code>ngx_http_gzip_static_module</code>的<code>gzip_static</code>命令解决，先把资源一次性压缩完放那，gzip会直接拿，此时头信息里面也会多两个信息指定<code>Content-Encoding: gzip;</code> <code>Vary:Accept-Encoding;</code></p>
</div>
<h2 id="缓存" tabindex="-1">缓存 <a class="header-anchor" href="#缓存" aria-label="Permalink to &quot;缓存&quot;">&ZeroWidthSpace;</a></h2>
<p>nginx主要是设置浏览器缓存，服务器缓存不在这讨论
<img src="./static/Nginx-EP2_images_1.png" alt=""></p>
<table tabindex="0">
<thead>
<tr>
<th>header</th>
<th>说明 HTTP协议中和页面缓存相关的字段</th>
</tr>
</thead>
<tbody>
<tr>
<td>Expires</td>
<td>缓存过期的日期和时间</td>
</tr>
<tr>
<td>Cache-Control</td>
<td>设置和缓存相关的配置信息</td>
</tr>
<tr>
<td>Last-Modified</td>
<td>请求资源最后修改时间</td>
</tr>
<tr>
<td>ETag</td>
<td>请求变量的实体标签的当前值，比如文件的MD5值</td>
</tr>
</tbody>
</table>
<table tabindex="0">
<thead>
<tr>
<th>语法</th>
<th>默认值</th>
<th>位置</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>expires off;</code></td>
<td>off</td>
<td>http、server、location</td>
<td>如果直接写整数值以秒计数，负数就不缓存;epoch或max会把Cache-Control的值设置为no-cache或者10年</td>
</tr>
<tr>
<td><code>add_header Cache-control no-cache always;</code></td>
<td>-</td>
<td>http、server、location</td>
<td>自定义添加头信息，always代表不检查兼容直接添加</td>
</tr>
</tbody>
</table>
<table tabindex="0">
<thead>
<tr>
<th>Cache-Control作为响应头</th>
<th>可以设置如下值</th>
</tr>
</thead>
<tbody>
<tr>
<td>Cache-control: must-revalidate</td>
<td>可缓存但必须再向源服务器进行确认</td>
</tr>
<tr>
<td>Cache-control: no-cache</td>
<td>缓存前必须确认其有效性</td>
</tr>
<tr>
<td>Cache-control: no-store</td>
<td>不缓存请求或响应的任何内容</td>
</tr>
<tr>
<td>Cache-control: no-transform</td>
<td>代理不可更改媒体类型</td>
</tr>
<tr>
<td>Cache-control: public</td>
<td>可向任意方提供响应的缓存</td>
</tr>
<tr>
<td>Cache-control: private</td>
<td>仅向特定用户返回响应</td>
</tr>
<tr>
<td>Cache-control: proxy-revalidate</td>
<td>要求中间缓存服务器对缓存的响应有效性再进行确认</td>
</tr>
<tr>
<td>Cache-control: max-age=&lt;秒&gt;</td>
<td>响应最大Age值</td>
</tr>
<tr>
<td>Cache-control: s-maxage=&lt;秒&gt;</td>
<td>公共缓存服务器响应的最大Age值</td>
</tr>
</tbody>
</table>
<h2 id="跨域" tabindex="-1">跨域 <a class="header-anchor" href="#跨域" aria-label="Permalink to &quot;跨域&quot;">&ZeroWidthSpace;</a></h2>
<h3 id="cors" tabindex="-1">CORS <a class="header-anchor" href="#cors" aria-label="Permalink to &quot;CORS&quot;">&ZeroWidthSpace;</a></h3>
<p>跨域是最基本的浏览器安全服务没有甚至会崩溃，跨域需要<strong>被访问的服务</strong>配置头信息，不仅要在服务框架中配置还要在网关中配置<br>
<code>add_header Access-Control-Allow-Origin *;</code>  允许哪些URI跨域访问服务，多个可以用逗号<code>add_header Access-Control-Allow-Methods GET,POST,PUT,DELETE;</code> 允许哪些方法访问，</p>
<p>下面三个看看知道就行，用的时候再看</p>
<ol>
<li><code>add_header 'Access-Control-Allow-Headers' 'Origin, X-Requested-With, Content-Type, Accept, Authorization'</code>: 这个配置指定了允许跨域请求携带的额外头信息。这些头信息在跨域请求时需要进行预检（OPTIONS请求）来确认是否允许。常见的头信息包括Origin、X-Requested-With、Content-Type、Accept和Authorization等。这里我们允许请求携带这些头信息。</li>
<li><code>add_header 'Access-Control-Allow-Credentials' 'true'</code>: 这是一个可选配置。如果你的跨域请求需要携带认证信息（如cookies或HTTP认证），则需要将该配置设置为true。如果不需要携带认证信息，则可以省略此配置，默认值为false。</li>
<li><code>add_header 'Access-Control-Max-Age' 3600</code>: 这是一个可选配置，用于设置预检请求（OPTIONS请求）的缓存时间，单位为秒。预检请求是浏览器在发送真实请求之前发送的检查请求，以确保跨域请求是安全的。通过设置缓存时间，可以减少不必要的预检请求，提高性能。在这里，设置缓存时间为3600秒（1小时）。</li>
</ol>
<div class="warning custom-block"><p class="custom-block-title">[⚠️Warning]</p>
<p>请注意，这些配置仅适用于HTTP响应头，因为跨域访问是由浏览器执行的安全策略。因此，它们只影响浏览器发起的跨域请求。如果你使用其他方式（例如服务器到服务器通信,RPC等），则可能不受这些配置的限制。</p>
</div>
<h3 id="防盗链" tabindex="-1">防盗链 <a class="header-anchor" href="#防盗链" aria-label="Permalink to &quot;防盗链&quot;">&ZeroWidthSpace;</a></h3>
<p>（Hotlinking）使用Referer字段，表明此链接从哪过来的，服务器根据Referer信息来判断是否为信任的，不是则可以返回403(服务端拒绝访问)。</p>
<div class="language-bash vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">server</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> {</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    listen</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 80</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    server_name</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> yourdomain.com</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    location</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> /images/</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> {</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 整个文件夹下的都验证Referer</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        valid_referers</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> none</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> blocked</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> yourdomain.com</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 允许来自yourdomain.com的请求，也可添加多个域名，空格隔开，例如：yourdomain.com example.com</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> ($invalid_referer) {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 403</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        }</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        root</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> /path/to/your/images</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br></div></div><p>配置中的<code>valid_referers</code>是允许什么域名访问，一般的域名可以自己定义，注意none 和blocked代表Referer空或者直接不携带该字段的，配置上了也会允许。<br>
此指令并不直接拦截或者放行，而是更改内置变量<code>$invalid_referer</code>的值，需要判断后自己做处理<br>
更细粒度的控制使用第三方模块<code>ngx_http_accesskey_module</code>，需要了自己去官网找</p>
<h2 id="重定向" tabindex="-1">重定向 <a class="header-anchor" href="#重定向" aria-label="Permalink to &quot;重定向&quot;">&ZeroWidthSpace;</a></h2>
<p>Nginx的<code>rewrite</code>功能通常需要使用PCRE（Perl Compatible Regular Expressions）库但是会自动启用不用额外配置，Nginx使用的是<code>ngx_http_rewrite_module</code> <a href="http://nginx.org/en/docs/http/ngx_http_rewrite_module.html" target="_blank" rel="noreferrer">模块</a></p>
<ul>
<li>重定向浏览器地址会发生变化而转发则不变</li>
<li>一次重定向会产生两次请求而一次转发只会产生一次请求</li>
<li>地址重定向到的页面必须路径而地址转发则不需要</li>
<li>地址重定向因为是两次请求所以request范围内属性不能传递给新页面而地址转发因为是一次请求所以可以传递值</li>
<li>地址转发速度快于地址重定向</li>
</ul>
<table tabindex="0">
<thead>
<tr>
<th>语法</th>
<th>默认值</th>
<th>位置</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>set $var value;</code></td>
<td>-</td>
<td>http、server、location</td>
<td>设置一个变量可以是字符串，变量或者组合，不能与Nginx服务器预设的全局变量同名</td>
</tr>
<tr>
<td><code>if (condition){}</code></td>
<td>-</td>
<td>server、location</td>
<td>判断  = !=</td>
</tr>
<tr>
<td><code>break;</code></td>
<td>-</td>
<td>server、location、if</td>
<td>此命名空间中break之后的指令全都失效</td>
</tr>
<tr>
<td><code>return 200 abc;</code></td>
<td>-</td>
<td>server、location、if</td>
<td>返回此响应就结束了，可以放字符串json也可以直接放一个url可以跳转过去，如果想要展示可以使用default_type去指定</td>
</tr>
<tr>
<td><code>rewrite ^/rew/(url)\w*$ http://baidu.com/?$1=abc</code></td>
<td>-</td>
<td>server、location、if</td>
<td>匹配/rew/url和任意字符，跳转到<code>http://baidu.com/?url=abc</code> 跳转的时候可以使用正则匹配的变量</td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
<p>用法如下</p>
<ul>
<li><code>~</code>代表匹配正则表达式过程中区分大小写，</li>
<li><code>~*</code>代表匹配正则表达式过程中不区分大小写</li>
<li><code>!~</code>和<code>!~*</code>刚好和上面取相反值，如果匹配上返回false,匹配不上返回true</li>
<li><code>-f $document_uri</code>时，如果请求的文件存在返回true，不存在返回false，<code>!f $document_uri</code>返回的状态相反
Rewrite常用全局变量</li>
</ul>
<table tabindex="0">
<thead>
<tr>
<th>变量</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>$http_user_agent</code></td>
<td>用户访问服务的代理信息(如果通过浏览器访问，记录的是浏览器的相关版本信息)</td>
</tr>
<tr>
<td><code>$host</code></td>
<td>访问服务器的server_name值</td>
</tr>
<tr>
<td><code>$document_root</code></td>
<td>当前请求对应location的root值，如果未设置，默认指向Nginx自带html目录所在位置</td>
</tr>
<tr>
<td><code>$content_length</code></td>
<td>请求头中的Content-Length的值</td>
</tr>
<tr>
<td><code>$content_type</code></td>
<td>请求头中的Content-Type的值</td>
</tr>
<tr>
<td><code>$http_cookie</code></td>
<td>客户端的cookie信息，可以通过add_header Set-Cookie 'cookieName=cookieValue'来添加cookie数据</td>
</tr>
<tr>
<td><code>$limit_rate</code></td>
<td>Nginx服务器对网络连接速率的限制，也就是Nginx配置中对limit_rate指令设置的值，默认是0，不限制。</td>
</tr>
<tr>
<td><code>$remote_addr</code></td>
<td>客户端的IP地址</td>
</tr>
<tr>
<td><code>$remote_port</code></td>
<td>客户端与服务端建立连接的端口号</td>
</tr>
<tr>
<td><code>$remote_user</code></td>
<td>客户端的用户名，需要有认证模块才能获取</td>
</tr>
<tr>
<td><code>$scheme</code></td>
<td>访问协议</td>
</tr>
<tr>
<td><code>$server_addr</code></td>
<td>服务端的地址</td>
</tr>
<tr>
<td><code>$server_name</code></td>
<td>客户端请求到达的服务器的名称</td>
</tr>
<tr>
<td><code>$server_port</code></td>
<td>客户端请求到达服务器的端口号</td>
</tr>
<tr>
<td><code>$server_protocol</code></td>
<td>客户端请求协议的版本，比如&quot;HTTP/1.1&quot;</td>
</tr>
<tr>
<td><code>$request_body_file</code></td>
<td>发给后端服务器的本地文件资源的名称</td>
</tr>
<tr>
<td><code>$request_method</code></td>
<td>客户端的请求方式，比如&quot;GET&quot;,&quot;POST&quot;等</td>
</tr>
<tr>
<td><code>$request_filename</code></td>
<td>当前请求的资源文件的路径名</td>
</tr>
<tr>
<td><code>$document_uri</code></td>
<td>当前访问地址的URI，功能和$uri一样，但不带参数</td>
</tr>
<tr>
<td><code>$request_uri</code></td>
<td>当前请求的URI，并且携带请求参数，去除掉ip和端口后的server的唯一资源</td>
</tr>
<tr>
<td><code>$args</code></td>
<td>请求URL中的关键字参数，功能和$query_string一样</td>
</tr>
</tbody>
</table>
<p>可以在日志的format中用</p>
<div class="warning custom-block"><p class="custom-block-title">[⚠️Warning]</p>
<p>if指令在location块中使用时，其影响其他location的原因是因为if条件的判断逻辑是在配置加载时生成的，而不是在每个请求级别上执行的。
当Nginx配置文件加载时，它会解析所有的location块，并对每个location中的if条件进行求值，并为每个location生成对应的判断逻辑。这些判断逻辑在服务器运行期间是静态的，不会随着请求的不同而变化</p>
<div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">server</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> {</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    listen</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 80</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    server_name</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> example.com</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    location</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> /</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> ($uri </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">~*</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> \.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">jpg</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">|</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">png</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">|</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">gif</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">$</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 403</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        }</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        proxy_pass</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> http://backend</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    location</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> /admin</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> ($uri </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">~*</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> \.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">jpg</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">|</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">png</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">|</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">gif</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">$</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 404</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        }</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        proxy_pass</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> http://backend_admin</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br></div></div><p>在上面的配置中，两个location块都有相同的if条件，即匹配URI是否以图片文件结尾。如果有一个请求 &quot;/example.jpg&quot;，它会匹配到两个location块的if条件，即使第一个location块中的if条件返回了403，第二个location块的if条件也会对其进行判断。这会导致最终请求被第二个location块返回404，而不是预期的403。
#TODO <a href="https://blog.csdn.net/zzhongcy/article/details/106146790" target="_blank" rel="noreferrer">阴间的if</a></p>
</div>
<h2 id="反向代理" tabindex="-1">反向代理 <a class="header-anchor" href="#反向代理" aria-label="Permalink to &quot;反向代理&quot;">&ZeroWidthSpace;</a></h2>
<p>正向代理就是客户端和代理服务器是一块的，请求数据的时候，服务器看到的是代理服务器的地址。<br>
反向代理是代理服务器和服务端是一块的，请求数据的时候客户端看到的是统一的代理服务器的地址，常用来做反向代理。<br>
只能在location里面加，注意斜杠的作用</p>
<p><code>proxy_pass</code>，<code>proxy_set_header</code>，<code>proxy_redirect</code></p>
<div class="language-bash vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">location</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> /abc{</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 注意这个location</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        # proxy_pass http://192.168.0.1; </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        # 上面这个相当于访问http://192.168.0.1/abc/index.html</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        # 如果是http://192.168.0.1/aaa，那访问的会是http://192.168.0.1/aaaindex.html</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        proxy_pass</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> http://192.168.0.1/</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 这个相当于访问http://192.168.0.1/index.html</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        proxy_set_header</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> username</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> TOM</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 可以在这里设置带到服务器的任意的头使用$username，可以放在http、server、location</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br></div></div><p>如果location是只有一个根目录，那加不加效果都是一样的</p>
<p><code>proxy_redirect </code>修改301或者302转发过程中的Location。默认值为<code>proxy_redirect default</code></p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>location / {</span></span>
<span class="line"><span>    proxy_pass http://192.168.8.46:8080; #去掉/</span></span>
<span class="line"><span>    proxy_redirect off #修改默认值default为off</span></span>
<span class="line"><span>    }</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br></div></div><p>如果去掉最后的/以后<br>
<code>curl -I http://192.168.8.46/haha4</code><br>
访问会显示 <code>Location: http://192.168.8.46:8080/haha4/</code><br>
浏览器访问显示的地址栏为<code>http://192.168.8.46:8080/haha4/</code>，(如果还是之前的，需要先删缓存)<br>
真实的Location地址全部暴露出来的，这个时候就需要使用proxy_redirect修改这个Location</p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>location / {</span></span>
<span class="line"><span>    proxy_pass http://192.168.8.46:8080;</span></span>
<span class="line"><span>    proxy_redirect http://192.168.8.46:8080/haha4/ http://192.168.8.46/haha4/;</span></span>
<span class="line"><span>}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br></div></div><p>这样，就能修改Location的地址，<code>Location: http://192.168.8.46/haha4/</code>，在浏览器里也是如此，就不会暴露端口号等信息，当然你还可以直接重定向Location弄到其它网站上去<br>
<code>proxy_redirect http://192.168.8.46:8080/haha4/;</code> 然后浏览器就跳转过去了</p>
<h2 id="ssl证书" tabindex="-1">SSL证书 <a class="header-anchor" href="#ssl证书" aria-label="Permalink to &quot;SSL证书&quot;">&ZeroWidthSpace;</a></h2>
<p>一般的安全控制策略是nginx将不同的请求转发到不同的服务器端口，服务器防火墙只开放应用端口就可以，维护nginx网关而不是服务器。<br>
Nginx的模块是没有添加http_ssl_module的，需要自己手动编译添加(docker的镜像应该有的)<br>
基本所有的命令都是在<code>http,server</code>块中配置</p>
<div class="language-bash vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">server</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">{</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    listen</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 443</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> ssl</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 等于 ssl on; </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    server_name</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> e.ooowl.fun</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 监听的域名</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    ssl_certificate</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> server.cert</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    ssl_ceritificate_key</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> server.key</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 这个后缀一般是key，另一个不一定是啥</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    ssl_session_timeout</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 5m</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># session缓存的超时时间</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    ssl_ciphers</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> HIGH:!aNULL:!MD5</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 指出允许的密码，密码指定为OpenSSL支持的格式</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    ssl_perfer_server_ciphers</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> off</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 指定是否服务器密码优先客户端密码 </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    ssl_session_cache</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> none</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 见下面详解</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    location</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> /</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> {</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        root</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">   html</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        index</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">  index.html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> index.htm</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br></div></div><table tabindex="0">
<thead>
<tr>
<th>语法</th>
<th>ssl_sesion_cache off|none|[builtin[:size]] [shared:name:size]</th>
</tr>
</thead>
<tbody>
<tr>
<td>默认值</td>
<td>ssl_session_cache none;</td>
</tr>
<tr>
<td>位置</td>
<td>http、server</td>
</tr>
</tbody>
</table>
<ul>
<li>off:禁用会话缓存，客户端不得重复使用会话</li>
<li>none:禁止使用会话缓存，客户端可以重复使用，但是并没有在缓存中存储会话参数</li>
<li>builtin:内置OpenSSL缓存，仅在一个工作进程中使用。</li>
<li>shared:所有工作进程之间共享缓存，缓存的相关信息用name和size来指定</li>
</ul>
<p>可以建立一个监听80端口的,然后通过rewrite重定向到https</p>
<div class="language-bash vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">server</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> {</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">	listen</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">	80</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">	server_name</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> e.ooowl.fun</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">	access_log</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> logs/access.log</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> main</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">	location</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> /</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> {</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">		rewrite</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> ^</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">.</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">*</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">https://e.ooowl.fun</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">$1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 重定向</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">	}</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br></div></div><p>证书申请下来就有两个文件<code>server.key</code>,<code>server.cert</code>，分别配置就好，证书不会随着ip或者机器变化而变化，证书有子域名，泛域名证书，可以使用acme.sh进行 <a href="https://github.com/acmesh-official/acme.sh" target="_blank" rel="noreferrer">证书自动续期</a>  ，也可以使用certbot</p>
<details class="details custom-block"><summary>我自己配置文件的一个例子</summary>
<p>我自己配置文件的一个例子</p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>server {</span></span>
<span class="line"><span>  # nps管理端口;</span></span>
<span class="line"><span>  server_name e.ooowl.fun;</span></span>
<span class="line"><span>  listen 443 ssl http2;</span></span>
<span class="line"><span>  ssl_certificate /home/nginxWebUI/.acme.sh/chain.cer;</span></span>
<span class="line"><span>  ssl_certificate_key /home/nginxWebUI/.acme.sh/fun.key;</span></span>
<span class="line"><span>  ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;</span></span>
<span class="line"><span>  listen 80;</span></span>
<span class="line"><span>  if ($scheme = http) {</span></span>
<span class="line"><span>    return 301 https://$host:443$request_uri;</span></span>
<span class="line"><span>  }</span></span>
<span class="line"><span>  location / {</span></span>
<span class="line"><span>    proxy_pass http://127.0.0.1:800006;</span></span>
<span class="line"><span>    proxy_set_header Host $host;</span></span>
<span class="line"><span>    proxy_set_header X-Real-IP $remote_addr;</span></span>
<span class="line"><span>    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;</span></span>
<span class="line"><span>    proxy_set_header X-Forwarded-Host $http_host;</span></span>
<span class="line"><span>    proxy_set_header X-Forwarded-Port $server_port;</span></span>
<span class="line"><span>    proxy_set_header X-Forwarded-Proto $scheme;</span></span>
<span class="line"><span>    proxy_redirect http:// https://;</span></span>
<span class="line"><span>  }</span></span>
<span class="line"><span>}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br></div></div></details>
<h2 id="cheatsheet" tabindex="-1">CheatSheet <a class="header-anchor" href="#cheatsheet" aria-label="Permalink to &quot;CheatSheet&quot;">&ZeroWidthSpace;</a></h2>
<p>经常想要跑一个nginx做测试或者展示，还要现扒配置，索性存一份</p>
<details class="details custom-block"><summary>启动之前执行setup创建映射出来的文件</summary>
<p>动之前执行setup创建映射出来的文件</p>
<div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#!/bin/bash</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 创建目录</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">mkdir</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -p</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> nginx_html/html</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> conf.d</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">mkdir</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> nginx_logs</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 创建 html/index.html</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">echo</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "hello world"</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> ></span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> nginx_html/html/index.html</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 创建 nginx.conf</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">cat</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> ></span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> nginx.conf</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> &#x3C;&#x3C;</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 'EOF'</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">user  nginx;</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">worker_processes  auto;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">error_log  /var/log/nginx/error.log notice;</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">pid        /run/nginx.pid;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">events {</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    worker_connections  1024;</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">http {</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    include       /etc/nginx/mime.types;</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    default_type  application/octet-stream;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">                      '$status $body_bytes_sent "$http_referer" '</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">                      '"$http_user_agent" "$http_x_forwarded_for"';</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    access_log  /var/log/nginx/access.log  main;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    sendfile        on;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    keepalive_timeout  65;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    include /etc/nginx/conf.d/*.conf;</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">}</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">EOF</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 创建 conf.d/default.conf</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">cat</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> ></span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> conf.d/default.conf</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> &#x3C;&#x3C;</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 'EOF'</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">server {</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    listen       80;</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    listen  [::]:80;</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    server_name  localhost;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    location / {</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">        root   /usr/share/nginx/html;</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">        index  index.html index.htm;</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    error_page   500 502 503 504  /50x.html;</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    location = /50x.html {</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">        root   /usr/share/nginx/html;</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    }</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">}</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">EOF</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 创建 docker-compose.yaml</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">cat</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> ></span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> docker-compose.yaml</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> &#x3C;&#x3C;</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 'EOF'</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">services:</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">  test-nginx:</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    image: nginx:latest</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    container_name: test-nginx</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    ports:</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">      - "8080:80"</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    volumes:</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">      - ./nginx.conf:/etc/nginx/nginx.conf</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">      - ./conf.d:/etc/nginx/conf.d</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">      - ./nginx_html:/usr/share/nginx</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">EOF</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br><span class="line-number">50</span><br><span class="line-number">51</span><br><span class="line-number">52</span><br><span class="line-number">53</span><br><span class="line-number">54</span><br><span class="line-number">55</span><br><span class="line-number">56</span><br><span class="line-number">57</span><br><span class="line-number">58</span><br><span class="line-number">59</span><br><span class="line-number">60</span><br><span class="line-number">61</span><br><span class="line-number">62</span><br><span class="line-number">63</span><br><span class="line-number">64</span><br><span class="line-number">65</span><br><span class="line-number">66</span><br><span class="line-number">67</span><br><span class="line-number">68</span><br><span class="line-number">69</span><br><span class="line-number">70</span><br><span class="line-number">71</span><br></div></div></details>
<details class="details custom-block"><summary>docker-compose.yaml</summary>
<p>ocker-compose.yaml</p>
<div class="language-yaml vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">yaml</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">services</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">  test-nginx</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">    image</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">nginx:latest</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">    container_name</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">test-nginx</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">    ports</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      - </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"8080:80"</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">    volumes</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      - </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">./nginx.conf:/etc/nginx/nginx.conf</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      - </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">./conf.d:/etc/nginx/conf.d</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      - </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">./nginx_html:/usr/share/nginx</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br></div></div></details>
<details class="details custom-block"><summary>nginx.conf</summary>
<p>ginx.conf</p>
<div class="language-nginx vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">nginx</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">user </span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> nginx;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">worker_processes </span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> auto;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">error_log </span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> /var/log/nginx/error.log </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">notice</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">pid </span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">       /run/nginx.pid;</span></span>
<span class="line"></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">events</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    worker_connections </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1024</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">http</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    include </span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      /etc/nginx/mime.types;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    default_type </span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> application/octet-stream;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    log_format </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> main</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">  '$</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">remote_addr</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> - $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">remote_user</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> [$</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">time_local</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">] "$</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">request</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">" '</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">                      '$</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">status</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> $</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">body_bytes_sent</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "$</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">http_referer</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">" '</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">                      '"$</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">http_user_agent</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">" "$</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">http_x_forwarded_for</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    access_log </span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> /var/log/nginx/access.log  </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">main</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    sendfile </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">       on</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    #tcp_nopush     on;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    keepalive_timeout </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 65</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    #gzip  on;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    include </span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">/etc/nginx/conf.d/*.conf;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br></div></div></details>
<details class="details custom-block"><summary>conf.d/default.conf</summary>
<p>onf.d/default.conf</p>
<div class="language-nginx vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">nginx</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">server</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    listen </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">      80</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    listen </span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> [::]:80;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    server_name </span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> localhost;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    #access_log  /var/log/nginx/host.access.log  main;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    location</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> / </span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        root </span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  /usr/share/nginx/html;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        index </span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> index.html index.htm;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    #error_page  404              /404.html;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    # redirect server error pages to the static page /50x.html</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    #</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    error_page </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">  500</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 502</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 503</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 504</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  /50x.html;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    location</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#032F62;--shiki-dark:#DBEDFF"> /50x.html </span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        root </span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  /usr/share/nginx/html;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    # proxy the PHP scripts to Apache listening on 127.0.0.1:80</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    #</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    #location ~ \.php$ {</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    #    proxy_pass   http://127.0.0.1;</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    #}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    #</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    #location ~ \.php$ {</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    #    root           html;</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    #    fastcgi_pass   127.0.0.1:9000;</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    #    fastcgi_index  index.php;</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    #    include        fastcgi_params;</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    #}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    # deny access to .htaccess files, if Apache's document root</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    # concurs with nginx's one</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    #</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    #location ~ /\.ht {</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    #    deny  all;</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    #}</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br></div></div></details>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Nginx-EP1]]></title>
            <link>http://ooowl.fun/blogs/Web%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/%E7%BD%91%E5%85%B3/Nginx-EP1.html</link>
            <guid isPermaLink="false">http://ooowl.fun/blogs/Web%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/%E7%BD%91%E5%85%B3/Nginx-EP1.html</guid>
            <pubDate>Tue, 25 Jul 2023 15:26:57 GMT</pubDate>
            <content:encoded><![CDATA[<h1 id="nginx-ep1" tabindex="-1">Nginx-EP1 <a class="header-anchor" href="#nginx-ep1" aria-label="Permalink to &quot;Nginx-EP1&quot;">&ZeroWidthSpace;</a></h1><p class="article-meta">创建于 2023年7月25日 23:26:57 · 约524字</p>
<h2 id="nginx的基础介绍" tabindex="-1">NGINX的基础介绍 <a class="header-anchor" href="#nginx的基础介绍" aria-label="Permalink to &quot;NGINX的基础介绍&quot;">&ZeroWidthSpace;</a></h2>
<p><a href="https://segmentfault.com/a/1190000023050141" target="_blank" rel="noreferrer">webserver的历史</a>，没事看看就当看营销号了，nginx默认使用多进程复用CGI<br>
<a href="http://nginx.org/en/" target="_blank" rel="noreferrer">Nginx开源版</a><br>
Nginx plus商业版,开箱即用但是要付钱，集成了一些功能。<br>
<a href="https://openresty.org/cn/" target="_blank" rel="noreferrer">Open Resty</a> OpenResty是一个基于Nginx与 Lua 的高性能 Web 平台，其内部集成了大量精良的 Lua 库、第三方模块以及大多数的依赖项。<strong>更适用于需要大量二次开发的场景，有极强的扩展性</strong><br>
<a href="https://tengine.taobao.org/" target="_blank" rel="noreferrer">Tengine</a> 淘宝定制的nginx版本，添加了很多特性，- 相比于Open Resty，扩展性不够强，但是能够满足绝多数使用场景<br>
<a href="https://www.nginx.org.cn/" target="_blank" rel="noreferrer">nginx中文开源社区</a></p>
<p>源码编译安装需要的依赖gcc PCRE zlib OpenSSL<br>
<code>nginx -v/V</code> 获得版本(详细信息，包括编译的时候指定的各种路径等)<br>
如果要删除的话需要先关闭nginx，再删除本体，最后清理编译环境</p>
<h3 id="一些路径" tabindex="-1">一些路径: <a class="header-anchor" href="#一些路径" aria-label="Permalink to &quot;一些路径:&quot;">&ZeroWidthSpace;</a></h3>
<ul>
<li>源码安装的时候会安装到<code>/usr/local/nginx</code></li>
<li>使用包管理器安装的话安装在<code>/etc/nginx</code></li>
<li>日志默认在<code>/logs/access.log</code>,<code>/logs/error.log</code></li>
<li>默认的 PID 文件路径通常为：<code>/var/run/nginx.pid</code>，cat这个会返回nginx的进程好</li>
<li>默认的锁文件路径为：<code>/var/run/nginx.lock</code></li>
</ul>
<h4 id="目录功能" tabindex="-1">目录功能 <a class="header-anchor" href="#目录功能" aria-label="Permalink to &quot;目录功能&quot;">&ZeroWidthSpace;</a></h4>
<div class="language-C vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">C</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">/</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">etc</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">/</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">nginx</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">├── conf.d # 被include的配置文件</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">│   └── default.conf # 初始化自带默认配置文件</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">├── fastcgi.conf # CGI的各种配置文件，建议cgi类的文件提前复制一次，后缀改为default备份  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">├── fastcgi_params</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">├── koi</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">utf</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">├── koi</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">win</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">├── mime.types # 记录了所有的类型配置头文件的时候用的上</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">├── modules</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">available</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">├── modules</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">enabled</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">│   ├── </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">50</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">mod</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">http</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">geoip2.conf...</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">│   └── ...</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">├── nginx.conf # 总的配置文件</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">├── proxy_params</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">├── scgi_params</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">├── sites</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">available</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">│   └── default</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">├── sites</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">enabled</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">│   └── default </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-></span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> /</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">etc</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">/</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">nginx</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">/</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">sites</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">available</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">/</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">default</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">├── snippets</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">│   ├── fastcgi</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">php.conf</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">│   └── snakeoil.conf</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">├── uwsgi_params</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">└── win</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">utf</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br></div></div><p><code>/usr/share/nginx</code> 下面还有一些文件，html是默认配置w文件读取网页的地方</p>
<div class="language-C vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">C</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">/</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">usr</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">/</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">share</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">/</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">nginx</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">├── html # 默认的网页文件夹</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">│   └── index.html</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">├── modules </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> ..</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">/</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">..</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">/</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">lib</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">/</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">nginx</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">/</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">modules</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">└── modules</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">available</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    ├── ...</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    └── mod</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">stream</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">geoip2.conf</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br></div></div><p><code>/usr/sbin/nginx</code>，<code>/sbin/nginx</code> 是nginx的程序执行文件</p>
<h2 id="命令" tabindex="-1">命令 <a class="header-anchor" href="#命令" aria-label="Permalink to &quot;命令&quot;">&ZeroWidthSpace;</a></h2>
<h3 id="使用linux命令" tabindex="-1">使用linux命令 <a class="header-anchor" href="#使用linux命令" aria-label="Permalink to &quot;使用linux命令&quot;">&ZeroWidthSpace;</a></h3>
<p>此方式依赖nginx的pid文件默认是从/run/nginx.pid来读取的。如果你另外配置了nginx的pid的文件的位置，则会导致命令执行失败。报错信息为：</p>
<div class="language-js vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">nginx</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: [error] </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">open</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">() </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"/var/run/nginx.pid"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> failed</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: No such file or directory)</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p>此时就必须用拿到PID并发送信号<br>
nginx 的命令很少</p>
<div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">nginx</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -g</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "daemon on;"</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 使用守护进程模式启动nginx，即不在控制台打印日志，默认是on，可以手动使用off启动</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">nginx</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -s</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> quit</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 优雅停止nginx，nginx会等待所有请求处理完毕后才停止</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">nginx</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -s</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> stop</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 快速停止nginx，不等待请求是否处理完毕</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">nginx</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -s</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> reload</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">配置文件修改完，reload加载新的配置。</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">当执行此命令时，nginx会检查配置文件的语法并尝试使用新的配置</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">如果成功，nginx将会以新的配置启动新的工作进程，并向旧的工作进程发送关闭信号</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">否则，主进程回滚更改并继续使用旧的配置和旧的工作进程。当旧进程收到关闭信号后，它将会停止接受新的请求，并在处理完旧请求的自行退出。</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">nginx</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -s</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> reopen</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 更改滚动日志句柄</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">nginx</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -t/T</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 检查所有的配置文件是否合法</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 如果用T的话会返回成功的文件内容，又臭又长</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">nginx</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -c</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 指定文件路径</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br></div></div><div class="tip custom-block"><p class="custom-block-title">[💡Tip]</p>
<p>更改滚动日志句柄这在我们的日志文件过大时，我们将日志文件mv后，发现日志文件仍在写入，这是由于mv后的文件inode相关信息不变，进行还会将日志写入到该文件中。这时我们就可以执行reopen操作，nginx就会关闭原来的句柄，在配置的日志目录下重新创建新的日志文件来进行日志记录。</p>
</div>
<p>其他的不是很常用</p>
<h3 id="服务信号" tabindex="-1">服务信号 <a class="header-anchor" href="#服务信号" aria-label="Permalink to &quot;服务信号&quot;">&ZeroWidthSpace;</a></h3>
<p>此方式进行起停，通过向master发送信号控制</p>
<div class="language-mermaid vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">mermaid</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">graph LR</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  A[管理员] -->|控制| B(Master分配请求)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  B -->|管理| C(Worker1处理)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  B -->|管理| D(Worker2处理)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  B -->|管理| E(Worker3处理)</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br></div></div><p>使用信号控制Master<br>
<code>ps -ef | grep nginx</code> 查看nginx 的所有进程，发送信号需要发送给master</p>
<div class="language-bash vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">kill</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -信号</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> PID</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">-</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> TERM,</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> INT</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 作用和</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> nginx</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -s</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> stop一致</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">也可kill</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -9</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> PID</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">-</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> QUIT</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 作用和</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> nginx</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -s</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> quit一致</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">-</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> HUP</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 作用和</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> nginx</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -s</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> reload一致</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">-</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> USR1</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 作用和</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> nginx</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -s</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> reopen一致</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">-</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> USR2</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 平滑升级</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">用到了再去看，基本原理就是把PID开副本，升级完了在换回来，只替换sbin的nginx执行文件就行了</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br></div></div><h2 id="祖传的pagespeed" tabindex="-1">祖传的pagespeed <a class="header-anchor" href="#祖传的pagespeed" aria-label="Permalink to &quot;祖传的pagespeed&quot;">&ZeroWidthSpace;</a></h2>
<p>使用google的pagespeed 优化nginx提高网页访问速度</p>
<div class="language-nginx vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">nginx</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 先放师哥的祖传优化配置，单体绝对够用的，在框架和DB出现瓶颈之前它绝对不会出瓶颈</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">user </span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">root;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">worker_processes </span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">auto;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">pid </span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">/run/nginx.pid;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># include /etc/nginx/modules-enabled/*.conf;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">events</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">   worker_connections </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">16383</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">   # multi_accept on;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">http</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">   ##  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">   # Basic Settings   ##  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">   sendfile </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">on</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">   client_max_body_size </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">256m</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">   tcp_nopush </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">on</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">   tcp_nodelay </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">on</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">   keepalive_timeout </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">65</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">   types_hash_max_size </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">2048</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">   # server_tokens off;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">   # server_names_hash_bucket_size 64;   # server_name_in_redirect off;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">   include </span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">/etc/nginx/mime.types;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">   default_type </span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">application/octet-stream;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">   ##  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">   # SSL Settings   ##  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">   ssl_protocols </span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">TLSv1 TLSv1.1 TLSv1.2; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># Dropping SSLv3, ref: POODLE  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">   ssl_prefer_server_ciphers </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">on</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">   ##  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">   # Logging Settings   ##  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">   access_log </span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">/var/log/nginx/access.log;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">   error_log </span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">/var/log/nginx/error.log;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">   add_header </span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">X-Content-Type-Options </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"nosniff"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">   ##  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">   # Enable PageSpeed   ##  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">   pagespeed</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> on</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">   #启用PageSpeed Gzip请求资源，此项要求ng启用gzip  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">   #pagespeed FetchWithGzip on;  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">   #配置筛选项默认CoreFilters  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">   pagespeed</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> RewriteLevel CoreFilters;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">   #是否尊重原始header，为了达到优化最大效果，官方建议不开启  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">   pagespeed</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> RespectVary </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">off</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">   # ···是否让PageSpeed优化缓存时间（接管缓存控制）  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">   pagespeed</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> DisableRewriteOnNoTransform </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">off</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">   #重写HTML缓存头，官方不建议关闭，默认会统计执行为Cache-Control: no-cache, max-age=0  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">   pagespeed</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> ModifyCachingHeaders </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">on</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">   #列出未解决的错误  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">   pagespeed</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> ListOutstandingUrlsOnError </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">on</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">   # ···限制资源最大值启用优化，默认大小16M  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">   pagespeed</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> MaxCacheableContentLength </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">16777216</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">   # 单个js文件最大大小，配合combine_javascript使用，该数值过小会引起js文件不合并  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">   pagespeed</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> MaxCombinedJsBytes </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">921600</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">   #配置共享内存元数据缓存  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">   pagespeed</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> CreateSharedMemoryMetadataCache </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"/var/cache/pagespeed/"</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 51200</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">   #配置文件高速缓存  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">   pagespeed</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> FileCachePath /var/cache/pagespeed;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">   pagespeed</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> FileCacheSizeKb </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">102400</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">   pagespeed</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> FileCacheCleanIntervalMs </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">3600000</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">   pagespeed</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> FileCacheInodeLimit </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">500000</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">   # 为了优化性能，可以写LRU缓存，nginx使用更少的进程，LRUCacheKbPerProcess可以适当大点  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">   pagespeed</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> LRUCacheKbPerProcess </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">8192</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">   pagespeed</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> LRUCacheByteLimit </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">16384</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">   #缓存清除，比较方便的管理方式是，通过admin页面管理（自己可以通过配置开启）  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">   pagespeed</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> EnableCachePurge </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">on</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">   pagespeed</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> PurgeMethod PURGE;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">   #PageSpeed管理页面配置  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">   #共享内存统计  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">   pagespeed</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Statistics </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">on</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">   #开启虚拟主机统计信息  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">   pagespeed</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> UsePerVhostStatistics </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">on</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">   pagespeed</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> StatisticsLogging </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">on</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">   pagespeed</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> StatisticsLoggingIntervalMs </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">60000</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">   pagespeed</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> StatisticsLoggingMaxFileSizeKb </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1024</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">   #消息缓冲区大小，默认为0，不保留消息  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">   pagespeed</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> MessageBufferSize </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">100000</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">   pagespeed</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> LogDir /var/log/pagespeed;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">   pagespeed</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> StatisticsPath /ngx_pagespeed_statistics;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">   pagespeed</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> GlobalStatisticsPath /ngx_pagespeed_global_statistics;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">   pagespeed</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> MessagesPath /ngx_pagespeed_message;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">   pagespeed</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> ConsolePath /pagespeed_console;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">   pagespeed</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> AdminPath /pagespeed_admin;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">   pagespeed</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> GlobalAdminPath /pagespeed_global_admin;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">   ##  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">   # Gzip Settings   ##  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">   gzip </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">on</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">   gzip_disable </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"msie6"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">   gzip_vary </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">on</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">   gzip_proxied </span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">any;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">   gzip_comp_level </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">6</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">   gzip_buffers </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">16</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 8k</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">   gzip_http_version </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1.1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">   gzip_types </span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">   ##  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">   # Virtual Host Configs   ##  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">   server</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        location</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> / </span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            root </span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  /usr/share/nginx/html;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            index </span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> index.html index.htm;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        }  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        location</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> /api </span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">         rewrite</span><span style="--shiki-light:#032F62;--shiki-dark:#DBEDFF">  ^/api/(.*)$</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> /$1 </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">break</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;   </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">client_max_body_size </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">   20m</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">         proxy_set_header </span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Host $proxy_host;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">         proxy_set_header </span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">X-Real-IP $remote_addr;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">         proxy_set_header </span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">REMOTE-HOST $remote_addr;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">         proxy_set_header </span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">X-Forwarded-For $proxy_add_x_forwarded_for;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">         proxy_pass </span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">http://cda-server:8092/api;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        }  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        location</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> /api/api </span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">         rewrite</span><span style="--shiki-light:#032F62;--shiki-dark:#DBEDFF">  ^/api/(.*)$</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> /$1 </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">break</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;   </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">client_max_body_size </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">   20m</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">         proxy_set_header </span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Host $proxy_host;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">         proxy_set_header </span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">X-Real-IP $remote_addr;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">         proxy_set_header </span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">REMOTE-HOST $remote_addr;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">         proxy_set_header </span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">X-Forwarded-For $proxy_add_x_forwarded_for;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">         proxy_pass </span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">http://cda-server:8092/api;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        }  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">      location</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> /escs </span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">         rewrite</span><span style="--shiki-light:#032F62;--shiki-dark:#DBEDFF">  ^/api/(.*)$</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> /$1 </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">break</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;   </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">client_max_body_size </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">   20m</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">         proxy_set_header </span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Host $proxy_host;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">         proxy_set_header </span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">X-Real-IP $remote_addr;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">         proxy_set_header </span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">REMOTE-HOST $remote_addr;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">         proxy_set_header </span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">X-Forwarded-For $proxy_add_x_forwarded_for;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">         proxy_pass </span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">http://cda-rabbitmq:15672/api/queues/;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        }  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">   }  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br><span class="line-number">50</span><br><span class="line-number">51</span><br><span class="line-number">52</span><br><span class="line-number">53</span><br><span class="line-number">54</span><br><span class="line-number">55</span><br><span class="line-number">56</span><br><span class="line-number">57</span><br><span class="line-number">58</span><br><span class="line-number">59</span><br><span class="line-number">60</span><br><span class="line-number">61</span><br><span class="line-number">62</span><br><span class="line-number">63</span><br><span class="line-number">64</span><br><span class="line-number">65</span><br><span class="line-number">66</span><br><span class="line-number">67</span><br><span class="line-number">68</span><br><span class="line-number">69</span><br><span class="line-number">70</span><br><span class="line-number">71</span><br><span class="line-number">72</span><br><span class="line-number">73</span><br><span class="line-number">74</span><br><span class="line-number">75</span><br><span class="line-number">76</span><br><span class="line-number">77</span><br><span class="line-number">78</span><br><span class="line-number">79</span><br><span class="line-number">80</span><br><span class="line-number">81</span><br><span class="line-number">82</span><br><span class="line-number">83</span><br><span class="line-number">84</span><br><span class="line-number">85</span><br><span class="line-number">86</span><br><span class="line-number">87</span><br><span class="line-number">88</span><br><span class="line-number">89</span><br><span class="line-number">90</span><br><span class="line-number">91</span><br><span class="line-number">92</span><br><span class="line-number">93</span><br><span class="line-number">94</span><br><span class="line-number">95</span><br><span class="line-number">96</span><br><span class="line-number">97</span><br><span class="line-number">98</span><br><span class="line-number">99</span><br><span class="line-number">100</span><br><span class="line-number">101</span><br><span class="line-number">102</span><br><span class="line-number">103</span><br><span class="line-number">104</span><br><span class="line-number">105</span><br><span class="line-number">106</span><br><span class="line-number">107</span><br><span class="line-number">108</span><br><span class="line-number">109</span><br><span class="line-number">110</span><br><span class="line-number">111</span><br><span class="line-number">112</span><br><span class="line-number">113</span><br><span class="line-number">114</span><br><span class="line-number">115</span><br><span class="line-number">116</span><br><span class="line-number">117</span><br><span class="line-number">118</span><br><span class="line-number">119</span><br><span class="line-number">120</span><br><span class="line-number">121</span><br><span class="line-number">122</span><br><span class="line-number">123</span><br><span class="line-number">124</span><br><span class="line-number">125</span><br><span class="line-number">126</span><br><span class="line-number">127</span><br><span class="line-number">128</span><br><span class="line-number">129</span><br><span class="line-number">130</span><br><span class="line-number">131</span><br><span class="line-number">132</span><br><span class="line-number">133</span><br><span class="line-number">134</span><br><span class="line-number">135</span><br><span class="line-number">136</span><br><span class="line-number">137</span><br><span class="line-number">138</span><br><span class="line-number">139</span><br><span class="line-number">140</span><br><span class="line-number">141</span><br><span class="line-number">142</span><br><span class="line-number">143</span><br><span class="line-number">144</span><br><span class="line-number">145</span><br><span class="line-number">146</span><br><span class="line-number">147</span><br><span class="line-number">148</span><br><span class="line-number">149</span><br><span class="line-number">150</span><br><span class="line-number">151</span><br><span class="line-number">152</span><br><span class="line-number">153</span><br><span class="line-number">154</span><br></div></div>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[分库分表]]></title>
            <link>http://ooowl.fun/blogs/Web%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/%E5%AD%98%E5%82%A8%E6%8A%80%E6%9C%AF/%E5%88%86%E5%BA%93%E5%88%86%E8%A1%A8.html</link>
            <guid isPermaLink="false">http://ooowl.fun/blogs/Web%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/%E5%AD%98%E5%82%A8%E6%8A%80%E6%9C%AF/%E5%88%86%E5%BA%93%E5%88%86%E8%A1%A8.html</guid>
            <pubDate>Fri, 24 Feb 2023 15:17:11 GMT</pubDate>
            <content:encoded><![CDATA[<h1 id="分库分表" tabindex="-1">分库分表 <a class="header-anchor" href="#分库分表" aria-label="Permalink to &quot;分库分表&quot;">&ZeroWidthSpace;</a></h1><p class="article-meta">创建于 2023年2月24日 23:17:11 · 约192字</p>
<p>为什么要分库分表
例如 关系型DB的深分页越往后越慢，甚至会有十倍以上的差距20w+条，查询limit100items耗时0.04s，如果offset从20万开始，耗时0.37s<br>
数据量变大的时候或者性能有一定要求的时候，单表单库达不到要求<br>
不分库只分表: 单表过大水平分表
只分库不分表:单库QPS过高读问题，连接不够用，调大连接数+开强一致性的镜像库
既分库又分表：两个问题都出现了</p>
<p>数据库转型需要考虑的问题，数据库是个重状态的服务=改动需要考虑已有数据
水平拓展分库分表or换DB产品
<img src="./static/分库分表_images_1.png" alt="|500"></p>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Uinotes爬虫]]></title>
            <link>http://ooowl.fun/blogs/Python/%E7%88%AC%E8%99%AB/Uinotes%E7%88%AC%E8%99%AB.html</link>
            <guid isPermaLink="false">http://ooowl.fun/blogs/Python/%E7%88%AC%E8%99%AB/Uinotes%E7%88%AC%E8%99%AB.html</guid>
            <pubDate>Fri, 24 Feb 2023 12:55:38 GMT</pubDate>
            <content:encoded><![CDATA[<h1 id="uinotes爬虫" tabindex="-1">Uinotes爬虫 <a class="header-anchor" href="#uinotes爬虫" aria-label="Permalink to &quot;Uinotes爬虫&quot;">&ZeroWidthSpace;</a></h1><p class="article-meta">创建于 2023年2月24日 20:55:38 · 约1,967字</p>
<p>爬这个东西，scrapy扒库+url指定拿取图片<a href="https://uinotes.com/app" target="_blank" rel="noreferrer">App库 - UI Notes</a>
app-&gt;缩略图-&gt;单个大图<br>
现在使用者想一次性获得此APP的大图不用一个一个点<br>
其实用不到框架，但是自己练手把扒站也写了吧</p>
<h2 id="普通爬虫" tabindex="-1">普通爬虫 <a class="header-anchor" href="#普通爬虫" aria-label="Permalink to &quot;普通爬虫&quot;">&ZeroWidthSpace;</a></h2>
<p>需求输入url 下载此app对应的所有大图</p>
<h3 id="分析请求" tabindex="-1">分析请求 <a class="header-anchor" href="#分析请求" aria-label="Permalink to &quot;分析请求&quot;">&ZeroWidthSpace;</a></h3>
<p>首页会重定向，获取是从阿里上海CDN格式暂时没看到在那继续往下看<br>
<img src="./static/Uinotes爬虫_images_1.png" alt="|500">
往下翻页明显是翻页式的，而且是简单的翻页，没带scroll cursor，翻了几十页，没什么问题<br>
<img src="./static/Uinotes爬虫_images_2.png" alt="|800">
看请求头，有自定义的header，但是我并不想弄明白它的header是在干什么，cookie也是直接复制的<br>
注意详情页，获取原图，首页，header并不一样，需要定义三个，我没试出来哪个是必须的。<br>
<img src="./static/Uinotes爬虫_images_3.png" alt="|600"></p>
<p>他的原图是存在阿里云的CDN的，在json里和URL里直接拼接就行
<img src="./static/Uinotes爬虫_images_4.png" alt="|300">
点击查看原图的时候发现会请求alicdn，通过在不同页面保存图片观察变化，分辨率是通过后面的参数确定的<br>
<img src="./static/Uinotes爬虫_images_5.png" alt="|800"></p>
<h3 id="反爬机制" tabindex="-1">反爬机制 <a class="header-anchor" href="#反爬机制" aria-label="Permalink to &quot;反爬机制&quot;">&ZeroWidthSpace;</a></h3>
<p>爬取的过程中发现时不时出现<code>requests.exceptions.ProxyError</code>，时不时会Connect Reset by Peer，就是不定时断线。<br>
while True给他重试一下就行了，10s一次<br>
调试过程中几个小时内请求约3000图片ip就被封禁了 ，在一个多小时候解开了，封禁的时候网页是不能访问的。</p>
<h3 id="代码实现" tabindex="-1">代码实现 <a class="header-anchor" href="#代码实现" aria-label="Permalink to &quot;代码实现&quot;">&ZeroWidthSpace;</a></h3>
<p>使用pickle进行本地的持久化，可以断点续爬<br>
不多说</p>
<details class="details custom-block"><summary>Click to see more</summary>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># -*-coding:utf-8-*-  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># SettingCode here  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">__author__ </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "a_little_rubbish"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">__date__ </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "2023/2/27 09:13"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># import your model here  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> os.path  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> random  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> time  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> typing </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> List  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> requests  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> pickle  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> fastapi </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> FastAPI  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># your class&#x26;function here  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">urls </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> set</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">HEADER</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    'Host'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'uinotes.com'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    'User-Agent'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:109.0) Gecko/20100101 Firefox/110.0'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    'Accept'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    'Accept-Language'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    'Accept-Encoding'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'gzip, deflate, br'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    'Connection'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'keep-alive'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    'Cookie'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'Hm_lvt_24d5bc972e9b9e9b2ba031648f98eceb=1677205860; Hm_lpvt_24d5bc972e9b9e9b2ba031648f98eceb=1677460645; __vtins__JrOcbAvQF047xVR4=%7B</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%22s</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">id</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%22%</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">3A</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%20%</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">22416be1c5-321f-5983-88d5-84f67c028362</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%22%</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">2C</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%20%</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">22vd</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%22%</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">3A</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%205%</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">2C</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%20%</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">22stt</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%22%</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">3A</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%20891664%</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">2C</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%20%</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">22dr</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%22%</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">3A</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%2020210%</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">2C</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%20%</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">22expires</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%22%</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">3A</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%201677462444542%</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">2C</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%20%</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">22ct</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%22%</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">3A</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%201677460644542%</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">7D; __51uvsct__JrOcbAvQF047xVR4=3; __51vcke__JrOcbAvQF047xVR4=6d6af076-7332-536e-b956-d0e63e9a69cf; __51vuft__JrOcbAvQF047xVR4=1677205861743'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    'Upgrade-Insecure-Requests'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'1'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    'Sec-Fetch-Dest'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'document'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    'Sec-Fetch-Mode'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'navigate'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    'Sec-Fetch-Site'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'same-origin'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    'Referer'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'https://uinotes.com/app/146907778227438046'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    'TE'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'trailers'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    'If-None-Match'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'W/"1125-cxIIC4CA1SUrDsKKenx3oU7m8k4"'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">detail_header </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'Accept'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'image/avif,image/webp,*/*'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">                 'Accept-Encoding'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'gzip, deflate, br'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">                 'Accept-Language'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">                 'Host'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'uiwiki4.oss-cn-shanghai.aliyuncs.com'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">                 'Referer'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'https://uinotes.com/'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">                 'User-Agent'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:109.0) Gecko/20100101 Firefox/110.0'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">                 }  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">HEADER_TITLE</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    'Accept'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    'Accept-Encoding'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'gzip, deflate, br'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    'Accept-Language'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    'Connection'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'keep-alive'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    'Cookie'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'Hm_lvt_24d5bc972e9b9e9b2ba031648f98eceb=1677205860; Hm_lpvt_24d5bc972e9b9e9b2ba031648f98eceb=1677467926; __vtins__JrOcbAvQF047xVR4=%7B</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%22s</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">id</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%22%</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">3A</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%20%</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">22826916f9-3ae7-510d-8060-bf72a4852a62</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%22%</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">2C</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%20%</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">22vd</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%22%</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">3A</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%2013%</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">2C</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%20%</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">22stt</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%22%</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">3A</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%203593758%</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">2C</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%20%</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">22dr</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%22%</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">3A</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%20791782%</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">2C</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%20%</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">22expires</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%22%</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">3A</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%201677469725867%</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">2C</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%20%</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">22ct</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%22%</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">3A</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%201677467925867%</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">7D; __51uvsct__JrOcbAvQF047xVR4=4; __51vcke__JrOcbAvQF047xVR4=6d6af076-7332-536e-b956-d0e63e9a69cf; __51vuft__JrOcbAvQF047xVR4=1677205861743'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    'Host'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'uinotes.com'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    'If-None-Match'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'W/"105e-x8xiTTLRwcejqeYiMrKrWBDTS0I"'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    'Sec-Fetch-Dest'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'document'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    'Sec-Fetch-Mode'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'navigate'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    'Sec-Fetch-Site'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'cross-site'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    'Upgrade-Insecure-Requests'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'1'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    'User-Agent'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:109.0) Gecko/20100101 Firefox/110.0'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> write_dumplicate</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">():  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    with</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> open</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'url.pkl'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'wb'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">as</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> f:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        pickle.dump(urls, f)  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 进行序列化  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> save</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(res_list, appname):  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> source </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> res_list:  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        # time.sleep((random.randint(0, 1000)) / 1000)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        url </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "https://uiwiki4.oss-cn-shanghai.aliyuncs.com</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">{image_uid}</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">?x-oss-process=style/title"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.format(  </span></span>
<span class="line"><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">            image_uid</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">source[</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'url'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">])  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> url </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> urls:  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">            print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"此url已存在，跳过"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            continue</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        try</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            res </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> requests.get(url, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">headers</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">detail_header)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            urls.add(url)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        except</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> requests.exceptions.ProxyError:  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">            print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"连接错误，停止10s"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            return</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "break"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        imgsuffix </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> source[</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'url'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">].split(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"/"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x3C;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">br</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">/></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"获取图片："</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, source[</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'imageName'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">] </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> '-'</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> +</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> imgsuffix)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        with</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> open</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">{appname}</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">/</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">{img_name}</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.format(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">appname</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">appname, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">img_name</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">source[</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'imageName'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> '-'</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> +</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> imgsuffix,  </span></span>
<span class="line"><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">                  mode</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'wb'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">as</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> f:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            f.write(res.content)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> spider</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(appurl):  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    appid </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> appurl.split(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'/'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x3C;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">br</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">/></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    page </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"APP</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">{appid}</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">开始"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.format(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">appid</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">appid))  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    while</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> True</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        page </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        HEADER</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'Referer'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">] </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> appurl  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        try</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            res </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> requests.get(  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">                "https://uinotes.com/uinotes-api/app-detail?uuid=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">{appid}</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">&#x26;page=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">{page}</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.format(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">appid</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">appid, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">page</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">page),  </span></span>
<span class="line"><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">                headers</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">HEADER</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        except</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> requests.exceptions.ProxyError:  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">            print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"获取页面错误，暂停10s"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            write_dumplicate()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            time.sleep(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">10</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            page </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            continue</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> res.status_code </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">==</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 204</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">            print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"此APP</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">{appid}</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">结束"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.format(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">appid</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">appid))  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            break</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        res </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> res.json()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        time.sleep((random.randint(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1500</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">/</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1000</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">f</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"获取page </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">{</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">page</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">}</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> : "</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.format(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">page</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">page), res)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        appname </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> res[</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">][</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"appName"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        if</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> not</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> os.path.exists(appname):  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            os.makedirs(appname)  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">            print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"创建文件夹"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, appname)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        single </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> save(res, appname)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> single </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">==</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "break"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            write_dumplicate()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            time.sleep(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">10</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            page </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            continue</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    write_dumplicate()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> main</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(SOURCELIST):  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    if</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> not</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> os.path.exists(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'url.pkl'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">):  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        write_dumplicate()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    with</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> open</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'url.pkl'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'rb'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">as</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> f:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        urls </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> pickle.load(f)  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"上次爬过："</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, urls)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> SOURCELIST</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        spider(i)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">app </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> FastAPI()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">@app.post</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"/"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> root</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(app_url_list: List[</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">str</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]):  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    main(app_url_list)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"message"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"OK"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># nohup python -m  uvicorn main:app --reload > runtime.log 2>&#x26;1 &#x26;</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br><span class="line-number">50</span><br><span class="line-number">51</span><br><span class="line-number">52</span><br><span class="line-number">53</span><br><span class="line-number">54</span><br><span class="line-number">55</span><br><span class="line-number">56</span><br><span class="line-number">57</span><br><span class="line-number">58</span><br><span class="line-number">59</span><br><span class="line-number">60</span><br><span class="line-number">61</span><br><span class="line-number">62</span><br><span class="line-number">63</span><br><span class="line-number">64</span><br><span class="line-number">65</span><br><span class="line-number">66</span><br><span class="line-number">67</span><br><span class="line-number">68</span><br><span class="line-number">69</span><br><span class="line-number">70</span><br><span class="line-number">71</span><br><span class="line-number">72</span><br><span class="line-number">73</span><br><span class="line-number">74</span><br><span class="line-number">75</span><br><span class="line-number">76</span><br><span class="line-number">77</span><br><span class="line-number">78</span><br><span class="line-number">79</span><br><span class="line-number">80</span><br><span class="line-number">81</span><br><span class="line-number">82</span><br><span class="line-number">83</span><br><span class="line-number">84</span><br><span class="line-number">85</span><br><span class="line-number">86</span><br><span class="line-number">87</span><br><span class="line-number">88</span><br><span class="line-number">89</span><br><span class="line-number">90</span><br><span class="line-number">91</span><br><span class="line-number">92</span><br><span class="line-number">93</span><br><span class="line-number">94</span><br><span class="line-number">95</span><br><span class="line-number">96</span><br><span class="line-number">97</span><br><span class="line-number">98</span><br><span class="line-number">99</span><br><span class="line-number">100</span><br><span class="line-number">101</span><br><span class="line-number">102</span><br><span class="line-number">103</span><br><span class="line-number">104</span><br><span class="line-number">105</span><br><span class="line-number">106</span><br><span class="line-number">107</span><br><span class="line-number">108</span><br><span class="line-number">109</span><br><span class="line-number">110</span><br><span class="line-number">111</span><br><span class="line-number">112</span><br><span class="line-number">113</span><br><span class="line-number">114</span><br><span class="line-number">115</span><br><span class="line-number">116</span><br><span class="line-number">117</span><br><span class="line-number">118</span><br><span class="line-number">119</span><br><span class="line-number">120</span><br><span class="line-number">121</span><br><span class="line-number">122</span><br><span class="line-number">123</span><br><span class="line-number">124</span><br><span class="line-number">125</span><br><span class="line-number">126</span><br><span class="line-number">127</span><br><span class="line-number">128</span><br><span class="line-number">129</span><br><span class="line-number">130</span><br><span class="line-number">131</span><br><span class="line-number">132</span><br><span class="line-number">133</span><br><span class="line-number">134</span><br><span class="line-number">135</span><br><span class="line-number">136</span><br><span class="line-number">137</span><br><span class="line-number">138</span><br><span class="line-number">139</span><br><span class="line-number">140</span><br><span class="line-number">141</span><br><span class="line-number">142</span><br><span class="line-number">143</span><br><span class="line-number">144</span><br><span class="line-number">145</span><br><span class="line-number">146</span><br><span class="line-number">147</span><br><span class="line-number">148</span><br><span class="line-number">149</span><br></div></div><p>运行结果</p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>/opt/anaconda3/envs/spiders/bin/python -m uvicorn main:app --reload</span></span>
<span class="line"><span>INFO:     Will watch for changes in these directories: ['/Users/jack/code/py/uinotespider']</span></span>
<span class="line"><span>INFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)</span></span>
<span class="line"><span>INFO:     Started reloader process [70977] using StatReload</span></span>
<span class="line"><span>INFO:     Started server process [70979]</span></span>
<span class="line"><span>INFO:     Waiting for application startup.</span></span>
<span class="line"><span>INFO:     Application startup complete.</span></span>
<span class="line"><span>INFO:     127.0.0.1:50483 - "GET /docs HTTP/1.1" 200 OK</span></span>
<span class="line"><span>INFO:     127.0.0.1:50483 - "GET /openapi.json HTTP/1.1" 200 OK</span></span>
<span class="line"><span>上次爬过： set()</span></span>
<span class="line"><span>APPstring开始</span></span>
<span class="line"><span>此APPstring结束</span></span>
<span class="line"><span>INFO:     127.0.0.1:50488 - "POST / HTTP/1.1" 200 OK</span></span>
<span class="line"><span>上次爬过： set()</span></span>
<span class="line"><span>APP012779878697506993开始</span></span>
<span class="line"><span>此APP012779878697506993结束</span></span>
<span class="line"><span>APP146907778227438046开始</span></span>
<span class="line"><span>获取page 1 :  [{'uuid': '287632322506322094', 'height': 520, 'width': 1170, 'url': '/KWBJUPFRH7692/LEE2SY63EOTLS/LEE3VRYMTT7DJ.png', 'logoUrl': '/KWBJUPFRH7692/LEE2SY63EOTLS/LEE3VRYNI2SX0.png', 'app': '146907778227438046', 'appName': '京东金融', 'imageName': '京东金融-001', 'order': '001'}, {'uuid': '587239999955940464', 'height': 520, 'width': 1170, 'url': '/KWBJUPFRH7692/LEE2SY63EOTLS/LEE3VRYN3UWOG.png', 'logoUrl': '/KWBJUPFRH7692/LEE2SY63EOTLS/LEE3VRYNI2SX0.png', 'app': '146907778227438046', 'appName': '京东金融', 'imageName': '京东金融-002', 'order': '002'}, {'uuid': '322259292774089886', 'height': 520, 'width': 1170, 'url': '/KWBJUPFRH7692/LEE2SY63EOTLS/LEE3VRYN2O6BF.png', 'logoUrl': '/KWBJUPFRH7692/LEE2SY63EOTLS/LEE3VRYNI2SX0.png', 'app': '146907778227438046', 'appName': '京东金融', 'imageName': '京东金融-003', 'order': '003'}, {'uuid': '556218580832726485', 'height': 520, 'width': 1170, 'url': '/KWBJUPFRH7692/LEE2SY63EOTLS/LEE3VRYN0OEUU.png', 'logoUrl': '/KWBJUPFRH7692/LEE2SY63EOTLS/LEE3VRYNI2SX0.png', 'app': '146907778227438046', 'appName': '京东金融', 'imageName': '京东金融-004', 'order': '004'}, {'uuid': '395426589330760169', 'height': 520, 'width': 1170, 'url': '/KWBJUPFRH7692/LEE2SY63EOTLS/LEE3VRYNCXUVF.png', 'logoUrl': '/KWBJUPFRH7692/LEE2SY63EOTLS/LEE3VRYNI2SX0.png', 'app': '146907778227438046', 'appName': '京东金融', 'imageName': '京东金融-005', 'order': '005'}, {'uuid': '802571492955637764', 'height': 520, 'width': 1170, 'url': '/KWBJUPFRH7692/LEE2SY63EOTLS/LEE3VRYNJ43GD.png', 'logoUrl': '/KWBJUPFRH7692/LEE2SY63EOTLS/LEE3VRYNI2SX0.png', 'app': '146907778227438046', 'appName': '京东金融', 'imageName': '京东金融-006', 'order': '006'}, {'uuid': '995953259139436499', 'height': 520, 'width': 1170, 'url': '/KWBJUPFRH7692/LEE2SY63EOTLS/LEICQ52U204AH.png', 'logoUrl': '/KWBJUPFRH7692/LEE2SY63EOTLS/LEE3VRYNI2SX0.png', 'app': '146907778227438046', 'appName': '京东金融', 'imageName': '京东金融-007', 'order': '007'}, {'uuid': '100254973566281366', 'height': 520, 'width': 1170, 'url': '/KWBJUPFRH7692/LEE2SY63EOTLS/LEICQ52U2PD5Q.png', 'logoUrl': '/KWBJUPFRH7692/LEE2SY63EOTLS/LEE3VRYNI2SX0.png', 'app': '146907778227438046', 'appName': '京东金融', 'imageName': '京东金融-008', 'order': '008'}, {'uuid': '416666334451018289', 'height': 520, 'width': 1170, 'url': '/KWBJUPFRH7692/LEE2SY63EOTLS/LEICQ52U7Y5AA.png', 'logoUrl': '/KWBJUPFRH7692/LEE2SY63EOTLS/LEE3VRYNI2SX0.png', 'app': '146907778227438046', 'appName': '京东金融', 'imageName': '京东金融-009', 'order': '009'}, {'uuid': '760622668671455588', 'height': 520, 'width': 1170, 'url': '/KWBJUPFRH7692/LEE2SY63EOTLS/LEICQ52U2FOII.png', 'logoUrl': '/KWBJUPFRH7692/LEE2SY63EOTLS/LEE3VRYNI2SX0.png', 'app': '146907778227438046', 'appName': '京东金融', 'imageName': '京东金融-010', 'order': '010'}, {'uuid': '218217284774724377', 'height': 520, 'width': 1170, 'url': '/KWBJUPFRH7692/LEE2SY63EOTLS/LEICQ52UGTPG9.png', 'logoUrl': '/KWBJUPFRH7692/LEE2SY63EOTLS/LEE3VRYNI2SX0.png', 'app': '146907778227438046', 'appName': '京东金融', 'imageName': '京东金融-011', 'order': '011'}, {'uuid': '426021415318981234', 'height': 520, 'width': 1170, 'url': '/KWBJUPFRH7692/LEE2SY63EOTLS/LEICQ52UB1A94.png', 'logoUrl': '/KWBJUPFRH7692/LEE2SY63EOTLS/LEE3VRYNI2SX0.png', 'app': '146907778227438046', 'appName': '京东金融', 'imageName': '京东金融-012', 'order': '012'}, {'uuid': '217555576664546594', 'height': 520, 'width': 1170, 'url': '/KWBJUPFRH7692/LEE2SY63EOTLS/LEICQ52U05OCC.png', 'logoUrl': '/KWBJUPFRH7692/LEE2SY63EOTLS/LEE3VRYNI2SX0.png', 'app': '146907778227438046', 'appName': '京东金融', 'imageName': '京东金融-013', 'order': '013'}, {'uuid': '068139017852427542', 'height': 520, 'width': 1170, 'url': '/KWBJUPFRH7692/LEE2SY63EOTLS/LEICQ52UVA59Z.png', 'logoUrl': '/KWBJUPFRH7692/LEE2SY63EOTLS/LEE3VRYNI2SX0.png', 'app': '146907778227438046', 'appName': '京东金融', 'imageName': '京东金融-014', 'order': '014'}, {'uuid': '074867591771388938', 'height': 520, 'width': 1170, 'url': '/KWBJUPFRH7692/LEE2SY63EOTLS/LEICQ52U0OAYL.png', 'logoUrl': '/KWBJUPFRH7692/LEE2SY63EOTLS/LEE3VRYNI2SX0.png', 'app': '146907778227438046', 'appName': '京东金融', 'imageName': '京东金融-015', 'order': '015'}, {'uuid': '238891650394776034', 'height': 520, 'width': 1170, 'url': '/KWBJUPFRH7692/LEE2SY63EOTLS/LEICQ52UFORZM.png', 'logoUrl': '/KWBJUPFRH7692/LEE2SY63EOTLS/LEE3VRYNI2SX0.png', 'app': '146907778227438046', 'appName': '京东金融', 'imageName': '京东金融-016', 'order': '016'}, {'uuid': '936839413021684790', 'height': 520, 'width': 1170, 'url': '/KWBJUPFRH7692/LEE2SY63EOTLS/LEICQ52UC1EL4.png', 'logoUrl': '/KWBJUPFRH7692/LEE2SY63EOTLS/LEE3VRYNI2SX0.png', 'app': '146907778227438046', 'appName': '京东金融', 'imageName': '京东金融-017', 'order': '017'}, {'uuid': '631014334916994354', 'height': 520, 'width': 1170, 'url': '/KWBJUPFRH7692/LEE2SY63EOTLS/LEICQ52UUKL9Q.png', 'logoUrl': '/KWBJUPFRH7692/LEE2SY63EOTLS/LEE3VRYNI2SX0.png', 'app': '146907778227438046', 'appName': '京东金融', 'imageName': '京东金融-018', 'order': '018'}]</span></span>
<span class="line"><span>创建文件夹 京东金融</span></span>
<span class="line"><span>获取图片： 京东金融-001-LEE3VRYMTT7DJ.png</span></span>
<span class="line"><span>获取图片： 京东金融-002-LEE3VRYN3UWOG.png</span></span>
<span class="line"><span>获取图片： 京东金融-003-LEE3VRYN2O6BF.png</span></span>
<span class="line"><span>获取图片： 京东金融-004-LEE3VRYN0OEUU.png</span></span>
<span class="line"><span>获取图片： 京东金融-005-LEE3VRYNCXUVF.png</span></span>
<span class="line"><span>INFO:     Shutting down</span></span>
<span class="line"><span>INFO:     Waiting for connections to close. (CTRL+C to force quit)</span></span>
<span class="line"><span></span></span>
<span class="line"><span>Process finished with exit code 137 (interrupted by signal 9: SIGKILL)</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br></div></div></details>
<h2 id="scrapy扒站" tabindex="-1">Scrapy扒站 <a class="header-anchor" href="#scrapy扒站" aria-label="Permalink to &quot;Scrapy扒站&quot;">&ZeroWidthSpace;</a></h2>
<p>按照app分下载所有的大图，这个等以后整理爬虫大块的时候一块整理</p>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Scrapy-Web集成]]></title>
            <link>http://ooowl.fun/blogs/Python/%E7%88%AC%E8%99%AB/Scrapy-Web%E9%9B%86%E6%88%90.html</link>
            <guid isPermaLink="false">http://ooowl.fun/blogs/Python/%E7%88%AC%E8%99%AB/Scrapy-Web%E9%9B%86%E6%88%90.html</guid>
            <pubDate>Fri, 24 Feb 2023 11:16:38 GMT</pubDate>
            <content:encoded><![CDATA[<h1 id="scrapy-web集成" tabindex="-1">Scrapy-Web集成 <a class="header-anchor" href="#scrapy-web集成" aria-label="Permalink to &quot;Scrapy-Web集成&quot;">&ZeroWidthSpace;</a></h1><p class="article-meta">创建于 2023年2月24日 19:16:38 · 约0字</p>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[后端开发常见层式结构]]></title>
            <link>http://ooowl.fun/blogs/Web%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/%E5%90%8E%E7%AB%AF%E5%BC%80%E5%8F%91%E5%B8%B8%E8%A7%81%E5%B1%82%E5%BC%8F%E7%BB%93%E6%9E%84.html</link>
            <guid isPermaLink="false">http://ooowl.fun/blogs/Web%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/%E5%90%8E%E7%AB%AF%E5%BC%80%E5%8F%91%E5%B8%B8%E8%A7%81%E5%B1%82%E5%BC%8F%E7%BB%93%E6%9E%84.html</guid>
            <pubDate>Thu, 23 Feb 2023 16:21:19 GMT</pubDate>
            <description><![CDATA[#TODO 论文复现]]></description>
            <content:encoded><![CDATA[<h1 id="后端开发常见层式结构" tabindex="-1">后端开发常见层式结构 <a class="header-anchor" href="#后端开发常见层式结构" aria-label="Permalink to &quot;后端开发常见层式结构&quot;">&ZeroWidthSpace;</a></h1><p class="article-meta">创建于 2023年2月24日 00:21:19 · 约1,392字</p>
<p>#TODO 论文复现</p>
<p>系统设计案例<a href="https://github.com/donnemartin/system-design-primer/blob/master/README-zh-Hans.md" target="_blank" rel="noreferrer">system-design-primer· GitHub</a></p>
<p>后端开发常见层式结构：时间轮(TimingWheel)、跳表、LSM-Tree</p>
<ol>
<li>海量并发的定时任务组织：时间轮[linux内核,skynet,kafka,netty]</li>
<li>高并发读写的有序结构组织：跳表[redis,lucene,rocksdb]</li>
<li>空间利用率以及写性能高的磁盘数据组织：LSM-Tree[leveldb(google的k-v) rocksdb(布式关系型数据库)  tidb(mysql) cockroachdb(pg)]</li>
</ol>
<p>都是按照层来组织数据的</p>
<h2 id="时间轮timingwheel" tabindex="-1">时间轮TimingWheel <a class="header-anchor" href="#时间轮timingwheel" aria-label="Permalink to &quot;时间轮TimingWheel&quot;">&ZeroWidthSpace;</a></h2>
<h3 id="数据组织" tabindex="-1">数据组织 <a class="header-anchor" href="#数据组织" aria-label="Permalink to &quot;数据组织&quot;">&ZeroWidthSpace;</a></h3>
<p><img src="./static/后端开发常见层式结构_images_1.png" alt=""></p>
<p>普通时间轮，每个链表存储的是此时刻的任务，在ptr指向此时刻的时候执行此时刻的任务<br>
层级时间轮，按照任务的优先级进行任务划分，在分针运行到下一个时间块的时候，秒针任务空间会被重置为第二个分钟块的任务，时针以此类推<br>
kafka中用的也是三级时间轮1ms✖️20ms✖️400ms<br>
在自己设计时间轮的时候，需要从三方面考虑，可以设置为参数方便调整：</p>
<ul>
<li>设计最小时间精度 支持最小的时间块</li>
<li>设计最大时间范围 超过时间范围会出现错误</li>
<li>设计层级个数 决定了映射的频繁程度</li>
</ul>
<h3 id="应用场景" tabindex="-1">应用场景 <a class="header-anchor" href="#应用场景" aria-label="Permalink to &quot;应用场景&quot;">&ZeroWidthSpace;</a></h3>
<p>时间轮在海量多线程并发的情景下，需要考虑锁的问题<br>
锁本质上是希望同一时刻只有一个线程去操作DS，提升性能两条路子：</p>
<ul>
<li>减少时间复杂度（降低此DS占用线程 cpu的时间）时间轮</li>
<li>在更细粒度上加锁（让多个线程同时操作本DS的细粒度DS，不会浪费每个线程的cpu时间）任务队列APscheduler+redis，<mark>跳表也是</mark></li>
</ul>
<h3 id="论文和实现" tabindex="-1">论文和实现 <a class="header-anchor" href="#论文和实现" aria-label="Permalink to &quot;论文和实现&quot;">&ZeroWidthSpace;</a></h3>
<p><a href="http://www.cs.columbia.edu/~nahum/w6998/papers/ton97-timing-wheels.pdf" target="_blank" rel="noreferrer">论文指路</a> 没有中文版，时间轮被提出的论文，还有一个<a href="https://www.cse.wustl.edu/~cdgill/courses/cs6874/TimingWheels.ppt" target="_blank" rel="noreferrer">PPT</a>，文章<a href="https://shanxiaoi.top/post/2021/02/19/b14c8701-ab88-48fa-a6ba-58ce33fa2a8e/" target="_blank" rel="noreferrer">可能以后有用</a>
有时间可以读一读论文，甚至可以翻译一下，照着其他博客实现几个小的demo，视频上的东西先做初步了解</p>
<h2 id="跳表skip-list" tabindex="-1">跳表Skip List <a class="header-anchor" href="#跳表skip-list" aria-label="Permalink to &quot;跳表Skip List&quot;">&ZeroWidthSpace;</a></h2>
<p>多层级的有序链表<br>
<a href="https://redisbook.readthedocs.io/en/latest/internal-datastruct/skiplist.html" target="_blank" rel="noreferrer">跳跃表 — Redis 设计与实现</a></p>
<h3 id="数据组织-1" tabindex="-1">数据组织 <a class="header-anchor" href="#数据组织-1" aria-label="Permalink to &quot;数据组织&quot;">&ZeroWidthSpace;</a></h3>
<p><img src="./static/后端开发常见层式结构_images_2.png" alt="">
单层级链表时间复杂度为O(n)，跳表将其降低为O(log2n)和二分一样，每次查找能够排除一半的节点<br>
增加节点的时候会赋予新元素<mark>随机层数</mark>，其实不影响<br>
跳表的增删改查都需要先查，核心就是不断比较层数之间，如果被夹住中间没有节点了，那就是应该插入的位置<br>
跳表的作者本来想得是每隔一个节点设置一个相同的层级，每次查询恰好排除一半，是这样</p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>3-------3</span></span>
<span class="line"><span>2---2---2---2</span></span>
<span class="line"><span>1-1-1-1-1-1-1-1</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br></div></div><p>但是发现每次增删的时候会破坏所有的层级结构，需要重新构建<br>
插入节点的时候，层数往上以每层1/2概率决定是否累加，下一层，这样当数据足够大的时候（在redis中为256个节点的时候稳定）时间复杂度为
$$1-\frac{c}{log_{2} n}$$</p>
<h3 id="应用场景-1" tabindex="-1">应用场景 <a class="header-anchor" href="#应用场景-1" aria-label="Permalink to &quot;应用场景&quot;">&ZeroWidthSpace;</a></h3>
<p>跳表适应多线程写的，因为在更细粒度上加锁，只需要锁住最高高度以及自己身边的两个节点即可。</p>
<ul>
<li>redis的Zset是用跳表实现的有序集合为什么是用跳表而不是红黑树？
<ul>
<li>红黑树不会浪费层数但是也是log2n，而且空间没浪费时间复杂度稳定</li>
<li>redis是数据库，需要做范围查找，红黑树不是很合适会有很多的回溯和比较</li>
</ul>
</li>
<li>为什么不用B+ 因为B+的搜索为h * log2n 查找的时候会包很多比较每次比较一层都是 log2n</li>
</ul>
<div class="info custom-block"><p class="custom-block-title">[📝Note]</p>
<p>跳表适合组织内存数据，而B+树适合组织磁盘数据。</p>
<p>我们把每一个索引的大小设置为磁盘的页大小证书倍，每次在B+树里行进一个高度，都要进行一次磁盘的IO，h决定了磁盘的IO数量</p>
<p>红黑和跳表高度太高了，B+更扁平</p>
<p>pg索引用的是B树，mysql是B+</p>
</div>
<h3 id="论文和实现-1" tabindex="-1">论文和实现 <a class="header-anchor" href="#论文和实现-1" aria-label="Permalink to &quot;论文和实现&quot;">&ZeroWidthSpace;</a></h3>
<p><a href="https://15721.courses.cs.cmu.edu/spring2018/papers/08-oltpindexes1/pugh-skiplists-cacm1990.pdf" target="_blank" rel="noreferrer">论文指路</a></p>
<h2 id="lsm-tree" tabindex="-1">LSM-Tree <a class="header-anchor" href="#lsm-tree" aria-label="Permalink to &quot;LSM-Tree&quot;">&ZeroWidthSpace;</a></h2>
<p>日志结构合并树，不是单纯的数据结构，而是磁盘文件组织方式 一种非常复杂的复合数据结构，它包含了 WAL（Write Ahead Log）、跳表（SkipList）和一个分层的有序表（SSTable，Sorted String Table）。</p>
<h3 id="数据组织-2" tabindex="-1">数据组织 <a class="header-anchor" href="#数据组织-2" aria-label="Permalink to &quot;数据组织&quot;">&ZeroWidthSpace;</a></h3>
<table tabindex="0">
<thead>
<tr>
<th>比较</th>
<th style="text-align:center">B+</th>
<th style="text-align:center">LSM-tree</th>
</tr>
</thead>
<tbody>
<tr>
<td>解决的问题</td>
<td style="text-align:center">读多写少</td>
<td style="text-align:center">写多读少</td>
</tr>
<tr>
<td>空间利用率</td>
<td style="text-align:center">分裂时候利用率&lt;50% innodb157G</td>
<td style="text-align:center">空间利用率好  myrocks40-50G</td>
</tr>
<tr>
<td>时间复杂度</td>
<td style="text-align:center">稳定O(logn)</td>
<td style="text-align:center">O(n)-O(1)</td>
</tr>
</tbody>
</table>
<div class="tip custom-block"><p class="custom-block-title">[💡Tip]</p>
<p>不同的存储设备延迟对比<br>
磁盘随机io 寻道(8-12)+旋转(7200r/4ms)+传输(50M/s 0.3)=10ms左右    <br>
内存顺序io 10ns左右，100w倍的差距     <br>
磁盘随机&lt;&lt;磁盘顺序≈内存随机&lt;&lt;内存顺序  <br></p>
</div>
<p><img src="./static/后端开发常见层式结构_images_3.png" alt=""></p>
<p>使用跳表保证内存中有序，然后写到磁盘里，RAM中有只读的内存和可写的内存。当写入内存达到阈值会变为不可写的内存块并写入level0，在此level可能会出现两个跳表相同的key<br>
根据数据操作的热度进行分层，level往下逐渐归并排序并合并文件，到最后一个level基本都是冷数据，占据文件的90%，其他的热数据占据10%<br>
因为在不断的合并所以占用空间少，以附加日志的方式写入，总是在文件末尾不断顺序IO。<br>
在level0和层与层之间可能出现相同的数据，在每一个文件中加入布隆过滤器，先概率判断再去搜索。</p>
<h3 id="应用场景-2" tabindex="-1">应用场景 <a class="header-anchor" href="#应用场景-2" aria-label="Permalink to &quot;应用场景&quot;">&ZeroWidthSpace;</a></h3>
<ul>
<li>myrocks，不仅使用LSM-Tree而且还实现了事务</li>
<li>日志结构的存储引擎</li>
<li>高性能，适合频繁写入的场景</li>
<li>内部维护 kv 对（适合应用于 kv 存储）</li>
<li>内部维护了多种不同的数据结构，每种结构都进行了针对性优化，数据在不同结构之间同步</li>
</ul>
<h3 id="论文和实现-2" tabindex="-1">论文和实现 <a class="header-anchor" href="#论文和实现-2" aria-label="Permalink to &quot;论文和实现&quot;">&ZeroWidthSpace;</a></h3>
<p><a href="https://xonlab.com/2021/01/10/%E8%AE%BA%E6%96%87%E7%BF%BB%E8%AF%91The%20Log-Structured%20Merge-Tree%EF%BC%88LSM-Tree%EF%BC%89/" target="_blank" rel="noreferrer">论文翻译指路</a><br/>
<a href="https://www.cs.umb.edu/~poneil/lsmtree.pdf" target="_blank" rel="noreferrer">论文指路</a></p>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[DNS选择机制]]></title>
            <link>http://ooowl.fun/blogs/Book/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C%E8%87%AA%E9%A1%B6%E5%90%91%E4%B8%8B/%E4%B8%80%E4%BA%9B%E9%9B%B6%E6%95%A3%E7%9A%84%E7%9F%A5%E8%AF%86%E7%82%B9/DNS%E9%80%89%E6%8B%A9%E6%9C%BA%E5%88%B6.html</link>
            <guid isPermaLink="false">http://ooowl.fun/blogs/Book/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C%E8%87%AA%E9%A1%B6%E5%90%91%E4%B8%8B/%E4%B8%80%E4%BA%9B%E9%9B%B6%E6%95%A3%E7%9A%84%E7%9F%A5%E8%AF%86%E7%82%B9/DNS%E9%80%89%E6%8B%A9%E6%9C%BA%E5%88%B6.html</guid>
            <pubDate>Wed, 22 Feb 2023 19:37:02 GMT</pubDate>
            <content:encoded><![CDATA[<h1 id="dns选择机制" tabindex="-1">DNS选择机制 <a class="header-anchor" href="#dns选择机制" aria-label="Permalink to &quot;DNS选择机制&quot;">&ZeroWidthSpace;</a></h1><p class="article-meta">创建于 2023年2月23日 03:37:02 · 约652字</p>
<h2 id="多个dns" tabindex="-1">多个DNS <a class="header-anchor" href="#多个dns" aria-label="Permalink to &quot;多个DNS&quot;">&ZeroWidthSpace;</a></h2>
<p>在多个dns服务器下，只有第一个彻底不通的时候才会使用到第二个。<br>
例如：你第一个设置一个不可使用的 IP ： 1.1.1.1 第二个设置 114.114.114.114 ，这个时候就可以使用了。<br>
如果你第一个 DNS ，没有彻底挂了的时候，例如 DNS 服务不正常，能通，但无法解析，这个时候是不会使用到第二个 DNS 的。<a href="http://man7.org/linux/man-pages/man5/resolv.conf.5.html" target="_blank" rel="noreferrer">man文档</a><br>
Windows: 第一个超过 1s 没返回就使用第二个，当你使用 nslookup 或者 dig 时，是仅用第一个的。微软官方有文档dan但我没找到<br>
但是 linux 的 DNS 系统是可以设置的。可以设置成负载均衡，也可以设置成每次请求向所有配置的 DNS 发送请求，谁先回复就用谁的，也可以像楼主描述的一样按照顺序查询
<a href="https://howiezhao.github.io/2020/12/29/dns/" target="_blank" rel="noreferrer">DNS 运行机制 | Howie's Notes</a></p>
<h3 id="dns-fallback机制" tabindex="-1">DNS fallback机制 <a class="header-anchor" href="#dns-fallback机制" aria-label="Permalink to &quot;DNS fallback机制&quot;">&ZeroWidthSpace;</a></h3>
<p><a href="https://tachyondevel.medium.com/%E6%BC%AB%E8%B0%88%E5%90%84%E7%A7%8D%E9%BB%91%E7%A7%91%E6%8A%80%E5%BC%8F-dns-%E6%8A%80%E6%9C%AF%E5%9C%A8%E4%BB%A3%E7%90%86%E7%8E%AF%E5%A2%83%E4%B8%AD%E7%9A%84%E5%BA%94%E7%94%A8-62c50e58cbd0" target="_blank" rel="noreferrer">谈一谈各种 DNS</a>
接下来再说说一种叫做 DNS fallback 的技术（这个名字可能不太对），在代理服务器不支持 UDP 的时候，<strong>单纯的全局 TCP/UDP 流量代理</strong> 就会出问题了，因为要解析 DNS 就需要 UDP，服务器不支持 UDP 就没办法处理 DNS ，也就没办法处理所有域名请求了，DNS fallback 是一种可以强制让应用程序把 DNS 请求以 TCP 流量发送出去的技术。</p>
<blockquote>
<p>需要说明的是，如果用了 V2Ray 的技术，或者 Fake DNS，那 DNS fallback 是没必要的，DNS fallback 也是一种处理 DNS 相关问题技术，这里只是想把这种技术也列举出来</p>
</blockquote>
<p>众所周知一般的 DNS 请求都是用 UDP 发的，但 DNS 的 UDP 报文的大小会被限制在大概 512 字节，如果某个 DNS 答复很长，超过了这个限制，就不能通过 UDP 来传输了，为此 DNS 规范中提出，对于这种超过限制大小的 DNS 请求，DNS 服务器可以在答复中设置一个 flag（truncated），来告诉客户端这个答复太长，你不能用 UDP 来做这个 DNS 请求，请用 TCP，于是客户端就会用 TCP 来重新请求 DNS。</p>
<p>DNS fallback 正是利用了这一点，在 tun2socks 给过来的 UDP 流量中识别出 DNS 请求，然后伪造一个设置了 truncated flag 的答复返回给客户端，客户端就会转用 TCP 来做 DNS 请求了。</p>
<p>DNS fallback 的实现也是非常简单的，有兴趣可以看一下 <a href="https://github.com/eycorsican/go-tun2socks/blob/master/proxy/dnsfallback/udp.go" target="_blank" rel="noreferrer">这里的代码</a>。</p>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[网络八股Cache]]></title>
            <link>http://ooowl.fun/blogs/Book/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C%E8%87%AA%E9%A1%B6%E5%90%91%E4%B8%8B/%E4%B8%80%E4%BA%9B%E9%9B%B6%E6%95%A3%E7%9A%84%E7%9F%A5%E8%AF%86%E7%82%B9/%E5%85%AB%E8%82%A1Cache.html</link>
            <guid isPermaLink="false">http://ooowl.fun/blogs/Book/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C%E8%87%AA%E9%A1%B6%E5%90%91%E4%B8%8B/%E4%B8%80%E4%BA%9B%E9%9B%B6%E6%95%A3%E7%9A%84%E7%9F%A5%E8%AF%86%E7%82%B9/%E5%85%AB%E8%82%A1Cache.html</guid>
            <pubDate>Wed, 22 Feb 2023 19:36:49 GMT</pubDate>
            <description><![CDATA[| 端口 | 功能 | |]]></description>
            <content:encoded><![CDATA[<h1 id="网络八股cache" tabindex="-1">网络八股Cache <a class="header-anchor" href="#网络八股cache" aria-label="Permalink to &quot;网络八股Cache&quot;">&ZeroWidthSpace;</a></h1><p class="article-meta">创建于 2023年2月23日 03:36:49 · 约586字</p>
<h2 id="常用的端口" tabindex="-1">常用的端口 <a class="header-anchor" href="#常用的端口" aria-label="Permalink to &quot;常用的端口&quot;">&ZeroWidthSpace;</a></h2>
<table tabindex="0">
<thead>
<tr>
<th>端口</th>
<th>功能</th>
</tr>
</thead>
<tbody>
<tr>
<td>20</td>
<td>FTP数据</td>
</tr>
<tr>
<td>21</td>
<td>ftp 控制</td>
</tr>
<tr>
<td>23</td>
<td>Telnet</td>
</tr>
<tr>
<td>25</td>
<td>SMTP(Simple Mail Transfer Protocol，简单邮件传输协议)</td>
</tr>
<tr>
<td>53</td>
<td>DNS,Domain Name Server</td>
</tr>
<tr>
<td>67 68</td>
<td>分别是为Bootp服务的Bootstrap Protocol Server<br/>（引导程序协议服务端）和Bootstrap Protocol Client（引导程序协议客户端）<br/>早期Unix的远程启动协议，DHCP前身为局域网的计算机动态分配IP</td>
</tr>
<tr>
<td>69</td>
<td>TFTP(Trival File Tranfer Protocol,次要文件传输协议)</td>
</tr>
<tr>
<td>79</td>
<td>Finger服务，查询远程主机在线用户、操作系统类型以及是否<br/>缓冲区溢出等用户的详细信息finger <a href="mailto:user01@www.abc.com" target="_blank" rel="noreferrer">user01@www.abc.com</a></td>
</tr>
<tr>
<td>80</td>
<td>HTTP(HyperText Transport Protocol)</td>
</tr>
<tr>
<td>99</td>
<td>“Metagram Relay”（亚对策延时)较少见用不到</td>
</tr>
<tr>
<td>109 110</td>
<td>POP2(Post Office Protocol Version 2)&amp;POP3</td>
</tr>
<tr>
<td>111</td>
<td>SUN公司的RPC(Remote Procedure Call，远程过程调用)服务所开 <br/>放的端口，主要用于分布式系统中不同计算机的内部进程通信</td>
</tr>
<tr>
<td>113</td>
<td>Windows的“Authentication Service”（验证服务），<br/>与网络连接的计算机都运行该服务，主要用于验证TCP连接的用户</td>
</tr>
<tr>
<td>119</td>
<td>“Network News Transfer Protocol”（网络新闻组传输协议，<br/>NNTP)主要用于新闻组传输</td>
</tr>
<tr>
<td>135</td>
<td>RPC（Remote Procedure Call，远程过程调用）协议并提供DCOM<br/>(分布式组件对象模型）服务，通过RPC可以保证在一台计算机上运行的程序<br>可以顺利地执行远程计算机上的代码；<br/>使用DCOM可以通过网络直接通信，能够跨包括HTTP协议的多种网络传输。</td>
</tr>
<tr>
<td>137</td>
<td>“NetBIOS Name Service”（NetBIOS名称服务），<br/>属于UDP端口，使用者只需要向局域网或互联网上的<br/>某台计算机的137端口发送一个请求，<br/>就可以获取该计算机的名称、注册用户名，以及是否安装主域控制器、IIS是否正在运行等信息。</td>
</tr>
<tr>
<td>139</td>
<td>“NetBIOS Session Service”主要用于提供Windows文件和打印机共享以及<br/>Unix中的Samba服务</td>
</tr>
<tr>
<td>143</td>
<td>“Internet Message Access Protocol”v2(Internet消息访问协议，<br/>简称IMAP),和POP3一样，是用于电子邮件的接收的协议</td>
</tr>
<tr>
<td>161</td>
<td>“Simple Network Management Protocol”（简单网络管理协议，<br/>简称SNMP），该协议 主要用于管理TCP/IP网络中的网络协议</td>
</tr>
<tr>
<td>443</td>
<td>HTTPS</td>
</tr>
</tbody>
</table>
<p><a href="https://www.bilibili.com/video/BV1J54y1Z79A" target="_blank" rel="noreferrer">10道网络八股文面试题，网络原理tcp/udp，网络编程epoll/reactor_哔哩哔哩_bilibili</a></p>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[设计图的概述]]></title>
            <link>http://ooowl.fun/blogs/Web%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/SoftwareEngineeringGraph.html</link>
            <guid isPermaLink="false">http://ooowl.fun/blogs/Web%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/SoftwareEngineeringGraph.html</guid>
            <pubDate>Wed, 22 Feb 2023 18:15:27 GMT</pubDate>
            <content:encoded><![CDATA[<h1 id="设计图的概述" tabindex="-1">设计图的概述 <a class="header-anchor" href="#设计图的概述" aria-label="Permalink to &quot;设计图的概述&quot;">&ZeroWidthSpace;</a></h1><p class="article-meta">创建于 2023年2月23日 02:15:27 · 约2,814字</p>
<p><img src="./static/SoftwareEngineeringGraph_images_1.svg" alt="|1050"></p>
<h3 id="一、背景" tabindex="-1">一、背景 <a class="header-anchor" href="#一、背景" aria-label="Permalink to &quot;一、背景&quot;">&ZeroWidthSpace;</a></h3>
<p>大家应该在从事软件开发领域工作时间有一段时间之后，就开始有画图的意识，不管是懵懂的学别人还是想更好的让其它人理解自己的一个观点。所谓“一图胜千言”，我们身处于软件开发这个<strong>水很深且要求精确</strong>的复杂<strong>领域</strong>里，要想把事情做好，最基本的是要把事情想明白，其次还要让相关的人能够明白你要说的东西，进行协作。<br>
特别对于一位架构师来说，能否画得一手好图尤其重要，因为相关的干系人数较多，要让不同领域的人能够达成一个统一的认识，是一件不太容易但也是必须要做好的事情。</p>
<h3 id="二、图为了解决什么问题" tabindex="-1">二、图为了解决什么问题 <a class="header-anchor" href="#二、图为了解决什么问题" aria-label="Permalink to &quot;二、图为了解决什么问题&quot;">&ZeroWidthSpace;</a></h3>
<p>软件开发涉及的流程是：需求 --&gt; 开发 --&gt; 测试 --&gt; 发布上线。<br>
作图本身是个设计的工作，是个前期工作。那么从软件开发的整个生命周期来说，用到的图的地方是在前期的需求、开发阶段较多。在软件开发这个非常抽象的领域，只要涉及到多人协作，那么通过文字来进行交流叙述是非常晦涩难懂的，需要沟通好几遍才能理解达成一致也是比较常见的情况。那么我们画图，就是为了把不适合用言语表述的内容通过作图的方式呈现出来，让相关协作者有一个共同的具象的参照物。这个参照物可以有它的额外价值，是对软件长期价值的延伸，一份一致、清晰的设计图，可以给后续的软件迭代提供非常有帮助的决策依据。当然保证设计图与系统的一致本身也是件费精力的事情。</p>
<h3 id="三、不同流程中适合运用的图" tabindex="-1">三、不同流程中适合运用的图 <a class="header-anchor" href="#三、不同流程中适合运用的图" aria-label="Permalink to &quot;三、不同流程中适合运用的图&quot;">&ZeroWidthSpace;</a></h3>
<h4 id="_3-1-用例图" tabindex="-1">3.1 用例图 <a class="header-anchor" href="#_3-1-用例图" aria-label="Permalink to &quot;3.1 用例图&quot;">&ZeroWidthSpace;</a></h4>
<div class="language-txt vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">txt</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>scale 1.5</span></span>
<span class="line"><span>@startuml</span></span>
<span class="line"><span>left to right direction</span></span>
<span class="line"><span>skinparam usecase {</span></span>
<span class="line"><span>    BackgroundColor #FFFF99</span></span>
<span class="line"><span>    BorderColor black</span></span>
<span class="line"><span>    FontColor black</span></span>
<span class="line"><span>    FontSize 13</span></span>
<span class="line"><span>    FontName Arial</span></span>
<span class="line"><span>}</span></span>
<span class="line"><span></span></span>
<span class="line"><span>actor 游客</span></span>
<span class="line"><span>actor 注册会员</span></span>
<span class="line"><span>actor 管理员</span></span>
<span class="line"><span></span></span>
<span class="line"><span>usecase (注册) as UC1</span></span>
<span class="line"><span>usecase (发表评论) as UC2</span></span>
<span class="line"><span>usecase (发布新闻) as UC3</span></span>
<span class="line"><span>usecase (新闻管理) as UC4</span></span>
<span class="line"><span>usecase (评论管理) as UC5</span></span>
<span class="line"><span>usecase (会员管理) as UC6</span></span>
<span class="line"><span></span></span>
<span class="line"><span>游客 --> UC1</span></span>
<span class="line"><span>UC1 .> 注册会员 : &#x3C;&#x3C;extends>></span></span>
<span class="line"><span>注册会员 --> UC2</span></span>
<span class="line"><span>管理员 --> UC3</span></span>
<span class="line"><span>管理员 --> UC4</span></span>
<span class="line"><span>管理员 --> UC5</span></span>
<span class="line"><span>管理员 --> UC6</span></span>
<span class="line"><span></span></span>
<span class="line"><span>@enduml</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br></div></div><p>用例图是UML交互图中的一种，是指由参与者（Actor）、用例（Use Case），边界以及它们之间的关系构成的用于描述系统功能的视图。用例图（User Case）是外部用户（被称为参与者，一般为软件的面向用户）所能观察到的系统功能的模型图。</p>
<ul>
<li>适用场景：当新做一个产品或者功能的时候，首先需要明确核心方向，用例图就是整理这个核心方向的工具。它用来说明的是谁要使用系统，以及他们使用该系统可以做些什么。可以理解为是MVP思想的写照，去除画龙点睛的功能，这些就是基础、核心。</li>
<li>缺点：仅仅描述的是提供什么功能，不能表达非功能需求，如可靠性、性能等非功能需求。</li>
</ul>
<h4 id="_3-2-鲁棒图-robustness-diagram" tabindex="-1">3.2 鲁棒图（Robustness Diagram） <a class="header-anchor" href="#_3-2-鲁棒图-robustness-diagram" aria-label="Permalink to &quot;3.2 鲁棒图（Robustness Diagram）&quot;">&ZeroWidthSpace;</a></h4>
<p><img src="./static/SoftwareEngineeringGraph_images_2.png" alt="600"></p>
<p>可能英文名Robustness Diagram更为常见一些，用于衔接用例图之后的设计，识别出系统在用例图中的各种职责，对后续的细节设计提供基础。算是对用例图的一种延伸。</p>
<ul>
<li>适用场景：在确立用户场景之后，如果需要将关键功能设计出来，那么就需要它了。作图过程中最关键的2个点，发现职责，和梳理各个职责之间的关系。</li>
<li>缺点：和用例图是一样- 缺点，唯一的变化是，其有了粗粒度的实现层面的内容。</li>
</ul>
<h4 id="_3-3-思维导图" tabindex="-1">3.3 思维导图 <a class="header-anchor" href="#_3-3-思维导图" aria-label="Permalink to &quot;3.3 思维导图&quot;">&ZeroWidthSpace;</a></h4>
<p>思维导图是一个很厉害的发明，他将我们的思考过程具象化了，完美展示了由点到面不断发散的过程。但是它最大的价值，反而不是最终呈现出来的这个图，而是促进了思考的过程。并且需要注意的是，一定要把一条分支走到尽头，再回过头来走其它的分支，把思想榨干。</p>
<ul>
<li>适用场景：在一个事情刚开始的萌芽期，不知如何下手；或者陷入一个困境的时候。利用思维导图来活跃大脑，进行发散思维。这时候如果结合头脑风暴，效果更佳。</li>
<li>缺点：它是一种树状的信息分层可视化展视，结构比较固定，不适合分支间互相交互比较复杂的信息展示。</li>
</ul>
<h4 id="_3-4-dfd-data-flow-diagram-图" tabindex="-1">3.4 DFD（Data Flow Diagram）图 <a class="header-anchor" href="#_3-4-dfd-data-flow-diagram-图" aria-label="Permalink to &quot;3.4 DFD（Data Flow Diagram）图&quot;">&ZeroWidthSpace;</a></h4>
<p><img src="./static/SoftwareEngineeringGraph_images_3.png" alt="600"></p>
<p>DFD图是从数据传递和加工角度，以图形方式来表达系统的逻辑功能、数据在系统内部的逻辑流向和逻辑变换过程，是结构化系统分析方法的主要表达工具及用于表示软件模型的一种图示方法。</p>
<ul>
<li>适用场景：在将思维导图得出的东西进行整合、梳理形成一个粗粒度的流程。这个其实类似与DDD中的上下文映射图，是在需求分析过程中做宏观设计的一种方式。</li>
<li>缺点：反映系统“做什么”，不反映“如何做”，粒度算是中等，需要其它更细粒度的图来对细节做支撑。</li>
</ul>
<h4 id="_3-5-流程图" tabindex="-1">3.5 流程图 <a class="header-anchor" href="#_3-5-流程图" aria-label="Permalink to &quot;3.5 流程图&quot;">&ZeroWidthSpace;</a></h4>
<div class="language-mermaid vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">mermaid</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">graph TD</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    A([开始]) --> B[程序初始化]</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    B --> C[键盘中断控制方式]</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    C --> D[单片机低功耗节电方式]</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    D --> E{是否调用&#x3C;br>外部中断?}</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    E -->|否| F["DS18B20温度传感器&#x3C;br>数据采集"]</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    E -->|是| G["红外发射信号控制&#x3C;br>(PWM)"]</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    F --> H[显示工作状态]</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    G --> H</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    H --> I([结束])</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br></div></div><p>上面贴了2张图都是流程图，流程图有时也称作输入-输出图。该图直观地描述一个工作过程的具体步骤，各种操作一目了然，不会产生“歧义性”，便于理解，算法出错时容易发现。流程图对准确了解事情是如何进行的，以及决定应如何改进过程极有帮助。大到系统级别、小到某个操作背后的运转逻辑都可以使用流程图来画，我个人认为这应该是被最多人认识的图，没有之一。</p>
<ul>
<li>适用场景：正如上面所说这个- 适用场景比较广，日常工作中小到算法逻辑，大到战略层面的执行落地都需要它。主要用它来将背后的流程可视化，辅助做决策去（如改进等）。</li>
<li>缺点：所占篇幅较大，由于允许使用流程线，过于灵活，不受约束，使用者可使流程任意转向，从而造成程序阅读和修改上的困难，不利于结构化程序的设计。</li>
</ul>
<h4 id="_3-6-uml类图" tabindex="-1">3.6 UML类图 <a class="header-anchor" href="#_3-6-uml类图" aria-label="Permalink to &quot;3.6 UML类图&quot;">&ZeroWidthSpace;</a></h4>
<div class="language-mermaid vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">mermaid</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">classDiagram</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    %% 类定义</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    class Account {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        - accountState: AccountState</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        - owner: String</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        - balance: Double</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        + deposit(amount: Double)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        + shopping(amount: Double)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    class AccountState {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        &#x3C;&#x3C;abstract>></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        + deposit(account: Account, amount: Double)*</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        + shopping(account: Account, amount: Double)*</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        + checkState(account: Account)*</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    class VisitorState {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        + deposit(account: Account, amount: Double)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        + shopping(account: Account, amount: Double)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        + checkState(account: Account)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    class MemberState {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        + deposit(account: Account, amount: Double)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        + shopping(account: Account, amount: Double)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        + checkState(account: Account)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    class VIPState {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        + deposit(account: Account, amount: Double)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        + shopping(account: Account, amount: Double)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        + checkState(account: Account)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    %% 关系定义</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    Account *--> AccountState : 状态</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    AccountState &#x3C;|-- VisitorState : 继承</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    AccountState &#x3C;|-- MemberState : 继承</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    AccountState &#x3C;|-- VIPState : 继承</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br></div></div><p>UML类图是UML交互图中的一种，也是我们较常见的一种。类图是描述系统中的类，以及各个类之间的关系的静态视图。它不但是设计人员关心的核心，更是实现人员关注的核心。</p>
<ul>
<li>适用场景：一般作为编码前做的最后一步，将设计转为相应的模型。也可以使用Code First的方式直接在项目中建模，现在的VS也支持直接从代码中生成UML类图。</li>
<li>缺点：画起来太费时间了，但反过来其表达的粒度更细致，是代码实现级别的内容。由于现在有比较多的工具可以从代码生成UML类图，甚至在大部分提倡使用Code First的场景下，我们画UML类图的机会是越来越少了。</li>
</ul>
<h4 id="_3-7-状态图" tabindex="-1">3.7 状态图 <a class="header-anchor" href="#_3-7-状态图" aria-label="Permalink to &quot;3.7 状态图&quot;">&ZeroWidthSpace;</a></h4>
<div class="language-mermaid vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">mermaid</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">stateDiagram-v2</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    [*] --> Created</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    Created --> Paid: 用户支付</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    Created --> Canceled: 超时未支付</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    state Paid {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        [*] --> Payment_Confirmed</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Payment_Confirmed --> Refunded: 用户申请退款</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    Paid --> Shipped: 商家发货</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    Shipped --> Delivered: 快递签收</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    Shipped --> Returned: 用户退货</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    Delivered --> Completed: 确认收货</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    Delivered --> Returned: 质量问题退货</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    Returned --> [*]: 退货完成</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    Completed --> [*]</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    Canceled --> [*]</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    note right of Created: 订单有效期30分钟</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    note left of Returned: 需质检后处理</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    note right of Shipped: 48小时内必须发货</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br></div></div><p>状态图是对类图的补充。描述类的对象所有可能的状态，以及事件发生时状态的转移条件。可以捕获对象、子系统和系统的生命周期。他们可以告知一个对象可以拥有的状态，并且事件(如消息的接收、时间的流逝、错误、条件变为真等)会怎么随着时间的推移来影响这些状态。一个状态图应该连接到所有具有清晰的可标识状态和复杂行为的类；该图可以确定类的行为，以及该行为如何根据当前的状态变化，也可以展示哪些事件将会改变类的对象的状态。</p>
<ul>
<li>适用场景：当有一个对象拥有多个状态的时候，想要表达清楚状态之间的演变关系（也就是这个对象的生命周期）。比如通过什么条件触发状态变动的，到达某个状态之后会做什么动作等。这也是基于事件驱动设计的良好可视化图。</li>
<li>缺点：仅能表达行为/事件与状态之间的演变关系，不适用于其它领域。</li>
</ul>
<h4 id="_3-8-e-r图" tabindex="-1">3.8 E-R图 <a class="header-anchor" href="#_3-8-e-r图" aria-label="Permalink to &quot;3.8 E-R图&quot;">&ZeroWidthSpace;</a></h4>
<div class="language-mermaid vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">mermaid</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">erDiagram</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    %% 将中文实体名改为英文标识符</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    Student {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        string student_id PK</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        string name</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        string gender</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        string class</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        string password</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    Teacher {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        string teacher_id PK</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        string name</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        string gender</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        string department</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    Course {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        string course_name PK</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        string type</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        int required_students</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    Classroom {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        string class_id PK</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        string teacher_id FK</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        string course_name FK</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        datetime class_time</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        int student_count</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    %% 使用英文定义关系</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    Student ||--o{ Selection : "n"</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    Selection }o--|| Classroom : "m"</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    Teacher ||--|{ Lecture : "1"</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    Lecture }|--|| Classroom : "n"</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    Course ||--|{ Department : "1"</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    Department }|--|| Classroom : "n"</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br></div></div><p>E-R图提供了表示实体型(Entity)、属性(Attribute)和联系(Relationship)的方法。其中最核心的还属联系(Relationship)的表示。</p>
<ul>
<li>适用场景：虽然在UML类图中，也可以体现出聚合、依赖等关系。但是如果相关联的模型数量巨大的话，你会发现看起来特别费劲，要缩的很小才能看清全貌。这时候你需要E-R图出场了。</li>
<li>缺点：相对类图来说，E-R图无法定义类/实体的行为。它更面向数据库而不是代码。</li>
</ul>
<h4 id="_3-9-uml时序图" tabindex="-1">3.9 UML时序图 <a class="header-anchor" href="#_3-9-uml时序图" aria-label="Permalink to &quot;3.9 UML时序图&quot;">&ZeroWidthSpace;</a></h4>
<div class="language-mermaid vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">mermaid</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">sequenceDiagram</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    participant ViewRoot</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    participant WMVS</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    participant Surface</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    %% 主流程</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    ViewRoot->>WMVS: 1: relayout()</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    WMVS->>Surface: 1.1: newSurface()</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    activate Surface</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    Surface-->>WMVS: 1.1.1: init()</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    deactivate Surface</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    ViewRoot->>WMVS: 2: lockCanvas()</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    ViewRoot->>WMVS: 3: draw()</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    WMVS->>Surface: 4: unlockAndPost()</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    activate Surface</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    Surface-->>WMVS: 5: finishDrawing()</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    deactivate Surface</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    WMVS->>Surface: 6: setPosition()</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    WMVS->>Surface: 7: setLayer()</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    WMVS->>Surface: 8: show()</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br></div></div><p>时序图也是UML交互图中的一种，是描述对象是如何交互的，并且将重点放在消息序列上。也就是说，描述消息是如何在对象间发送和接收的。时序图有两个坐标轴：纵坐标轴显示时间，横坐标轴显示对象。</p>
<ul>
<li>适用场景：一般当我们想反映一个包含顺序的交互流程，比如http请求的生命周期、页面上某个按钮背后流转细节等情况时，就需要它了。</li>
<li>缺点：一个时序图仅能面向一个Case，同时画起来比较费时间。</li>
</ul>
<h3 id="四、实际的运用" tabindex="-1">四、实际的运用 <a class="header-anchor" href="#四、实际的运用" aria-label="Permalink to &quot;四、实际的运用&quot;">&ZeroWidthSpace;</a></h3>
<p>其实上一节中图的顺序就是按照由层次从高到底，粒度从粗到细规划的。我们可以用用例图来确定用户核心需求，再用Robustness Diagram定义好关键功能，随后在关键功能的实现上通过思维导图进行发散，然后用DFD图把粗粒度的内容串起来，至此大体的设计工作算是完成了。<br>
然后再通过流程图、UML类图、状态图、E-R图、时序图在不同的场景确定细节实现。最终就是Coding的事情了。<br>
其实最好的图是手稿，不但画起来快，还能让你的思维专注到构思上，用什么颜色之类的问题不会对你产生干扰。另外我们不要为了画图而画图，结合实际的情况把握好尺度，一般情况下，时间上不太会允许我们把图画的面面俱到，能覆盖到核心甚至80%就很好了。</p>
<p>参考资料：</p>
<ul>
<li><a href="https://mp.weixin.qq.com/s?__biz=MzU2NzEwMDc4OQ==&amp;mid=2247483696&amp;idx=1&amp;sn=5486eb664033ddbb6d59b3dfd0f8456b&amp;chksm=fca3152acbd49c3c301a619e7a7e6004863854a04b099836489a6f8ed337ddce2db1245e66c3&amp;scene=21#wechat_redirect" target="_blank" rel="noreferrer">程序设计中图的作用</a></li>
<li><a href="https://www.zhihu.com/question/22253854" target="_blank" rel="noreferrer">在软件开发过程中，有哪些UML图是比较常用的？ - 知乎</a></li>
<li><a href="https://www.zhihu.com/question/31998535/answer/54270159" target="_blank" rel="noreferrer">软件设计（总体设计、概要设计、详细设计）中常用的图有哪些？ - 知乎</a></li>
<li><a href="http://blog.csdn.net/t131452n/article/details/41381393" target="_blank" rel="noreferrer">软件开发过程中用到的各种图独孤文彬的博客-CSDN博客软件开发过程中采用多种图形化工具</a></li>
</ul>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[缓存系统设计]]></title>
            <link>http://ooowl.fun/blogs/Web%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/%E7%BC%93%E5%AD%98%E5%92%8C%E6%90%9C%E7%B4%A2/%E7%BC%93%E5%AD%98%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1.html</link>
            <guid isPermaLink="false">http://ooowl.fun/blogs/Web%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/%E7%BC%93%E5%AD%98%E5%92%8C%E6%90%9C%E7%B4%A2/%E7%BC%93%E5%AD%98%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1.html</guid>
            <pubDate>Tue, 10 Jan 2023 10:07:36 GMT</pubDate>
            <content:encoded><![CDATA[<h1 id="缓存系统设计" tabindex="-1">缓存系统设计 <a class="header-anchor" href="#缓存系统设计" aria-label="Permalink to &quot;缓存系统设计&quot;">&ZeroWidthSpace;</a></h1><p class="article-meta">创建于 2023年1月10日 18:07:36 · 约583字</p>
<p>缓存是系统中重要的一环，是为了解决io和</p>
<h3 id="缓存穿透" tabindex="-1">缓存穿透 <a class="header-anchor" href="#缓存穿透" aria-label="Permalink to &quot;缓存穿透&quot;">&ZeroWidthSpace;</a></h3>
<h4 id="描述" tabindex="-1">描述： <a class="header-anchor" href="#描述" aria-label="Permalink to &quot;描述：&quot;">&ZeroWidthSpace;</a></h4>
<p>缓存穿透是指缓存和数据库中都没有的数据，而用户不断发起请求，如发起为id为“-1”的数据或id为特别大不存在的数据。这时的用户很可能是攻击者，攻击会导致数据库压力过大。</p>
<h4 id="解决方案" tabindex="-1">解决方案： <a class="header-anchor" href="#解决方案" aria-label="Permalink to &quot;解决方案：&quot;">&ZeroWidthSpace;</a></h4>
<p>1 接口层增加校验，如用户鉴权校验，id做基础校验，id&lt;=0的直接拦截；
2 从缓存取不到的数据，在数据库中也没有取到，这时也可以将key-value对写为key-null，缓存有效时间可以设置短点，如30秒（设置太长会导致正常情况也没法使用）。这样可以防止攻击用户反复用同一个id暴力攻击
3 通过布隆过滤器实现</p>
<h3 id="缓存击穿" tabindex="-1">缓存击穿 <a class="header-anchor" href="#缓存击穿" aria-label="Permalink to &quot;缓存击穿&quot;">&ZeroWidthSpace;</a></h3>
<h4 id="描述-1" tabindex="-1">描述： <a class="header-anchor" href="#描述-1" aria-label="Permalink to &quot;描述：&quot;">&ZeroWidthSpace;</a></h4>
<p>缓存击穿是指缓存中没有但数据库中有的数据（一般是缓存时间到期），这时由于并发用户特别多，同时读缓存没读到数据，又同时去数据库去取数据，引起数据库压力瞬间增大，造成过大压力</p>
<h4 id="解决方案-1" tabindex="-1">解决方案： <a class="header-anchor" href="#解决方案-1" aria-label="Permalink to &quot;解决方案：&quot;">&ZeroWidthSpace;</a></h4>
<p>设置热点数据永远不过期。</p>
<h3 id="缓存雪崩" tabindex="-1">缓存雪崩 <a class="header-anchor" href="#缓存雪崩" aria-label="Permalink to &quot;缓存雪崩&quot;">&ZeroWidthSpace;</a></h3>
<h4 id="描述-2" tabindex="-1">描述： <a class="header-anchor" href="#描述-2" aria-label="Permalink to &quot;描述：&quot;">&ZeroWidthSpace;</a></h4>
<p>缓存雪崩是指缓存中数据大批量到过期时间，而查询数据量巨大，引起数据库压力过大甚至down机。和缓存击穿不同的是，        缓存击穿指并发查同一条数据，缓存雪崩是不同数据都过期了，很多数据都查不到从而查数据库。</p>
<h4 id="解决方案-2" tabindex="-1">解决方案： <a class="header-anchor" href="#解决方案-2" aria-label="Permalink to &quot;解决方案：&quot;">&ZeroWidthSpace;</a></h4>
<ol>
<li>缓存数据的过期时间设置随机，防止同一时间大量数据过期现象发生。</li>
<li>如果缓存数据库是分布式部署，将热点数据均匀分布在不同搞得缓存数据库中。</li>
<li>设置热点数据永远不过期</li>
</ol>
<p><a href="https://www.bilibili.com/video/BV1f94y1M7hZ/" target="_blank" rel="noreferrer">采用 Redis bitmap实现12306余票模型_哔哩哔哩_bilibili</a><br/>
<a href="https://www.bilibili.com/video/BV1ox4y1q7i7" target="_blank" rel="noreferrer">Redis缓存线上环境七大陷阱，你了解几个？建议收藏反复学习，面试时就不被面试官吊打了！_哔哩哔哩_bilibili</a><br/>
<a href="https://www.bilibili.com/video/BV1P5411C7C6/" target="_blank" rel="noreferrer">工作中用Redis，最常见的10种业务场景_哔哩哔哩_bilibili</a></p>
<p>测试一下RSS最新</p>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Fastapi-Sqlalchemy]]></title>
            <link>http://ooowl.fun/blogs/Python/Fastapi/Fastapi-EP2.html</link>
            <guid isPermaLink="false">http://ooowl.fun/blogs/Python/Fastapi/Fastapi-EP2.html</guid>
            <pubDate>Mon, 09 Jan 2023 21:43:28 GMT</pubDate>
            <content:encoded><![CDATA[<h1 id="fastapi-sqlalchemy" tabindex="-1">Fastapi-Sqlalchemy <a class="header-anchor" href="#fastapi-sqlalchemy" aria-label="Permalink to &quot;Fastapi-Sqlalchemy&quot;">&ZeroWidthSpace;</a></h1><p class="article-meta">创建于 2023年1月10日 05:43:28 · 约1,805字</p>
<h2 id="sqlalchemy" tabindex="-1">sqlalchemy <a class="header-anchor" href="#sqlalchemy" aria-label="Permalink to &quot;sqlalchemy&quot;">&ZeroWidthSpace;</a></h2>
<p>sqlalchemy是python的orm工具，被整合进fastapi里面了</p>
<p>updatetime应该在model生成而不是 请求时生成，因为前端会给你传乱七八糟的，这个字段应该是对用户只读或者不可见的，应该在model里定义而不是pydantic里定义。<br>
默认值的</p>
<h2 id="踩过的坑" tabindex="-1">踩过的坑 <a class="header-anchor" href="#踩过的坑" aria-label="Permalink to &quot;踩过的坑&quot;">&ZeroWidthSpace;</a></h2>
<h3 id="懒加载" tabindex="-1">懒加载 <a class="header-anchor" href="#懒加载" aria-label="Permalink to &quot;懒加载&quot;">&ZeroWidthSpace;</a></h3>
<p>默认的sqlalchemy的session是懒加载的，有时候update数据不进去可以考虑这个原因，使用<code>session.__repr__()</code>无感调用实现加载</p>
<h3 id="密码编码" tabindex="-1">密码编码 <a class="header-anchor" href="#密码编码" aria-label="Permalink to &quot;密码编码&quot;">&ZeroWidthSpace;</a></h3>
<p><a href="https://docs.sqlalchemy.org/en/14/core/engines.html" target="_blank" rel="noreferrer">Engine Configuration — SQLAlchemy 1.4 Documentation</a><br>
当密码中含有特殊字符比如@的时候，应该用特殊编码替换掉，其实python自带了一个包处理这个</p>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> urllib.parse</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">urllib.parse.quote_plus(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"kx@jj5/g"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=></span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'kx%40jj5</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%2F</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">g'</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # @被替换成了%40,/替换成了％2F</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br></div></div><div class="warning custom-block"><p class="custom-block-title">[⚠️Warning]</p>
<p>Changed in version 1.4: Support for <code>@</code> signs in hostnames and database names has been fixed. As a side effect of this fix, <code>@</code> signs in passwords must be escaped.</p>
<p>在版本1.4中改变: 在主机名和数据库名中支持@符号已经修复。作为此修复的一个副作用，必须转义密码中的@符号。</p>
</div>
<h3 id="update的时候报错" tabindex="-1">update的时候报错 <a class="header-anchor" href="#update的时候报错" aria-label="Permalink to &quot;update的时候报错&quot;">&ZeroWidthSpace;</a></h3>
<p>update方法默认为<code>synchronize_session='evaluate'</code><br>
在<code>update</code>方法中，还有一个可选参数<code>synchronize_session</code>，它用于指定何时将更改同步到数据库中。<code>synchronize_session</code>有三种取值：<code>False</code>、<code>True</code>和<code>'evaluate'</code>。</p>
<ul>
<li><code>synchronize_session=False</code>表示不同步任何更改，而是只将更改应用于查询对象本身。这意味着查询结果可能不反映实际数据库中的更改，因为更改将在提交事务之前被回滚。这个选项通常用于性能优化，特别是在需要更新大量记录的情况下。</li>
<li><code>synchronize_session='fetch'</code>表示立即同步更改到数据库中。查询结果将反映实际数据库中的更改。但是，这也可能导致脏读或死锁问题，因为其他并发事务可能正在访问被更新的记录。因此，这个选项通常用于更新少量记录或在并发性不是关键问题的情况下。</li>
<li><code>synchronize_session='evaluate'</code>表示根据查询对象自动决定何时同步更改。是默认值。如果查询对象是一个普通的SELECT查询，则会使用<code>True</code>；如果查询对象是一个JOIN查询，则会使用<code>False</code>。</li>
</ul>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">sqlalchemy.exc.InvalidRequestError: Synchronize session setting must be </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">set</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> to </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'evaluate'</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> or</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> False</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> bulk operations</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p>使用<code>filter</code>方法进行筛选后，调用<code>update</code>方法批量修改记录,SQLAlchemy无法确定何时将更改同步到数据库中，导致更新操作失败<br>
update的时候<code>synchronize_session=False</code>参数的诡异问题,忘了哪个错误了，直接设置为False就行了</p>
<h3 id="插入json字汉字被unicode编码" tabindex="-1">插入json字汉字被unicode编码 <a class="header-anchor" href="#插入json字汉字被unicode编码" aria-label="Permalink to &quot;插入json字汉字被unicode编码&quot;">&ZeroWidthSpace;</a></h3>
<p>插入json字段的时候，其中的汉字被编码为<code>\u4f60\u597d</code> 这样在数据库里和日志里都是unicode编码，但是查出来之后是正常的。<br>
检查sqlalchemy的engine，pg的client db都是utf-8但是不知道为啥哪里还是latin1(我恨他)<br>
<sup class="footnote-ref"><a href="#fn1" id="fnref1">[1]</a></sup></p>
<div class="language-sql vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">sql</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">select</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> *</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> from</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> users;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">alice|["𝓓𝓞Γ"]</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">bob|["\ud835\udcd3\ud835\udcde\u0393"]</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br></div></div><p>在issue<sup class="footnote-ref"><a href="#fn2" id="fnref2">[2]</a></sup>里有人问了，最后官方加上了个参数<sup class="footnote-ref"><a href="#fn3" id="fnref3">[3]</a></sup>
在create_engine申请的时候加入参数指定json序列化器</p>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">engine </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> create_engine(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"mysql://scott:tiger@hostname/dbname"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">                       encoding</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'utf8'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">echo</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">True</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">                       json_serializer</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=lambda</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> x: json.dumps(x, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">ensure_ascii</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">False</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">))</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br></div></div><p>之后存数据库就不会了</p>
<h3 id="json字段的模糊查询" tabindex="-1">json字段的模糊查询 <a class="header-anchor" href="#json字段的模糊查询" aria-label="Permalink to &quot;json字段的模糊查询&quot;">&ZeroWidthSpace;</a></h3>
<p>#todo pgsql的json字段模糊查询</p>
<h3 id="session传递和生命周期" tabindex="-1">session传递和生命周期 <a class="header-anchor" href="#session传递和生命周期" aria-label="Permalink to &quot;session传递和生命周期&quot;">&ZeroWidthSpace;</a></h3>
<p>python根据函数实际参数的类型不同进行传递:</p>
<ol>
<li>值传递：适用于实参类型为不可变类型（字符串、数字、元组）</li>
<li>引用（地址）传递：适用于实参类型为可变类型（列表，字典）</li>
</ol>
<p>sqlalchemy 的session是引用传递，在函数中传递的时候，子函数查询完了，在外层中可以读出来。</p>
<blockquote>
<p>查询出来的ORM对象本身在 <a href="https://www.osgeo.cn/sqlalchemy/orm/session_api.html#sqlalchemy.orm.Session" title="sqlalchemy.orm.Session" target="_blank" rel="noreferrer"><code>Session</code></a> ，在名为 <a href="https://www.osgeo.cn/sqlalchemy/glossary.html#term-identity-map" target="_blank" rel="noreferrer">identity map</a> -维护每个对象唯一副本的数据结构，其中“唯一”表示“只有一个具有特定主键的对象”。  Session以无状态的形式开始。一旦发出查询或其他对象被持久化，它将从 <a href="https://www.osgeo.cn/sqlalchemy/core/connections.html#sqlalchemy.engine.Engine" title="sqlalchemy.engine.Engine" target="_blank" rel="noreferrer"><code>Engine</code></a> 与 <a href="https://www.osgeo.cn/sqlalchemy/orm/session_api.html#sqlalchemy.orm.Session" title="sqlalchemy.orm.Session" target="_blank" rel="noreferrer"><code>Session</code></a> ，然后在该连接上建立一个事务  .</p>
</blockquote>
<p>也就是说在执行query之后的db对象维护的identity map不变，所以对这些对象还可以进行其他操作，但是此时如果query之后再update那么缓冲区就变成了update的结果，此时无法进行其他操作<br>
session相当于每个query返回一个cur，多个query实际上是分离的<br>
所以同一个query，应该先查出数据来再修改，但是取出来的数据会和db里面的不一致</p>
<blockquote>
<p>使用sqlalchemy 的engine直接执行sql <code>engine.execute(sql_)</code></p>
</blockquote>
<h2 id="redis集成" tabindex="-1">Redis集成 <a class="header-anchor" href="#redis集成" aria-label="Permalink to &quot;Redis集成&quot;">&ZeroWidthSpace;</a></h2>
<p><a href="https://yihuilu.github.io/Blog/archives/FastAPI%20Redis%20aioredis/" target="_blank" rel="noreferrer">小记一次FastAPI使用连接池调用Redis时，切换数据库的问题 - 一灰的随手记</a></p>
<h2 id="任务调度" tabindex="-1">任务调度 <a class="header-anchor" href="#任务调度" aria-label="Permalink to &quot;任务调度&quot;">&ZeroWidthSpace;</a></h2>
<p>使用schedule去调度，轻量好用，但是除了定时之外没有其他功能，而且是固定时间间隔检测，执行任务的时候线程会阻塞。</p>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> schedule</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> time</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> job</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">():</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Job started"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    time.sleep(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">5</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 任务执行时间为5秒</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Job completed"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 每3秒调度一次任务</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">schedule.every(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">).seconds.do(job)</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">while</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> True</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    schedule.run_pending()</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    time.sleep(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br></div></div><p>在fastapi中的最佳实践，在app_starup的时候启动一个线程，然后去定时执行，如果有多个Uvicorn的worker则会执行多次，此时需要锁，引入外部的锁背离了schdule的初衷，不如直接apschduler，所以需要更简便的锁<br>
任务要保证时间间隔内要执行完毕，否则任务会积压，schdule是维护一个内部的任务表，每当符合条件就往表里添加一个任务。<br>
使用<code>fcntl</code>(内置库)，在系统中自动生成锁文件，这样进程就只会启动一个线程，没有什么副作用。<br>
要注意如果任务出错线程会直接崩掉所以不要拿来做非常重要的事情</p>
<details class="details custom-block"><summary>Click to see more</summary>
<p>这是任务</p>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> time  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> datetime </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> datetime  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> schedule  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> sqlalchemy </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> and_  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> app.db.session </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> SessionLocal  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> app.modules.user.user_models </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> PushWXMsgInfoDelay  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> app.modules.user.wx_request_msg </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> push_wx_msg  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># import your model here  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># your class&#x26;function here  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> push_wx_notify</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">():  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    with</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> SessionLocal() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">as</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> db:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        today </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> datetime.today()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        # 将日期转换为 datetime 类型  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        today_start </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> datetime(today.year, today.month, today.day, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        # 获取今天的结束时间（23:59:59.999999）  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        today_end </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> datetime(today.year, today.month, today.day, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">23</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">59</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">59</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">999999</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        # 查询 push_date 是今天的所有记录  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        results </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> db.query(PushWXMsgInfoDelay).filter(  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            and_(  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">                PushWXMsgInfoDelay.push_date </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">>=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> today_start,  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">                PushWXMsgInfoDelay.push_date </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x3C;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> today_end,  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">                PushWXMsgInfoDelay.pushed </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">==</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            )  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        ).all()  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> push </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> results:  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">            print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"延时推送："</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, push)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            result </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> push_wx_msg(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">**</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">push.param)  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">            print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"推送结果："</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,result)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        db.query(PushWXMsgInfoDelay).filter(  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            and_(  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">                PushWXMsgInfoDelay.push_date </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">>=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> today_start,  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">                PushWXMsgInfoDelay.push_date </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x3C;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> today_end,  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">                PushWXMsgInfoDelay.pushed </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">==</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            )  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        ).update({</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"pushed"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">})  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        db.commit()  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"update record !"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">f</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Task executed at now </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">{</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">datetime.now().strftime(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'%Y-%m-</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%d</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> %H:%M:%S'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">}</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> schedule_task</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">():  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    # 每天7点执行  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    schedule.every().day.at(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"07:00"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">).do(push_wx_notify)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    while</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> True</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        schedule.run_pending()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        time.sleep(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 3 秒检查一次，不会占用过多CPU</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br><span class="line-number">50</span><br><span class="line-number">51</span><br><span class="line-number">52</span><br><span class="line-number">53</span><br></div></div><p>这是fastapi启动的时候，一种多进程的实践</p>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> fcntl  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> os  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> threading</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">@app.on_event</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"startup"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> start_scheduler</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">():  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    lock_file </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "/tmp/scheduler.lock"</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  # 锁文件的路径，可以根据需要调整  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    lock_file_descriptor </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> None</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    try</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        # 打开锁文件  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        lock_file_descriptor </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> os.open(lock_file, os.</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">O_CREAT</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> |</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> os.</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">O_RDWR</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        # 尝试获取文件锁  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        fcntl.flock(lock_file_descriptor, fcntl.</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">LOCK_EX</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> |</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> fcntl.</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">LOCK_NB</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Acquired lock, starting scheduler thread."</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        # 如果成功获取锁，启动守护线程  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        task_thread </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> threading.Thread(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">target</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">schedule_task)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        task_thread.daemon </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> True</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  # 确保程序退出时线程也能自动结束  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        task_thread.start()  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    except</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> BlockingIOError</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        # 如果未能获取锁，表示另一个worker已经启动了线程  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Lock already acquired by another worker. Skipping scheduler thread."</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    finally</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> lock_file_descriptor:  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">            # 保持锁的文件描述符打开，直到程序结束，以防止其他进程获取锁  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            pass</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br></div></div></details>
<p>在docker停止的时候，uvicorn会处理完最后一个请求之后停止，所以直接使用docker是安全的。但是数据库会直接断掉然后没有完成的事务放弃掉。</p>
<hr class="footnotes-sep">
<section class="footnotes">
<ol class="footnotes-list">
<li id="fn1" class="footnote-item"><p><a href="https://gerrit.sqlalchemy.org/c/sqlalchemy/sqlalchemy/+/1400/" target="_blank" rel="noreferrer">Correct name for json_serializer / json_deserializer, document and test (I1dbfe439) · Gerrit Code Review</a><br/> <a href="#fnref1" class="footnote-backref">↩︎</a></p>
</li>
<li id="fn2" class="footnote-item"><p><a href="https://github.com/sqlalchemy/sqlalchemy/issues/4798" target="_blank" rel="noreferrer">Error when querying JSON columns with wide unicode characters. · Issue #4798 · sqlalchemy/sqlalchemy · GitHub</a><br/> <a href="#fnref2" class="footnote-backref">↩︎</a></p>
</li>
<li id="fn3" class="footnote-item"><p><a href="https://www.osgeo.cn/sqlalchemy/core/engines.html?highlight=json_serializer#sqlalchemy.create_engine.params.json_serializer" target="_blank" rel="noreferrer">引擎配置 — SQLAlchemy 1.4 Documentation</a> <a href="#fnref3" class="footnote-backref">↩︎</a></p>
</li>
</ol>
</section>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Fastapi-Pydantic]]></title>
            <link>http://ooowl.fun/blogs/Python/Fastapi/Fastapi-EP1.html</link>
            <guid isPermaLink="false">http://ooowl.fun/blogs/Python/Fastapi/Fastapi-EP1.html</guid>
            <pubDate>Thu, 08 Dec 2022 13:36:13 GMT</pubDate>
            <description><![CDATA[首先我们应该思考一个web框架有哪些大部分组成，网页web的功能就是把持久化的数据提供为http服务 之后随着深入理解，我会不断更新这个东西，有可能会独立出一篇文章来]]></description>
            <content:encoded><![CDATA[<h1 id="fastapi-pydantic" tabindex="-1">Fastapi-Pydantic <a class="header-anchor" href="#fastapi-pydantic" aria-label="Permalink to &quot;Fastapi-Pydantic&quot;">&ZeroWidthSpace;</a></h1><p class="article-meta">创建于 2022年12月8日 21:36:13 · 约1,985字</p>
<h2 id="综述" tabindex="-1">综述 <a class="header-anchor" href="#综述" aria-label="Permalink to &quot;综述&quot;">&ZeroWidthSpace;</a></h2>
<p>首先我们应该思考一个web框架有哪些大部分组成，网页web的功能就是把持久化的数据提供为http服务<br>
之后随着深入理解，我会不断更新这个东西，有可能会独立出一篇文章来</p>
<p><strong>一门语言里面有什么？</strong>
<strong>一个web框架里面应该有什么？主要功能点列表</strong></p>
<ul>
<li>路由(Routing)</li>
<li>请求-响应处理</li>
<li>中间件(Middleware)</li>
<li>模板引擎(Template Engine)</li>
<li>静态文件处理</li>
<li>会话管理(Session Management)</li>
<li>安全性</li>
<li>数据验证</li>
<li>数据库支持</li>
<li>测试支持</li>
<li>国际化和本地化</li>
<li>缓存支持</li>
<li>任务调度</li>
<li>日志记录</li>
</ul>
<p><a href="https://zhu327.github.io/2018/08/29/gunicorn%E4%B8%8Euwsgi%E4%B9%8B%E6%88%91%E8%A7%81/" target="_blank" rel="noreferrer">Gunicorn与uWSGI之我见 · 跬步</a><br>
<a href="https://bbs.huaweicloud.com/blogs/309794" target="_blank" rel="noreferrer">Gunicorn的使用手册看这篇就够了【用过都说好】-云社区-华为云</a><br>
<a href="https://blog.csdn.net/studyeboy/article/details/120956188" target="_blank" rel="noreferrer">WSGI和ASGI的异同_studyeboy的博客-CSDN博客_asgi和wsgi的区别</a><br/>
<a href="https://zhuanlan.zhihu.com/p/115237857" target="_blank" rel="noreferrer">快如闪电的异步服务器Uvicorn - 知乎</a><br/>
<a href="https://zhu327.github.io/2014/09/21/wsgi-%E7%90%86%E8%A7%A3/" target="_blank" rel="noreferrer">WSGI 理解 · 跬步</a><br/>
<a href="https://zhu327.github.io/2014/12/26/wsgi%E4%B8%8Etornado%E6%83%B3%E5%88%B0%E7%9A%84/" target="_blank" rel="noreferrer">WSGI与Tornado想到的 · 跬步</a><br/>
<a href="https://bbs.huaweicloud.com/blogs/309794" target="_blank" rel="noreferrer">Gunicorn的使用手册看这篇就够了【用过都说好】-云社区-华为云</a></p>
<p><a href="https://www.cnblogs.com/liaowenhui/p/15390254.html" target="_blank" rel="noreferrer">Cookie Session Token JWT的区别和实现原理(2) - JustJavaIt - 博客园</a><br/>
<a href="https://www.bilibili.com/video/BV1f3411G7xk" target="_blank" rel="noreferrer">普通登录、微服务登录、单点登录的区别_哔哩哔哩_bilibili</a>
session</p>
<ol>
<li>Get方法长度限制</li>
</ol>
<p>Http Get方法提交的数据大小长度并没有限制，HTTP协议规范没有对URL长度进行限制。这个限制是特定的浏览器及服务器对它的限制。</p>
<table tabindex="0">
<thead>
<tr>
<th style="text-align:center">浏览器</th>
<th style="text-align:center">字符长度限制</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center">Microsoft Internet Explorer (Browser)</td>
<td style="text-align:center">2083<br/>如果超过，提交按钮没有任何反应</td>
</tr>
<tr>
<td style="text-align:center">Firefox (Browser)</td>
<td style="text-align:center">65,536</td>
</tr>
<tr>
<td style="text-align:center">Safari (Browser)</td>
<td style="text-align:center">80,000</td>
</tr>
<tr>
<td style="text-align:center">Opera (Browser)</td>
<td style="text-align:center">190,000</td>
</tr>
<tr>
<td style="text-align:center">Google (chrome)</td>
<td style="text-align:center">8182</td>
</tr>
<tr>
<td style="text-align:center">Apache (Server)</td>
<td style="text-align:center">8,192</td>
</tr>
<tr>
<td style="text-align:center">Microsoft Internet Information Server(IIS)</td>
<td style="text-align:center">16,384</td>
</tr>
</tbody>
</table>
<p>由此，URL最好不要超过IE的最大长度限制(2083个字符），当然，如果URL不直接提供给用户，而是提供给程序调用，这时的长度就只受Web服务器影响了</p>
<p>POST请求理论上也是不限制大小的，真正对其大小进行限制的是服务器的处理程序能力。Tomcat服务器对POST大小限制为2M</p>
<div class="language-json vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">json</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">"id"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span><span style="--shiki-light:#B31D28;--shiki-light-font-style:italic;--shiki-dark:#FDAEB7;--shiki-dark-font-style:italic">string</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">4-20</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">"string_list"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:[</span><span style="--shiki-light:#B31D28;--shiki-light-font-style:italic;--shiki-dark:#FDAEB7;--shiki-dark-font-style:italic">string(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">4-20</span><span style="--shiki-light:#B31D28;--shiki-light-font-style:italic;--shiki-dark:#FDAEB7;--shiki-dark-font-style:italic">)</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">100</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]} * </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">2000</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> 条 fastapi的POST数据就buffer溢出报错</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><h3 id="api和spi" tabindex="-1">API和SPI <a class="header-anchor" href="#api和spi" aria-label="Permalink to &quot;API和SPI&quot;">&ZeroWidthSpace;</a></h3>
<ul>
<li><a href="https://one-programmer.github.io/docs/http-api-design/" target="_blank" rel="noreferrer">API设计指南</a>
通俗的讲：API 和 SPI 都是相对的概念，他们的差别只在语义上，API 直接被应用开发人员使用，SPI 被框架扩展人员使用<br>
API （Application Programming Interface）</li>
<li>大多数情况下，都是<strong>实现方</strong>来制定接口并完成对接口的不同实现，<strong>调用方</strong>仅仅依赖却无权选择不同实现。
SPI (Service Provider Interface)</li>
<li>而如果是<strong>调用方</strong>来制定接口，<strong>实现方</strong>来针对接口来实现不同的实现。<strong>调用方</strong>来选择自己需要的实现方。
需要注意的事项
SPI 和 API 也不一定是接口，我这里都是指狭义的具体的接口。
<a href="https://github.com/ibbd-dev/fastapi-start" target="_blank" rel="noreferrer">GitHub - ibbd-dev/fastapi-start: FastAPI脚手架：用于系统后端接口项目的</a></li>
</ul>
<h2 id="fastapi中async" tabindex="-1">fastapi中async <a class="header-anchor" href="#fastapi中async" aria-label="Permalink to &quot;fastapi中async&quot;">&ZeroWidthSpace;</a></h2>
<p>是否使用async<sup class="footnote-ref"><a href="#fn1" id="fnref1">[1]</a></sup><br>
使用async和不使用async</p>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> fastapi </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> FastAPI</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> time</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> asyncio</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> os</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">app </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> FastAPI()</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">@app.get</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"/async_slowest"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">async</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> async_slowest</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">():</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">   time.sleep(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">   return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"message"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"async mode but use sync sleep"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">@app.get</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"/async_sleep_in_thread"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">async</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> async_sleep_in_thread</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">():</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">   loop </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> asyncio.get_event_loop()</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">   await</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> loop.run_in_executor(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">None</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, time.sleep, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">   return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"message"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"sleep run in thread pool"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">@app.get</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"/async_sleep"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">async</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> async_sleep</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">():</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">   await</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> asyncio.sleep(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">   return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"message"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"async mode sleep"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">@app.get</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"/sync"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> sync_sleep</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">():</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">   time.sleep(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">   return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"message"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"sync, but run in thread pool"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br></div></div><p>分别执行100次</p>
<table tabindex="0">
<thead>
<tr>
<th style="text-align:left">模式</th>
<th style="text-align:left">原理</th>
<th style="text-align:left">时间</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:left">异步函数同步方法</td>
<td style="text-align:left">会被扔到eventloop同步执行</td>
<td style="text-align:left">100s</td>
</tr>
<tr>
<td style="text-align:left">异步函数线程执行run_in_executor</td>
<td style="text-align:left">扔到线程池里执行开100个线程</td>
<td style="text-align:left">1s</td>
</tr>
<tr>
<td style="text-align:left">异步函数异步方法</td>
<td style="text-align:left">就是纯纯异步</td>
<td style="text-align:left">1s</td>
</tr>
<tr>
<td style="text-align:left">同步函数同步方法</td>
<td style="text-align:left">自动线程池执行,线程池的默认核心数*5</td>
<td style="text-align:left">3s</td>
</tr>
</tbody>
</table>
<p>官方文档的细节<sup class="footnote-ref"><a href="#fn2" id="fnref2">[2]</a></sup> #todo 看完
<strong>FastAPI会对路径操作函数(path operation function)和依赖(dependencies)进行特殊处理</strong>。这个特殊处理是：如果你把函数定义为def而不是async def，那么FastAPI会把它放到单独的线程池中，异步执行，这就是FastAPI精彩的地方。就像官方所说，如果你不清楚你函数里面的调用是不是异步(能不能用await)，那么就把它定义为普通函数，FastAPI会采用多线程的方式处理。乱用async，在async里面有同步调用，则会变成串行，Fast秒变Slow。<br>
而对于其他函数，FastAPI则不会管，def就是同步调用，立马返回结果。<br>
现在回过头来看前面的那句话：但是无论你是否使用async，FastAPI都将异步工作，以达到&quot;Fast&quot;的运行速度。</p>
<h2 id="pydantic" tabindex="-1">pydantic <a class="header-anchor" href="#pydantic" aria-label="Permalink to &quot;pydantic&quot;">&ZeroWidthSpace;</a></h2>
<p>pydantic比dataclass以及其他方法都慢得多，无论是在创建还是在修改的时候，pydantic因为在runtime会进行解析，创建需要5400ns，但例如tuple只需要30ns，慢了一百八十倍。dataclass需要250ns，慢了21倍。<br>
但是好用啊！</p>
<h3 id="序列化" tabindex="-1">序列化 <a class="header-anchor" href="#序列化" aria-label="Permalink to &quot;序列化&quot;">&ZeroWidthSpace;</a></h3>
<p>pydantic的基本使用就不说了，继承Base剩下的就是定义字段名字。<br>
字段的名字就是序列化字典和json的名字 ，Field中可以使用alias参数<br>
在使用alias之后，parse的时候读取的就是alias字段。<br>
序列化的时候json和dict，指定by_alias键就是alias，否则就是定义的字段名字。</p>
<details class="details custom-block"><summary>Click to see more</summary>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> pydantic </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> BaseModel, Field  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> R</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">BaseModel</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">):  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    code: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">int</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Field(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">alias</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Code"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    message: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">str</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Field(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">alias</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Mess"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    data: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">str</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Field(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">alias</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Data"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    commited: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">int</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">r </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> R.parse_obj({</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Code"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Mess"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"abc"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Data"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"abc"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"commited"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">})  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">y</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">r.dict(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">by_alias</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">True</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">x </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> r.json()  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(x,y)</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br></div></div><p>运行结果</p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>{"code": 1, "message": "abc", "data": "abc", "commited": 2} {'Code': 1, 'Mess': 'abc', 'Data': 'abc', 'commited': 2}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div></details>
<p>常用的还有自定义json序列化器，可以按照类型序列化，也可以拦截自定义处理<br>
<code>extra = Extra.allow </code> 允许创建完model后还可以添加属性<br>
使用json序列化器的时候，使用encoders只会去序列化非内置字段，builtin的类型会直接去序列化。<br>
对于所有的类型都序列化的话，有两种方法</p>
<ul>
<li>使用json_dumps 参数，会把所有的字段传进去，它会比指定的encoder早返回的是json编码的解码？，encoder会失效,</li>
<li>@validator这种方法还没实验</li>
</ul>
<details class="details custom-block"><summary>Click to see more</summary>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># -*-coding:utf-8-*-  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># SettingCode here  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">__author__ </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "a_little_rubbish"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">__date__ </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "2023/1/9 21:49"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># import your model here  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> datetime </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> datetime  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> orjson  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> pydantic </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> BaseModel, Field, Extra  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> utils.schema </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> convert_date  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> convert_datetime</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(dt) -> </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">str</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 拦截器</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(dt.strftime(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'%Y-%m-</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%d</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> %H:%M:%S'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">))  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> dt.strftime(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'%Y-%m-</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%d</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> %H:%M:%S'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> ascii_to_uft8</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(v, </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, default):  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> key, value </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> v.items():  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        if</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> isinstance</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(value, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">str</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">):  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">            print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"str hook"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            v[key] </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> value.encode(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'utf-8'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> orjson.dumps(v, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">default</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">default).decode()  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 注意返回什么</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> TemplateBaseModel</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">BaseModel</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">):  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Config</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        extra </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Extra.allow  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 允许创建完model后还可以添加属性</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        arbitrary_types_allowed </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> True</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  # 允许自定义类型</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        json_dumps </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> ascii_to_uft8  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 指定json序列化器，可以做钩子</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        orm_mode </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> True</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        json_encoders </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 对特定类型的json编码器</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">            # custom output conversion for datetime  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            datetime : convert_datetime  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        }  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> R</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">TemplateBaseModel</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">):  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    code: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">int</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Field(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">alias</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Code"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    message: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">str</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Field(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">alias</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Mess"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    data: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">str</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Field(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">alias</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Data"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    commited: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">int</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">r </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> R.parse_obj({</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Code"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Mess"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"abc"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Data"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"abc"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"commited"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">})  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">y</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">r.dict(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">by_alias</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">True</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 使用alias</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">x </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> r.json()  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(x,y)</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br></div></div><p>运行结果</p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>str hook</span></span>
<span class="line"><span>str hook</span></span>
<span class="line"><span>{"code":1,"message":"abc","data":"abc","commited":2} {'Code': 1, 'Mess': 'abc', 'Data': 'abc', 'commited': 2}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br></div></div></details>
<h3 id="默认生成uuid不生效" tabindex="-1">默认生成uuid不生效 <a class="header-anchor" href="#默认生成uuid不生效" aria-label="Permalink to &quot;默认生成uuid不生效&quot;">&ZeroWidthSpace;</a></h3>
<p>问题：有一个字段不是前端传过来的，需要赋一个默认值uuid，但是发现穿进来的数据每一批的uuid都一样，不用批次的uuid有时候一样有时候不一样<br>
原因：验证器生效在默认值之前，也就是说pydantic先验证再给默认值，而且每个pydantic对象只初始化一次，这样就导致uuid字段被固定了下来，同一批次的数据都被验证器赋了同一个uuid。不用批次的数据可能会被多进程(线程?)处理，如果两次都是同一个线程，那就uuid相同不同线程uuid就不同</p>
<p>#todo Fastapi系统的整理一下
<a href="https://www.imooc.com/learn/1299" target="_blank" rel="noreferrer">高性能 FastAPI 框架入门精讲-慕课网-Python Web 框架</a><br/>
<a href="https://www.modb.pro/db/144277" target="_blank" rel="noreferrer">Fastapi框架实战系列-纯个人使用之脚手架搭建篇 - 墨天轮</a></p>
<p>使用jwt的时候生成jwt的16进制字符串密钥</p>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> secrets</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(secrets.token_hex(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">32</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 生成一个安全的随机密钥</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br></div></div><p>pgsql-&gt;redis-&gt;rabbit-&gt;mongo-&gt;es-&gt;minio
fastapi-&gt;python-&gt;sqlalchemy-&gt;celery-&gt;pandas和numpy</p>
<p><a href="https://github.com/dmontagu/fastapi-utils/tree/master" target="_blank" rel="noreferrer">GitHub - dmontagu/fastapi-utils: Reusable utilities for FastAPI</a></p>
<p><code>from __future__ import annotations</code></p>
<hr class="footnotes-sep">
<section class="footnotes">
<ol class="footnotes-list">
<li id="fn1" class="footnote-item"><p><a href="https://blog.csdn.net/qq_29518275/article/details/109360617" target="_blank" rel="noreferrer">FastAPI到底用不用async？_程序的战歌的博客-CSDN博客_fastapi async</a><br/> <a href="#fnref1" class="footnote-backref">↩︎</a></p>
</li>
<li id="fn2" class="footnote-item"><p><a href="https://fastapi.tiangolo.com/async/" target="_blank" rel="noreferrer">Concurrency and async / await - FastAPI</a> <a href="#fnref2" class="footnote-backref">↩︎</a></p>
</li>
</ol>
</section>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[leetcode-EP1]]></title>
            <link>http://ooowl.fun/blogs/%E5%88%B7%E7%AE%97%E6%B3%95/Leetcode-EP1.html</link>
            <guid isPermaLink="false">http://ooowl.fun/blogs/%E5%88%B7%E7%AE%97%E6%B3%95/Leetcode-EP1.html</guid>
            <pubDate>Tue, 11 Oct 2022 22:28:02 GMT</pubDate>
            <content:encoded><![CDATA[<h1 id="leetcode-ep1" tabindex="-1">leetcode-EP1 <a class="header-anchor" href="#leetcode-ep1" aria-label="Permalink to &quot;leetcode-EP1&quot;">&ZeroWidthSpace;</a></h1><p class="article-meta">创建于 2022年10月12日 06:28:02 · 约203字</p>
<p><a href="https://leetcode.cn/studyplan/leetcode-75/" target="_blank" rel="noreferrer">LeetCode 75 - 学习计划 - 力扣（LeetCode）全球极客挚爱的技术成长平台</a></p>
<h2 id="leetcode-ep1-1" tabindex="-1">leetcode-EP1 <a class="header-anchor" href="#leetcode-ep1-1" aria-label="Permalink to &quot;leetcode-EP1&quot;">&ZeroWidthSpace;</a></h2>
<h3 id="二分查找" tabindex="-1">二分查找 <a class="header-anchor" href="#二分查找" aria-label="Permalink to &quot;二分查找&quot;">&ZeroWidthSpace;</a></h3>
<h4 id="分类" tabindex="-1">分类 <a class="header-anchor" href="#分类" aria-label="Permalink to &quot;分类&quot;">&ZeroWidthSpace;</a></h4>
<p>leetcode题号: 704. 二分查找
代码随想录视频<a href="https://www.bilibili.com/video/BV1fA4y1o715" target="_blank" rel="noreferrer">链接</a>
时间：37min</p>
<h4 id="代码" tabindex="-1">代码 <a class="header-anchor" href="#代码" aria-label="Permalink to &quot;代码&quot;">&ZeroWidthSpace;</a></h4>
<details class="details custom-block"><summary>Click to see more</summary>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> search</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(nums, target: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">int</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) -> </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">int</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    result </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> -</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    right </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> len</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(nums) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    left </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    middle </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> int</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(right </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">/</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    while</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> True</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> left </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">==</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> right:  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> target </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">==</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> nums[middle]:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">                result </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> middle  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            break</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> target </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">==</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> nums[middle]:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            result </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> middle  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            break</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        elif</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> target </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> nums[middle]:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            left </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> middle </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            middle </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> int</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">((left </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> right) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">/</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        elif</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> target </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x3C;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> nums[middle]:  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> middle</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">==</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">left: </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 处理边界条件，例如两个元素，为什右边不会有这个情况  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">                right </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> middle  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            else</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">                right </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> middle </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            middle </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> int</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">((left </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> right) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">/</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> result  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">if</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __name__</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> ==</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> '__main__'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(search([</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">4</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">5</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">6</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">],</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">7</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">))</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br></div></div><p>运行结果</p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>PASS 44ms</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div></details>
<h4 id="注意的点" tabindex="-1">注意的点: <a class="header-anchor" href="#注意的点" aria-label="Permalink to &quot;注意的点:&quot;">&ZeroWidthSpace;</a></h4>
<ul>
<li>注意边界条件开闭情况，一般是左闭右开或左闭右闭，在中间处理的时候也遵循这个</li>
<li>二分要在有序序列中查找</li>
<li>其他：None</li>
</ul>
<h3 id="删除元素" tabindex="-1">删除元素 <a class="header-anchor" href="#删除元素" aria-label="Permalink to &quot;删除元素&quot;">&ZeroWidthSpace;</a></h3>
<h4 id="分类-1" tabindex="-1">分类 <a class="header-anchor" href="#分类-1" aria-label="Permalink to &quot;分类&quot;">&ZeroWidthSpace;</a></h4>
<p>leetcode题号:27
代码随想录视频<a href="https://www.bilibili.com/video/BV12A4y1Z7LP/" target="_blank" rel="noreferrer">链接</a>
时间：45min</p>
<h4 id="代码-1" tabindex="-1">代码 <a class="header-anchor" href="#代码-1" aria-label="Permalink to &quot;代码&quot;">&ZeroWidthSpace;</a></h4>
<details class="details custom-block"><summary>Click to see more</summary>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> removeElement</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self, nums: List[</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">int</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">], val: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">int</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) -> </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">int</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    '''</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    双指针法</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    '''</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        f</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        s</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        while</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (f</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x3C;=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">len</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(nums)</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">):</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> nums[f]</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">==</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">val:</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">                f</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">                continue</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            else</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">                nums[s]</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">nums[f]</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">                f</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">                s</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> len</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(nums[:s])</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> removeElement</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self, nums: List[</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">int</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">], val: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">int</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) -> </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">int</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    ‘‘‘</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    暴力移除</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    '''</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">        i = 0</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">        while (i &#x3C; len(nums)):</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">            if nums[i] == val:</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">                for j in range(i, len(nums) - 1):</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">                    nums[j] = nums[j + 1]</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">                del(nums[-1])</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">            else:</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">                i += 1</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">        return len(nums)</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br></div></div><p>运行结果</p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>PASS</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div></details>
<h4 id="注意的点-1" tabindex="-1">注意的点: <a class="header-anchor" href="#注意的点-1" aria-label="Permalink to &quot;注意的点:&quot;">&ZeroWidthSpace;</a></h4>
<ul>
<li>主要就是处理边界条件，双指针fast一直拿最新的数据，slow就管着存，注意最后一个元素和重复元素的处理</li>
<li>其他：None</li>
</ul>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[part 4 踩坑记录]]></title>
            <link>http://ooowl.fun/blogs/Web%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/%E6%B5%8B%E8%AF%95%E8%BF%90%E7%BB%B4/linux%E7%AE%80%E5%8D%95%E9%80%9F%E9%80%9A/part-4-%E8%B8%A9%E5%9D%91%E8%AE%B0%E5%BD%95.html</link>
            <guid isPermaLink="false">http://ooowl.fun/blogs/Web%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/%E6%B5%8B%E8%AF%95%E8%BF%90%E7%BB%B4/linux%E7%AE%80%E5%8D%95%E9%80%9F%E9%80%9A/part-4-%E8%B8%A9%E5%9D%91%E8%AE%B0%E5%BD%95.html</guid>
            <pubDate>Wed, 03 Aug 2022 22:35:16 GMT</pubDate>
            <content:encoded><![CDATA[<h1 id="part-4-踩坑记录" tabindex="-1">part 4 踩坑记录 <a class="header-anchor" href="#part-4-踩坑记录" aria-label="Permalink to &quot;part 4 踩坑记录&quot;">&ZeroWidthSpace;</a></h1><p class="article-meta">创建于 2022年8月4日 06:35:16 · 约909字</p>
<p>在终端中输入&quot;vim -R&quot;或&quot;vim --readonly&quot;命令后，vim会以只读模式启动</p>
<p><a href="https://chen3961.github.io/2019/06/10/Ten-black-hole-in-bash/" target="_blank" rel="noreferrer">常见的Shell大坑 – 呀哈哈的咿咿呀呀</a></p>
<h2 id="linux出现ssl错误" tabindex="-1">linux出现ssl错误 <a class="header-anchor" href="#linux出现ssl错误" aria-label="Permalink to &quot;linux出现ssl错误&quot;">&ZeroWidthSpace;</a></h2>
<p>使用pip安装包的时候发现ssl错误，怀疑是openssl的问题。排查证书发现都在，没问题。<br>
测试网络，虚拟机与宿主机通信正常，测试curl google发现报ssl的问题，怀疑不仅是pip的ssl，进一步搜索网上说可能是系统时间有问题。<br>
date hwclock查看一下，硬件时间与本地时间差30分钟。<br>
<code>date -s 11/03/2009</code> 将系统日期设定成2009年11月3日的命令<br>
<code>date -s 17:55:55</code>将系统时间设定成下午5点55分55秒的命令<br>
<code>hwclock -w</code> 将当前时间和日期写入BIOS，避免重启后失效<br>
调整好时间后正常了</p>
<h2 id="wc-l-mac下会出现奇怪空格" tabindex="-1">wc -l mac下会出现奇怪空格 <a class="header-anchor" href="#wc-l-mac下会出现奇怪空格" aria-label="Permalink to &quot;wc -l mac下会出现奇怪空格&quot;">&ZeroWidthSpace;</a></h2>
<p>wc 命令统计指定文件中的字节数、字数、行数，并将统计结果显示输出。该命令统计指定文件中的字节数、字数、行数。如果没有给出文件名，则从标准输入读取。wc同时也给出所指定文件的总统计数。</p>
<div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">wc</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">-c 统计字节数。</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">-l 统计行数。</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">-m 统计字符数。这个标志不能与 -c 标志一起使用。</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">-w 统计字数。一个字被定义为由空白、跳格或换行字符分隔的字符串。</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">-L 打印最长行的长度。</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br></div></div><p>wc -l 的时候发现无法取到信息而是空，发现输出前面有7个空格<code>       1 a</code>而在linux为<code>1 a</code> 注意这个坑</p>
<p><a href="https://www.cnblogs.com/linagcheng/p/15748465.html" target="_blank" rel="noreferrer">linux离线安装软件（一）——Ubuntu 离线以安装包形式安装openssh-server 和 vsftp等软件 - 凉城旧巷 - 博客园</a></p>
<h2 id="不要使用vim直接编辑文件" tabindex="-1">不要使用vim直接编辑文件 <a class="header-anchor" href="#不要使用vim直接编辑文件" aria-label="Permalink to &quot;不要使用vim直接编辑文件&quot;">&ZeroWidthSpace;</a></h2>
<p>vim实际上也是把数据全都加载到内存中，如果文件很大会内存崩溃，使用vim的view命令查看。此模式下文件是只读的不能编辑<br>
在终端中输入&quot;vim -R&quot;或&quot;vim --readonly&quot;命令后，vim会以只读模式启动，约等于view</p>
<ol>
<li><strong>vim：</strong> 优点：功能强大，支持编辑和查看文件，提供了丰富的编辑功能和快捷键。缺点：加载大文件耗时，占用较多的内存，使用复杂。</li>
<li><strong>view（vim的只读模式）：</strong> 优点：快速加载大文件，占用较少的内存，安全性高。缺点：只能查看文件内容，不能进行编辑操作。</li>
<li><strong>cat：</strong> 优点：简单易用，适用于查看较小的<a href="https://so.csdn.net/so/search?q=%E6%96%87%E6%9C%AC%E6%96%87%E4%BB%B6&amp;spm=1001.2101.3001.7020" target="_blank" rel="noreferrer">文本文件</a>。缺点：无法翻页浏览，不支持搜索和编辑功能。</li>
<li><strong>less：</strong> 优点：加载大文件较快，占用较少的内存，支持上下滚动、搜索、跳转等功能。缺点：功能相对不如vim丰富，对于大文件并不是最高效的选择。</li>
<li><strong>more：</strong> 优点：简单易用，适用于分页查看大文件。缺点：功能有限，不支持搜索和编辑功能。</li>
<li><strong>head：</strong> 优点：显示文件开始部分，可以快速预览文件内容。缺点：只显示文件的开头部分，无法查看全文。</li>
<li><strong>tail：</strong> 优点：显示文件结尾部分，适用于查看最新的日志。缺点：只显示文件的结尾部分，无法查看全文。</li>
<li><strong>grep：</strong> 优点：用于在文件中搜索指定的字符串，可以快速定位关键字。缺点：只能查看匹配的行，无法查看全文内容。</li>
</ol>
<p><a href="https://www.sooele.com/4656.html" target="_blank" rel="noreferrer">常见的端口转发工具</a></p>
<h2 id="安装使用7z" tabindex="-1">安装使用7z <a class="header-anchor" href="#安装使用7z" aria-label="Permalink to &quot;安装使用7z&quot;">&ZeroWidthSpace;</a></h2>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>apt-get install p7zip p7zip-full</span></span>
<span class="line"><span></span></span>
<span class="line"><span>7z a package.7z package_folder</span></span>
<span class="line"><span>7z x package.7z -o package_folder</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br></div></div><p>某次在服务器上使用vscode更新代码 .git存在的时候使用ssh工具无法更新文件内容，打包不生效，重新连接之后内容变回原来的。</p>
<p><a href="https://www.bilibili.com/video/BV1Vu4y1D7Cd/" target="_blank" rel="noreferrer">线程池在 redis、skynet、workflow 等开源框架中的应用_哔哩哔哩_bilibili</a></p>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Twitter爬虫]]></title>
            <link>http://ooowl.fun/blogs/Python/%E7%88%AC%E8%99%AB/Twitter%E7%88%AC%E8%99%AB.html</link>
            <guid isPermaLink="false">http://ooowl.fun/blogs/Python/%E7%88%AC%E8%99%AB/Twitter%E7%88%AC%E8%99%AB.html</guid>
            <pubDate>Wed, 06 Jul 2022 15:18:34 GMT</pubDate>
            <content:encoded><![CDATA[<h1 id="twitter爬虫" tabindex="-1">Twitter爬虫 <a class="header-anchor" href="#twitter爬虫" aria-label="Permalink to &quot;Twitter爬虫&quot;">&ZeroWidthSpace;</a></h1><p class="article-meta">创建于 2022年7月6日 23:18:34 · 约5,286字</p>
<p>推特反爬机制稍微严一些，但是也不是很难突破。
这次爬虫主要是练多进程的使用</p>
<h2 id="分析请求" tabindex="-1">分析请求 <a class="header-anchor" href="#分析请求" aria-label="Permalink to &quot;分析请求&quot;">&ZeroWidthSpace;</a></h2>
<p>首先找请求，大小太离谱的都不要，
<img src="./static/Twitter爬虫_images_1.png" alt=""></p>
<p>因为网页是滑动的，座椅每次下滑看看他加载哪些，找这些里面的数据。<br>
一开始锁定的是all.json和guid.json后来发现guid.json返回的是边栏的推荐，all返回的是一些信息，这些信息也小小的误导了我<br>
后来找到是这个<br>
<img src="./static/Twitter爬虫_images_2.png" alt="1200"><br/>
<img src="./static/Twitter爬虫_images_3.png" alt="900"></p>
<p>发现每次查询变化的都是这个<strong>cursor</strong>，因为之前all里面有很多信息，我以为这个cursro是计算出来的，所以就在js里面逆向找片段，非常难找，最后找到头发现，是这次的json里面带着下次的标</p>
<p><img src="./static/Twitter爬虫_images_4.png" alt="600"></p>
<p>返回的json里面基本上包含了所有的内容。</p>
<h2 id="重发请求" tabindex="-1">重发请求 <a class="header-anchor" href="#重发请求" aria-label="Permalink to &quot;重发请求&quot;">&ZeroWidthSpace;</a></h2>
<p>直接在浏览器里面重发返回403，以为是服务器有反爬，然后把这个请求复制curl放到postman里面去，重发得到了数据<br>
猜测是有些请求头没带上，推特自己的请求头里面有好几个自定义的参数，估计是不带上就发不了<br>
<img src="./static/Twitter爬虫_images_5.png" alt="900"></p>
<p>之后在python里请求就可以了，参数很多配起来麻烦<br>
推文实际上在里面就有了，但是为了详细一点，顺手把评论第一页也爬一下<br>
接口是TweetsDetail</p>
<details class="details custom-block"><summary>Click to see more</summary>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> requests</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">cookies </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    ...</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">headers </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    'User-Agent'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:101.0) Gecko/20100101 Firefox/101.0'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    'Accept'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'*/*'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    'Accept-Language'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    # 'Accept-Encoding': 'gzip, deflate, br',</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    'content-type'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'application/json'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    'x-twitter-auth-type'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'OAuth2Session'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    'x-twitter-client-language'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'zh-cn'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    'x-twitter-active-user'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'yes'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    'x-csrf-token'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'1b73c3ff3f8905027c09c8....1c1c3d6a65c07e4b67f2f67c715a0728ccd2bb445956c'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    'Sec-Fetch-Dest'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'empty'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    'Sec-Fetch-Mode'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'cors'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    'Sec-Fetch-Site'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'same-origin'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    'authorization'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'Bearer AAAAAAAAsdasdk8LF81IU...jCpTnA'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    'Referer'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'https://twitter.com/taylorswift13'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    'Connection'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'keep-alive'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">params </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    'variables'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'{"userId":"17919972","count":40,"cursor":"HBaAwLTRytqKnSIAAA==","includePromotedContent":true,"withQuickPromoteEligibilityTweetFields":true,"withSuperFollowsUserFields":true,"withDownvotePerspective":false,"withReactionsMetadata":false,"withReactionsPerspective":false,"withSuperFollowsTweetFields":true,"withVoice":true,"withV2Timeline":true}'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    'features'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'{"dont_mention_me_view_api_enabled":true,"interactive_text_enabled":true,"responsive_web_uc_gql_enabled":false,"vibe_tweet_context_enabled":false,"responsive_web_edit_tweet_api_enabled":false,"standardized_nudges_misinfo":false,"responsive_web_enhance_cards_enabled":false}'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">response </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> requests.get(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'https://twitter.com/i/api/graphql/LeRJx69CS_6El2rAG0HQ9g/UserTweets'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">params</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">params, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">cookies</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">cookies, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">headers</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">headers)</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br></div></div><p>运行结果</p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>json很长很长，没人会看的</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div></details>
<h2 id="设计爬虫" tabindex="-1">设计爬虫 <a class="header-anchor" href="#设计爬虫" aria-label="Permalink to &quot;设计爬虫&quot;">&ZeroWidthSpace;</a></h2>
<h3 id="代码" tabindex="-1">代码 <a class="header-anchor" href="#代码" aria-label="Permalink to &quot;代码&quot;">&ZeroWidthSpace;</a></h3>
<p>老三样，请求，处理，持久化，程序很长的时候就需要写一个调度器<br>
代码和结构奉上<br>
这四个文件都是同一目录下的<br>
conf.py 配置</p>
<details class="details custom-block"><summary>Click to see more</summary>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># -*-coding:utf-8-*-  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># SettingCode here  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">COOKIES</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    ...</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">HEADERS</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    'User-Agent'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:101.0) Gecko/20100101 Firefox/101.0'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    'Accept'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'*/*'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    'Accept-Language'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    'content-type'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'application/json'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    # 推特自己整的header 不配置就403  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    'x-twitter-auth-type'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'OAuth2Session'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    'x-twitter-client-language'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'zh-cn'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    'x-twitter-active-user'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'yes'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    # csrf token 可能会变  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    'x-csrf-token'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'1b73c3ff3f8905027c09c83f2529sdasdasbc45ed03d998458ced11b1c1c3d6a65c07e4b67f2f67c715a0728ccd2bb445956c'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    'Sec-Fetch-Dest'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'empty'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    'Sec-Fetch-Mode'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'cors'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    'Sec-Fetch-Site'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'same-origin'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    # 这个字段不知道干嘛的，但是很明显不是自带的  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    'authorization'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'Bearer AAAAAAAAAAAAAAAsdsadsadZz4puTs%3D1Zv7ttfk8LF81IUq16cHjhLTvJu4FA33AGWWjCpTnA'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    'Referer'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">""</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    'Connection'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'keep-alive'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">PROXY</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    'http'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'http://127.0.0.1:7890'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    'https'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'http://127.0.0.1:7890'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 爬哪个用户  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">USERID</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 17919972</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">CRAWLED_PIN</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 0</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  # 制定是否被爬过  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">TIMELINE_SLEEP</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 15</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  # 每个timeline线程每次请求间隔时间  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">DETAIL_SLEEP</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 15</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  # 每个推文请求间隔</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br></div></div><p>运行结果</p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span></span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div></details>
<p>scheduler.py 主程序，调度</p>
<details class="details custom-block"><summary>Click to see more</summary>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># -*-coding:utf-8-*-  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># SettingCode here  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">__author__ </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "a_little_rubbish"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">__date__ </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "2022/7/5 15:06"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># import your model here  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> time  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> contextlib </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> contextmanager  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> queue </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Empty  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> multiprocessing  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> multiprocessing </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Manager  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> timeline_spider  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> detail_spider  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> persistence  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> conf </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> *</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> is_done</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(status_table, p_type):  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    """  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    检查某一类线程是否全都结束了  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    :param status_table: 状态表  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    :param p_type: 线程类型  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    :return:  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    """</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    done </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> []  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"ProcessStatus:"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, status_table)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> k, v </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> status_table[p_type].items():  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 遍历状态表  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> v </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">==</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 添加状态  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            done.append(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">True</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        else</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            done.append(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">False</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> all</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(done)  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 全完成就返回Tuee  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">@contextmanager</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> process_info_logger</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(status_table, p_type, p_name):  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    """  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    进程函数状态管理  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    :param status_table: 状态表  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    :param p_type: 哪类进程  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    :param p_name: 进程名，初始化用  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    :return:  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    """</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    temp </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> status_table[p_type]  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 进程嵌套字典需要中间转一下赋值  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    temp[p_name] </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    status_table[p_type] </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> temp  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%s</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> starting..."</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> %</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> p_name)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    yield</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    temp </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> status_table[p_type]  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 进程结束  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    temp[p_name] </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    status_table[p_type] </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> temp  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%s</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> has done"</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> %</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> p_name)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> timeline_crawler</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(status_table, detail_Q):  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    """  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    爬时间线的进程函数  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    只能起一个，多用户才能多个，因为不能切片只能下滑  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    """</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    name </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> multiprocessing.current_process().name  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    with</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> process_info_logger(status_table, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"timeline"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, name):  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        cursor </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> ""</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  # 第一次为空  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        while</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> True</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            try</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">                result </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> timeline_spider.crawl(cursor)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            except</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> Exception</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> as</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> e: </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 出现错误就返回  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">                print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(e)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">                break</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> result </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">==</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 这个人的已经爬完了  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">                break</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> result[</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"detail_list"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">                detail_Q.put(i)  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 结果加进去  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            cursor </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> result[</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"cursor"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 获得下一次的标  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            time.sleep(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">TIMELINE_SLEEP</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 控制频率  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> detail_crawler</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(status_table, detail_Q, ready_data_Q):  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    """  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    爬推文细节的进程函数,放到ready_data_Q  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    """</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    name </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> multiprocessing.current_process().name  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    with</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> process_info_logger(status_table, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"detail"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, name):  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        while</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> True</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            try</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">                tw_id </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> detail_Q.get(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">timeout</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            except</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Empty </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">as</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> e:  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">                if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> is_done(status_table, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"timeline"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">):  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">                    break</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">                continue</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            except</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> Exception</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> as</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> e:  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">                print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(e)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">                break</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            ready_data </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> detail_spider.crawl(tw_id)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            ready_data_Q.put(ready_data)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            time.sleep(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">DETAIL_SLEEP</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 控制频率  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> persist</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(status_table, ready_data_Q):  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    """  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    从ready_data_Q拿数据持久化，存数据库  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    """</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    name </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> multiprocessing.current_process().name  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    with</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> process_info_logger(status_table, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"persist"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, name):  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        while</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> True</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            try</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">                data </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> ready_data_Q.get(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">timeout</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            except</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Empty </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">as</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> e:  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">                if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> is_done(status_table, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"detail"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">):  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">                    break</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">                continue</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            persistence.persist_sql(data)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> main</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">():  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    """  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    主函数  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    """</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    pool </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> []  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> range</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">):  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 爬时间线的线程  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        p </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> multiprocessing.Process(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">target</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">timeline_crawler,  </span></span>
<span class="line"><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">                                    args</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(status_table, detail_Q),  </span></span>
<span class="line"><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">                                    name</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'timelineCrawlr</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%d</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> %</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> i)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        pool.append(p)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> range</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">):  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 爬推文的线程  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        p </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> multiprocessing.Process(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">target</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">detail_crawler,  </span></span>
<span class="line"><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">                                    args</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(status_table, detail_Q, ready_data_Q),  </span></span>
<span class="line"><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">                                    name</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'detailCrawler</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%d</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> %</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> i)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        pool.append(p)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> range</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">):  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 持久化线程  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        p </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> multiprocessing.Process(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">target</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">persist,  </span></span>
<span class="line"><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">                                    args</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(status_table, ready_data_Q),  </span></span>
<span class="line"><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">                                    name</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'persister</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%d</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> %</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> i)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        pool.append(p)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> pool:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        i.start()  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> pool:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        i.join()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">if</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __name__</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> ==</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> '__main__'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    status_table </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Manager().dict({</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"timeline"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: {}, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"detail"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: {}, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"persist"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: {}})  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 进程状态表,1是运行，0是运行结束  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    detail_Q </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Manager().Queue(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">maxsize</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">200</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 每个tweet的id队列  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    ready_data_Q </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Manager().Queue(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">maxsize</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">200</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 就绪数据队列\  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    persistence.init_table()  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 初始化数据库  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    main()</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br><span class="line-number">50</span><br><span class="line-number">51</span><br><span class="line-number">52</span><br><span class="line-number">53</span><br><span class="line-number">54</span><br><span class="line-number">55</span><br><span class="line-number">56</span><br><span class="line-number">57</span><br><span class="line-number">58</span><br><span class="line-number">59</span><br><span class="line-number">60</span><br><span class="line-number">61</span><br><span class="line-number">62</span><br><span class="line-number">63</span><br><span class="line-number">64</span><br><span class="line-number">65</span><br><span class="line-number">66</span><br><span class="line-number">67</span><br><span class="line-number">68</span><br><span class="line-number">69</span><br><span class="line-number">70</span><br><span class="line-number">71</span><br><span class="line-number">72</span><br><span class="line-number">73</span><br><span class="line-number">74</span><br><span class="line-number">75</span><br><span class="line-number">76</span><br><span class="line-number">77</span><br><span class="line-number">78</span><br><span class="line-number">79</span><br><span class="line-number">80</span><br><span class="line-number">81</span><br><span class="line-number">82</span><br><span class="line-number">83</span><br><span class="line-number">84</span><br><span class="line-number">85</span><br><span class="line-number">86</span><br><span class="line-number">87</span><br><span class="line-number">88</span><br><span class="line-number">89</span><br><span class="line-number">90</span><br><span class="line-number">91</span><br><span class="line-number">92</span><br><span class="line-number">93</span><br><span class="line-number">94</span><br><span class="line-number">95</span><br><span class="line-number">96</span><br><span class="line-number">97</span><br><span class="line-number">98</span><br><span class="line-number">99</span><br><span class="line-number">100</span><br><span class="line-number">101</span><br><span class="line-number">102</span><br><span class="line-number">103</span><br><span class="line-number">104</span><br><span class="line-number">105</span><br><span class="line-number">106</span><br><span class="line-number">107</span><br><span class="line-number">108</span><br><span class="line-number">109</span><br><span class="line-number">110</span><br><span class="line-number">111</span><br><span class="line-number">112</span><br><span class="line-number">113</span><br><span class="line-number">114</span><br><span class="line-number">115</span><br><span class="line-number">116</span><br><span class="line-number">117</span><br><span class="line-number">118</span><br><span class="line-number">119</span><br><span class="line-number">120</span><br><span class="line-number">121</span><br><span class="line-number">122</span><br><span class="line-number">123</span><br><span class="line-number">124</span><br><span class="line-number">125</span><br><span class="line-number">126</span><br><span class="line-number">127</span><br><span class="line-number">128</span><br><span class="line-number">129</span><br><span class="line-number">130</span><br><span class="line-number">131</span><br><span class="line-number">132</span><br><span class="line-number">133</span><br><span class="line-number">134</span><br><span class="line-number">135</span><br><span class="line-number">136</span><br><span class="line-number">137</span><br><span class="line-number">138</span><br><span class="line-number">139</span><br><span class="line-number">140</span><br><span class="line-number">141</span><br><span class="line-number">142</span><br><span class="line-number">143</span><br><span class="line-number">144</span><br><span class="line-number">145</span><br><span class="line-number">146</span><br><span class="line-number">147</span><br><span class="line-number">148</span><br><span class="line-number">149</span><br><span class="line-number">150</span><br></div></div><p>运行结果</p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>2022-07-06 15:11:52,653 INFO sqlalchemy.engine.Engine SELECT DATABASE()</span></span>
<span class="line"><span>2022-07-06 15:11:52,653 INFO sqlalchemy.engine.Engine [raw sql] {}</span></span>
<span class="line"><span>2022-07-06 15:11:52,666 INFO sqlalchemy.engine.Engine SELECT @@sql_mode</span></span>
<span class="line"><span>2022-07-06 15:11:52,667 INFO sqlalchemy.engine.Engine [raw sql] {}</span></span>
<span class="line"><span>2022-07-06 15:11:52,667 INFO sqlalchemy.engine.Engine SELECT @@lower_case_table_names</span></span>
<span class="line"><span>2022-07-06 15:11:52,667 INFO sqlalchemy.engine.Engine [raw sql] {}</span></span>
<span class="line"><span>2022-07-06 15:11:52,680 INFO sqlalchemy.engine.Engine BEGIN (implicit)</span></span>
<span class="line"><span>2022-07-06 15:11:52,681 INFO sqlalchemy.engine.Engine SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = %(table_schema)s AND table_name = %(table_name)s</span></span>
<span class="line"><span>2022-07-06 15:11:52,681 INFO sqlalchemy.engine.Engine [generated in 0.00012s] {'table_schema': 'twitter', 'table_name': 'posts'}</span></span>
<span class="line"><span>2022-07-06 15:11:52,768 INFO sqlalchemy.engine.Engine </span></span>
<span class="line"><span>DROP TABLE posts</span></span>
<span class="line"><span>2022-07-06 15:11:52,768 INFO sqlalchemy.engine.Engine [no key 0.00022s] {}</span></span>
<span class="line"><span>2022-07-06 15:11:52,958 INFO sqlalchemy.engine.Engine COMMIT</span></span>
<span class="line"><span>2022-07-06 15:11:52,964 INFO sqlalchemy.engine.Engine BEGIN (implicit)</span></span>
<span class="line"><span>2022-07-06 15:11:52,964 INFO sqlalchemy.engine.Engine SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = %(table_schema)s AND table_name = %(table_name)s</span></span>
<span class="line"><span>2022-07-06 15:11:52,964 INFO sqlalchemy.engine.Engine [cached since 0.2835s ago] {'table_schema': 'twitter', 'table_name': 'posts'}</span></span>
<span class="line"><span>2022-07-06 15:11:52,975 INFO sqlalchemy.engine.Engine </span></span>
<span class="line"><span>CREATE TABLE posts (</span></span>
<span class="line"><span>	id INTEGER NOT NULL AUTO_INCREMENT, </span></span>
<span class="line"><span>	main_posts TEXT NOT NULL, </span></span>
<span class="line"><span>	reply TEXT, </span></span>
<span class="line"><span>	PRIMARY KEY (id)</span></span>
<span class="line"><span>)</span></span>
<span class="line"><span></span></span>
<span class="line"><span></span></span>
<span class="line"><span>2022-07-06 15:11:52,975 INFO sqlalchemy.engine.Engine [no key 0.00009s] {}</span></span>
<span class="line"><span>2022-07-06 15:11:53,110 INFO sqlalchemy.engine.Engine COMMIT</span></span>
<span class="line"><span>detailCrawler2 starting...</span></span>
<span class="line"><span>detailCrawler1 starting...</span></span>
<span class="line"><span>persister2 starting...</span></span>
<span class="line"><span>persister1 starting...</span></span>
<span class="line"><span>timelineCrawlr1 starting...</span></span>
<span class="line"><span>status 200 crawing timelineSlice  </span></span>
<span class="line"><span>extracting timeline data  </span></span>
<span class="line"><span>ProcessStatus: ProcessStatus: {'timeline': {'timelineCrawlr1': 1}, 'detail': {'detailCrawler2': 1, 'detailCrawler1': 1}, 'persist': {'persister2': 1, 'persister1': 1}}</span></span>
<span class="line"><span>{'timeline': {'timelineCrawlr1': 1}, 'detail': {'detailCrawler2': 1, 'detailCrawler1': 1}, 'persist': {'persister2': 1, 'persister1': 1}}</span></span>
<span class="line"><span>status 200 crawing tweets 1459023801480474632</span></span>
<span class="line"><span>status 200 crawing tweets 1540382753677627393</span></span>
<span class="line"><span>extracting tweets data 1540382753677627393 </span></span>
<span class="line"><span>extracting tweets data 1459023801480474632 </span></span>
<span class="line"><span>inserting data {'posts': ['I’m absolutely terrified that this is where we are - that after so many decades of people fighting for women’s rights to their own bodies, today’s decision has stripped us of that.'], 'reply': ['@taylorswift13 A baby’s body is *not* your body. Let them live. Abortion is violence.', '@taylorswift13 why on earth does a gun have more protection in this country than i do??', '@taylorswift13 You may have lost a fan unless I’m misunderstanding you. Abortion is murder. Contraceptives should be used if you’re having sex and can’t handle/don’t want to have a child. In certain cases (rape, woman’s health etc…) an abortion should be an option…', '@taylorswift13 I don’t understand why everyone is upset… if you don’t want a baby just don’t get pregnant… right? And if you do, why just remove the existence of the fetus inside you, that you were once yourself, erasing their entire future and existence because you don’t want them? \U0001fae5', '@taylorswift13 Kindly explain why women who fight so hard for their own bodies find it so easy to destroy someone else’s (a baby’s, no less). Take your time, I’ll wait. (By the way, hundreds of babies were scheduled to die today, but now won’t. Does their reprieve make you happy or sad?)', '@taylorswift13 So disappointed in myself that I used to look up to you as a teenager! Taylor, your mother chose life, and chose to have you. If it wasn’t for her choosing life, you wouldn’t even have rights.', '@taylorswift13 I’m soooo disappointed to hear you say this … nobody should be able to choose to end someone else’s life.  No matter how old the person is, (fetus, 5 year’s old or 40 years old) it’s a living being. The women’s choice was to have sex, so they need to deal with the consequences.', '@taylorswift13 @BlueberryGabe I’m terrified of a centralized government dictating what all of us have to believe. I am less terrified now that the states have the individual power to decide what for their local cultures. If you’re really that worried take a morning-after pill. Does the same thing.', '@taylorswift13 @Kenshiro73 That’s just the start. They won’t stop there.  \n\nhttps://t.co/h8xzUX5FPx']}</span></span>
<span class="line"><span>inserting data {'posts': ['It never would have been possible to go back &#x26;amp; remake my previous work, uncovering lost art &#x26;amp; forgotten gems along the way if you hadn’t emboldened me. Red is about to be mine again, but it has always been ours. Now we begin again. Red (my version) is out\n\nhttps://t.co/ZUAWDuv4jL https://t.co/Ji26KdOlWQ', 'https://pbs.twimg.com/media/FD9-aXKWYAATZTm.jpg', 'https://pbs.twimg.com/media/FD9-aXIWYBI4DP6.jpg'], 'reply': ['@taylorswift13 i just wanna say that the very first night is one of the best vauIt track ever 😎 thanks for this b0p song😿❤️ \n https://t.co/Z86fmElt6A', '@taylorswift13 yassss speak now tv announcement!!\nhttps://t.co/S6U0tbJBCi', '@taylorswift13 ei tweeta aí https://t.co/SasFRYPgau', "@taylorswift13 OMG it's here 🥺❤️", "@taylorswift13 Best singer in the world is miss Taylor swift lady's and gentlemen love voodoo XX https://t.co/1iI3DjRoxd", "@taylorswift13 Tomorrow (Dhul-Hijjah 1st / July 1st) is Muslims valentine day due to the anniversary of a shining marriage of  a sacred couple Ali &#x26;amp; Fatemah. Their brilliant love is still an ideal one for marriage of many muslims and that's the reason they mostly have a great family.\n#pure_love", '@taylorswift13 Why do you have tour dates in venues that are 21 and older? You’re cutting off a lot of fans.', '@taylorswift13 A red rose grew up out of ice frozen ground, with no one around to tweet it. https://t.co/nB7KX5SzJH', '@taylorswift13 World s best singer ever. Miss Taylor swift best album ever sold red album  bye miss Taylor swift love voodoo XX my queen my love for ever XX https://t.co/slWOh6Q9xr']}</span></span>
<span class="line"><span>ProcessStatus: {'timeline': {'timelineCrawlr1': 1}, 'detail': {'detailCrawler2': 1, 'detailCrawler1': 1}, 'persist': {'persister2': 1, 'persister1': 1}}</span></span>
<span class="line"><span>ProcessStatus: {'timeline': {'timelineCrawlr1': 1}, 'detail': {'detailCrawler2': 1, 'detailCrawler1': 1}, 'persist': {'persister2': 1, 'persister1': 1}}</span></span>
<span class="line"><span>ProcessStatus: {'timeline': {'timelineCrawlr1': 1}, 'detail': {'detailCrawler2': 1, 'detailCrawler1': 1}, 'persist': {'persister2': 1, 'persister1': 1}}</span></span>
<span class="line"><span>ProcessStatus: {'timeline': {'timelineCrawlr1': 1}, 'detail': {'detailCrawler2': 1, 'detailCrawler1': 1}, 'persist': {'persister2': 1, 'persister1': 1}}</span></span>
<span class="line"><span>ProcessStatus: ProcessStatus: {'timeline': {'timelineCrawlr1': 1}, 'detail': {'detailCrawler2': 1, 'detailCrawler1': 1}, 'persist': {'persister2': 1, 'persister1': 1}}</span></span>
<span class="line"><span>{'timeline': {'timelineCrawlr1': 1}, 'detail': {'detailCrawler2': 1, 'detailCrawler1': 1}, 'persist': {'persister2': 1, 'persister1': 1}}</span></span>
<span class="line"><span>ProcessStatus: ProcessStatus: {'timeline': {'timelineCrawlr1': 1}, 'detail': {'detailCrawler2': 1, 'detailCrawler1': 1}, 'persist': {'persister2': 1, 'persister1': 1}}</span></span>
<span class="line"><span>{'timeline': {'timelineCrawlr1': 1}, 'detail': {'detailCrawler2': 1, 'detailCrawler1': 1}, 'persist': {'persister2': 1, 'persister1': 1}}</span></span>
<span class="line"><span>ProcessStatus: {'timeline': {'timelineCrawlr1': 1}, 'detail': {'detailCrawler2': 1, 'detailCrawler1': 1}, 'persist': {'persister2': 1, 'persister1': 1}}</span></span>
<span class="line"><span>ProcessStatus: {'timeline': {'timelineCrawlr1': 1}, 'detail': {'detailCrawler2': 1, 'detailCrawler1': 1}, 'persist': {'persister2': 1, 'persister1': 1}}</span></span>
<span class="line"><span>status 200 crawing timelineSlice "cursor":"HBaOgKPFjJfCwCcAAA==", </span></span>
<span class="line"><span>extracting timeline data HBaOgKPFjJfCwCcAAA== </span></span>
<span class="line"><span>status 200 crawing tweets 1540183720845533185</span></span>
<span class="line"><span>extracting tweets data 1540183720845533185 </span></span>
<span class="line"><span>inserting data {'posts': ['About a year &#x26;amp; half ago I wrote a song about the story of a girl who always lived on the outside, looking in. Figuratively &#x26;amp; literally. The juxtaposition of her loneliness &#x26;amp; independence. Her curiosity &#x26;amp; fear all tangled up. Her persisting gentleness &#x26;amp; the world’s betrayal of it. https://t.co/2o1z8Hrht6', 'https://pbs.twimg.com/ext_tw_video_thumb/1540183648468623360/pu/img/xHEqJJY-HYNZqQTZ.jpg'], 'reply': ['I wrote this one alone in the middle of the night and then @AaronDessner and I meticulously worked on a sound that we felt would be authentic to the moment when this story takes place. I made a wish that one day you would hear it. ‘Carolina’ is out now 🥺 \nhttps://t.co/2xqE0fEr10', '@taylorswift13 Thank for the song Taylor! Now please leave folkmore forest so that we can get TS10 yeah?', '@taylorswift13 Wen a song about leprechauns? @Leprechaun_Wtf #Leprechauntownwtf #LeprechaunTakeOver https://t.co/7aus6zadZd', '@taylorswift13 @jeonality @worthwhilefigh1 this is what u get for being optimist ;)', '@taylorswift13 @Leprechaun_Wtf got talent ms swift check out our theme song by the one and only @LiggyNFT', '@taylorswift13 my favorite tagline to see nowadays 🤍 https://t.co/PGjxahqHx6', '@taylorswift13 Get in Swifties, we’re going to the swamp! #Carolina https://t.co/vOVYgXqNGo', '@taylorswift13 Taylor only used instruments that were available before 1953 and Taylor recorded the song in one take like they did back then… no one is as extra as Ms. Swift https://t.co/4TPF4YWNUV']}</span></span>
<span class="line"><span>status 200 crawing tweets 1529295926057123841</span></span>
<span class="line"><span>extracting tweets data 1529295926057123841 </span></span>
<span class="line"><span>inserting data {'posts': ['Filled with rage and grief, and so broken by the murders in Uvalde. By Buffalo, Laguna Woods and so many others. By the ways in which we, as a nation, have become conditioned to unfathomable and unbearable heartbreak. Steve’s words ring so true and cut so deep.'], 'reply': ['@taylorswift13 de la nada no', "@taylorswift13 We should never get used on violence, no matter how many times we turn on the news just to see it all again. It is not just a number, is someone's daughter as you said in epiphany. As a health worker that deals with mothers in grief daily it breas my heart for each family.", "@taylorswift13 As a Canadian, I hate to say it, but nothing will change. Absolutely nothing.  Your government officials offer thoughts and prayers every single time, as if that's going to fix things.  I guarantee someone has said there should have been an armed guard at the school.  🤬🤬🤬", '@taylorswift13 If there are 50 senators refusing to vote, how are they still in office (if, essentially, they are refusing to do their job?) \n\nSomeone please (nicely) educate me', '@taylorswift13 What this shows is not the relationship between mental illness and gun violence, but between virtually unregulated access to assault weapons and gun violence. This has to change because it has to. Right now. https://t.co/e1cWDwkpOC', '@taylorswift13 I can’t imagine what it’s like to be a parent in the US. Knowing that every day you send your kids to school, it might be the last time. Every time you kiss them in the morning, it might be the last kiss. I don’t live in the US, I can’t affect its politics. But US lawmakers can!', '@taylorswift13 Thank you for speaking out on this, it’s feeling like nothing will ever change &#x26;amp; this will just keep happening regularly because that’s the reality we live in 💔', '@taylorswift13 We are all so tired, sad &#x26;amp; angry. I was a teen when Columbine happened. 23 yrs, we’ve had 23 yrs to do SOMETHING. And yet we’ve done NOTHING. Elected officials have the ability to do SOMETHING. Remember that. We’ve had ENOUGH. Our country stands alone in #s of mass shootings. 1/2', '@taylorswift13 swifties pls don’t make this ab u', '@taylorswift13 Taylor. Or Taylor social media person. Girl where are you on Roe v Wade??? I thought maybe you were just not getting out there on any current events or legislation, but this tweet? So you’re out here. Say something about abortion. Or tell us you’re pro life.']}</span></span>
<span class="line"><span></span></span>
<span class="line"><span>...</span></span>
<span class="line"><span>...</span></span>
<span class="line"><span>...</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br><span class="line-number">50</span><br><span class="line-number">51</span><br><span class="line-number">52</span><br><span class="line-number">53</span><br><span class="line-number">54</span><br><span class="line-number">55</span><br><span class="line-number">56</span><br><span class="line-number">57</span><br><span class="line-number">58</span><br><span class="line-number">59</span><br><span class="line-number">60</span><br><span class="line-number">61</span><br><span class="line-number">62</span><br><span class="line-number">63</span><br><span class="line-number">64</span><br></div></div></details>
<p>timeline_spider.py 爬时间线</p>
<details class="details custom-block"><summary>Click to see more</summary>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># -*-coding:utf-8-*-  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># SettingCode here  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">__author__ </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "a_little_rubbish"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">__date__ </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "2022/7/5 09:11"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># import your model here  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> time  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> pprint </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> pprint  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> requests  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> requests.exceptions </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> ProxyError  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> conf </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> *</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># your class&#x26;function here  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># userId 会根据不同用户变,%s处是cursor  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">PARAMS_</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    'variables'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'{"userId":"</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%d</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">","count":40,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%s</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"includePromotedContent":true,"withQuickPromoteEligibilityTweetFields":true,"withSuperFollowsUserFields":true,"withDownvotePerspective":false,"withReactionsMetadata":false,"withReactionsPerspective":false,"withSuperFollowsTweetFields":true,"withVoice":true,"withV2Timeline":true}'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    'features'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'{"dont_mention_me_view_api_enabled":true,"interactive_text_enabled":true,"responsive_web_uc_gql_enabled":false,"vibe_tweet_context_enabled":false,"responsive_web_edit_tweet_api_enabled":false,"standardized_nudges_misinfo":false,"responsive_web_enhance_cards_enabled":false}'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">TIMELINE_URL</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "https://twitter.com/i/api/graphql/LeRJx69CS_6El2rAG0HQ9g/UserTweets"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> crawl</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(cursor, userId</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">USERID</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">):  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    """  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    外部调用这个函数  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    解析一次timeline的cursor  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    :return: {detailList:int list,cursor:str }  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    """</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    raw_json </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> download(cursor, userId)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> raw_json </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">==</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> -</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        return</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "ERROR"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    result </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> extract(raw_json, cursor)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> result  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> extract</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(data, cursor):  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    """  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    处理json  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    :param cursor: 为了打印日志好看  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    :param data raw_json    :return: {detail_list:int list,cursor:str }  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    """</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    global</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> CRAWLED_PIN</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"extracting timeline data </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%s</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> %</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> cursor)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    # 取数据，没什么好说的，结构长什么样就怎么取  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    detail_list </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> []  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    cursor_next </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> ""</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    instructions </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> data[</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"data"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">][</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"user"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">][</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"result"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">][</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"timeline_v2"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">][</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"timeline"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">][</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"instructions"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    entries </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> []  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> instructions:  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> i[</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"type"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">] </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">==</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "TimelineAddEntries"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 时间线id  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            entries </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> i[</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"entries"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            if</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> len</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(entries) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">==</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">                return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 0</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  # 代表线程已经爬完，告诉外面结束  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> i[</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"type"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">] </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">==</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "TimelinePinEntry"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 拿置顶推的id  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            if</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> CRAWLED_PIN</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> ==</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 每次请求都会带置顶，爬一次就行  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">                entry_id </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> i[</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"entry"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">][</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"entryId"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">].split(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"-"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x3C;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">br</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">/></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">                detail_list.append(entry_id)  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">                CRAWLED_PIN</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> entry </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> entries:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        entry_id </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> entry[</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"entryId"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> entry_id.startswith((</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"promotedTweet"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"whoToFollow"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"cursor-top"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)):  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 推广和建议关注都不要  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            continue</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        elif</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> entry_id.startswith((</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"tweet"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"homeConversation"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)):  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            entry_id </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> entry_id.split(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"-"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x3C;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">br</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">/></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            detail_list.append(entry_id)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        elif</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> entry_id.startswith(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"cursor-bottom"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">):  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            cursor_next </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> entry[</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"content"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">][</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"value"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"detail_list"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: detail_list, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"cursor"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: cursor_next}  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> download</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(cursor, userId):  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    """  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    请求并判断连接状态处理  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    :param cursor userId    :return: raw_json  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    """</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> cursor </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">!=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> ""</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        cursor </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> '"cursor":"</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%s</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">",'</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> %</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> cursor  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 控制下拉加载什么的参数，首次请求没有，之后每次下拉加载都会在json里存放下一次的，每次都会刷新  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    PARAMS</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> PARAMS_</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.copy()  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    PARAMS</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"variables"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">] </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> PARAMS</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"variables"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">] </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">%</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (userId, cursor)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    while</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> True</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        try</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            response </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> requests.get(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">TIMELINE_URL</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">proxies</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">PROXY</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">params</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">PARAMS</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">cookies</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">COOKIES</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">headers</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">HEADERS</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        except</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> ProxyError </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">or</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> ConnectionResetError</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">            print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"timeline:ConnectionResetError"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            time.sleep(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">20</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            continue</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        break</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> response.status_code </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">!=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 200</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 请求错误就向上传递  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"error </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%d</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> when crawing timelineSlice </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%s</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> %</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (response.status_code, cursor))  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        return</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> -</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"status </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%d</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> crawing timelineSlice </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%s</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> %</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (response.status_code, cursor))  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> dict</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(response.json())  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">if</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __name__</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> ==</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "__main__"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    crawl(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"HBaOgKPFjJfCwCcAAA=="</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br><span class="line-number">50</span><br><span class="line-number">51</span><br><span class="line-number">52</span><br><span class="line-number">53</span><br><span class="line-number">54</span><br><span class="line-number">55</span><br><span class="line-number">56</span><br><span class="line-number">57</span><br><span class="line-number">58</span><br><span class="line-number">59</span><br><span class="line-number">60</span><br><span class="line-number">61</span><br><span class="line-number">62</span><br><span class="line-number">63</span><br><span class="line-number">64</span><br><span class="line-number">65</span><br><span class="line-number">66</span><br><span class="line-number">67</span><br><span class="line-number">68</span><br><span class="line-number">69</span><br><span class="line-number">70</span><br><span class="line-number">71</span><br><span class="line-number">72</span><br><span class="line-number">73</span><br><span class="line-number">74</span><br><span class="line-number">75</span><br><span class="line-number">76</span><br><span class="line-number">77</span><br><span class="line-number">78</span><br><span class="line-number">79</span><br><span class="line-number">80</span><br><span class="line-number">81</span><br><span class="line-number">82</span><br><span class="line-number">83</span><br><span class="line-number">84</span><br><span class="line-number">85</span><br><span class="line-number">86</span><br><span class="line-number">87</span><br><span class="line-number">88</span><br><span class="line-number">89</span><br><span class="line-number">90</span><br><span class="line-number">91</span><br><span class="line-number">92</span><br><span class="line-number">93</span><br><span class="line-number">94</span><br><span class="line-number">95</span><br><span class="line-number">96</span><br><span class="line-number">97</span><br><span class="line-number">98</span><br><span class="line-number">99</span><br><span class="line-number">100</span><br><span class="line-number">101</span><br><span class="line-number">102</span><br></div></div><p>运行结果</p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>status 200 crawing timelineSlice "cursor":"HBaOgKPFjJfCwCcAAA==", </span></span>
<span class="line"><span>extracting timeline data HBaOgKPFjJfCwCcAAA==</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br></div></div></details>
<p>detail_spider.py 爬细节</p>
<details class="details custom-block"><summary>Click to see more</summary>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># -*-coding:utf-8-*-  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># SettingCode here  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">__author__ </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "a_little_rubbish"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">__date__ </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "2022/7/5 15:06"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> time  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> requests  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> requests.exceptions </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> ProxyError  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> conf </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> *</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">PARAMS_</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 不能直接修改  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    'variables'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'{"focalTweetId":"</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%d</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">","with_rux_injections":false,"includePromotedContent":true,"withCommunity":true,'</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  # 这个focalTweetId是推文的详情  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">                 '"withQuickPromoteEligibilityTweetFields":true,"withBirdwatchNotes":true,'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">                 '"withSuperFollowsUserFields":true,"withDownvotePerspective":false,"withReactionsMetadata":false,'</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">                 '"withReactionsPerspective":false,"withSuperFollowsTweetFields":true,"withVoice":true,'</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">                 '"withV2Timeline":true}'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    'features'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'{"dont_mention_me_view_api_enabled":true,"interactive_text_enabled":true,'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">                '"responsive_web_uc_gql_enabled":false,"vibe_tweet_context_enabled":false,'</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">                '"responsive_web_edit_tweet_api_enabled":false,"standardized_nudges_misinfo":false,'</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">                '"responsive_web_enhance_cards_enabled":false}'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">DETAIL_URL</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 'https://twitter.com/i/api/graphql/0vaSJ4y9SDdSPPZ72dpuDA/TweetDetail'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> crawl</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(tw_id):  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    """  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    外部调用这个函数  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    :return:{posts:str,reply:str list}  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    """</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    tw_id </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> int</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(tw_id)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    raw_json </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> download(tw_id)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> raw_json </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">==</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> -</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        return</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "ERROR"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    result </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> extract(raw_json, tw_id)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> result  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> extract</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(data, tw_id):  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    """  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    解析返回的json  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    :param tw_id: 打印日志好看  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    :param data 接收原始json  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    :return {posts:str list,reply:str list}    """</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"extracting tweets data </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%s</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> %</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> tw_id)  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    # 取数据，没什么好说的，结构长什么样就怎么取,有问题就是json里面有没有值  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    posts </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> []  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    entries </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> []  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    try</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        instructions </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> data[</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"data"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">][</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"threaded_conversation_with_injections_v2"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">][</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"instructions"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    except</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> KeyError</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> as</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> e:  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(e)  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"ERROR:"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,tw_id,data)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'posts'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: [</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"key threaded_conversation_with_injections_v2 error"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">],</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'reply'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: []}  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> instructions:  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> i[</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"type"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">] </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">==</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "TimelineAddEntries"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            entries </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> i[</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"entries"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    post </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> entries[</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">][</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"content"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">][</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"itemContent"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">][</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"tweet_results"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">][</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"result"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">][</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"legacy"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">][</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"full_text"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    posts.append(post)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    media </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> entries[</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">][</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"content"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">][</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"itemContent"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">][</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"tweet_results"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">][</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"result"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">][</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"legacy"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">].get(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"extended_entities"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">""</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> media </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">!=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> ""</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> media[</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"media"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            posts.append(i[</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"media_url_https"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">])  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    reply </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> []  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> entry </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> entries[</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        _ </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> entry[</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"content"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">][</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"items"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">][</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">][</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"item"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">][</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"itemContent"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">][</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"tweet_results"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">][</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"result"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">].get(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'tombstone'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">False</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 处理封禁账号的消息  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> _:  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">            print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"消息来自已封禁账号"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            continue</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        _ </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> entry[</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"content"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">][</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"items"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">][</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">][</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"item"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">][</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"itemContent"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">][</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"tweet_results"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">][</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"result"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">][</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"legacy"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">][</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"full_text"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        reply.append(_)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"posts"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: posts, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"reply"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: reply}  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> download</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(tw_id):  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    """  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    :param tw_id: 该条推文的id  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    :return:  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    """</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    PARAMS</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> PARAMS_</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.copy()  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    PARAMS</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'variables'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">] </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> PARAMS</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'variables'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">] </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">%</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> tw_id  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    while</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> True</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        try</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            response </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> requests.get(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">DETAIL_URL</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">params</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">PARAMS</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">cookies</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">COOKIES</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">headers</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">HEADERS</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        except</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> ProxyError </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">or</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> ConnectionResetError</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">            print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"deatil:ConnectionResetError"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            time.sleep(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">20</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            continue</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        break</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> response.status_code </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">!=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 200</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 返回码错误就向上传递  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"error </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%d</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> when crawing tweets </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%d</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> %</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (response.status_code, tw_id))  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        return</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> -</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"status </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%d</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> crawing tweets </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%d</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> %</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (response.status_code, tw_id))  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> dict</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(response.json())  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">if</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __name__</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> ==</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "__main__"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(crawl(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">557649460810248194</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">))  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(crawl(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">899647503859032065</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">))</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br><span class="line-number">50</span><br><span class="line-number">51</span><br><span class="line-number">52</span><br><span class="line-number">53</span><br><span class="line-number">54</span><br><span class="line-number">55</span><br><span class="line-number">56</span><br><span class="line-number">57</span><br><span class="line-number">58</span><br><span class="line-number">59</span><br><span class="line-number">60</span><br><span class="line-number">61</span><br><span class="line-number">62</span><br><span class="line-number">63</span><br><span class="line-number">64</span><br><span class="line-number">65</span><br><span class="line-number">66</span><br><span class="line-number">67</span><br><span class="line-number">68</span><br><span class="line-number">69</span><br><span class="line-number">70</span><br><span class="line-number">71</span><br><span class="line-number">72</span><br><span class="line-number">73</span><br><span class="line-number">74</span><br><span class="line-number">75</span><br><span class="line-number">76</span><br><span class="line-number">77</span><br><span class="line-number">78</span><br><span class="line-number">79</span><br><span class="line-number">80</span><br><span class="line-number">81</span><br><span class="line-number">82</span><br><span class="line-number">83</span><br><span class="line-number">84</span><br><span class="line-number">85</span><br><span class="line-number">86</span><br><span class="line-number">87</span><br><span class="line-number">88</span><br><span class="line-number">89</span><br><span class="line-number">90</span><br><span class="line-number">91</span><br><span class="line-number">92</span><br><span class="line-number">93</span><br><span class="line-number">94</span><br><span class="line-number">95</span><br><span class="line-number">96</span><br><span class="line-number">97</span><br></div></div><p>运行结果</p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span></span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div></details>
<p>persistence.py持久化</p>
<details class="details custom-block"><summary>Click to see more</summary>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># -*-coding:utf-8-*-  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># SettingCode here  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">__author__ </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "a_little_rubbish"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">__date__ </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "2022/7/6 10:00"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> sqlalchemy </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Column, String, Integer, Text, create_engine  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> sqlalchemy.ext.declarative </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> declarative_base  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> sqlalchemy.orm </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> sessionmaker  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Base </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> declarative_base()  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 生成Model类的基类  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Posts</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Base</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">):  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    # 表的名字:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    __tablename__ </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 'posts'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    # 表的结构:  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    id</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Column(Integer, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">nullable</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">False</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">autoincrement</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">True</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">primary_key</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">True</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 资增int主键  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    main_posts </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Column(Text, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">nullable</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">False</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 主推文  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    reply </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Column(Text)  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 回复  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __repr__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self):  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        return</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 'Posts(id=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">{}</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">, posts=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">{}</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">, reply=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">{}</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">)'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.format(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.id, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.main_posts, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.reply)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __str__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self):  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">__repr__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> init_table</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">():  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    engine </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> create_engine(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'mysql+pymysql://root:1118@127.0.0.1:3306/twitter'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">echo</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">True</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    Base.metadata.drop_all(engine)  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 删除所有表  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    Base.metadata.create_all(engine)  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 创建所有表  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> persist_sql</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(data):  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    """  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    持久化到sql的函数  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    :param data: json数据，存sql  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    :return:  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    """</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    engine </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> create_engine(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'mysql+pymysql://root:1118@127.0.0.1:3306/twitter'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">echo</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">False</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    Session </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> sessionmaker(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">bind</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">engine)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    session </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Session()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    # 格式变一下  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    main_posts </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> ";"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.join(data[</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"posts"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">])  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    reply </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> ";"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.join(data[</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"reply"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">])  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"inserting data"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, data)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    # 插入  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    p </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Posts(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">main_posts</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">main_posts, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">reply</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">reply)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    session.add(p)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    try</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        session.commit()  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    except</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> Exception</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> as</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> e:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        session.rollback()  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        raise</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> e  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">if</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __name__</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> ==</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "__main__"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    # 测试数据  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    demodata </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'posts'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: [  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">        '@DamonAlbarn I was such a big fan of yours until I saw this. I write ALL of my own songs. Your hot take is completely false and SO damaging. You don’t have to like my songs but it’s really fucked up to try and discredit my writing. WOW.'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">],  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">        'reply'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: [</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'PS I wrote this tweet all by myself in case you were wondering 😑'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">                  '@taylorswift13 I totally agree with you. i had a conversation about songwriting and sadly it was reduced to clickbait. I apologise unreservedly and unconditionally. The last thing I would want to do is discredit your songwriting. I hope you understand. - Damon'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">                  '@taylorswift13 @Damonalbarn يابنت الحلال اطلعي خلاص وجع'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">                  '@taylorswift13 @Damonalbarn Must you use foul language? I understand your point and im a Christian and this just is upsetting to see ladies use such language. Im a great grandmother, grandmother and mother....I like your music just the language is upsetting.'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">                  '@taylorswift13 @Damonalbarn Just gonna leave this here. Look at all of these cowrites @Damonalbarn </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">\n\n</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">“Day doo de bop</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">\n</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">Day doo de bop” really required multiple writers to come up with that… https://t.co/aU8g9bD2rx'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">                  "@taylorswift13 @Damonalbarn what the fuck taylor you can't just say fucking it's rude"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">                  '@taylorswift13 @Damonalbarn OMG I JUST WOKE UP TO SEE TAYLOR SWIFT END A MAN YESSSSS https://t.co/3CAAXx1VGe'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">                  '@taylorswift13 @Damonalbarn https://t.co/Qb8BbHxFSY'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">                  '@taylorswift13 @Damonalbarn he’s just jealous he doesn’t have tons of awards like this shiny songwriter of the year 2020 award😌 https://t.co/JdwEN18dBT'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]}  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    init_table()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    persist_sql(demodata)</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br><span class="line-number">50</span><br><span class="line-number">51</span><br><span class="line-number">52</span><br><span class="line-number">53</span><br><span class="line-number">54</span><br><span class="line-number">55</span><br><span class="line-number">56</span><br><span class="line-number">57</span><br><span class="line-number">58</span><br><span class="line-number">59</span><br><span class="line-number">60</span><br><span class="line-number">61</span><br><span class="line-number">62</span><br><span class="line-number">63</span><br><span class="line-number">64</span><br><span class="line-number">65</span><br><span class="line-number">66</span><br><span class="line-number">67</span><br><span class="line-number">68</span><br><span class="line-number">69</span><br><span class="line-number">70</span><br><span class="line-number">71</span><br><span class="line-number">72</span><br><span class="line-number">73</span><br><span class="line-number">74</span><br></div></div><p>运行结果</p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>inserting data {'posts': ....</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div></details>
<div class="tip custom-block"><p class="custom-block-title">[💡Tip]</p>
<p>返回的json在处理的时候注意每次都会有置顶推，记得标记一下不要重复，还有判断边界条件什么时候停止进程<br>
持久化的时候注意多进程的坑，每个进程一个engine，申请session这类的操错不要放在True中<br>
多进程的变量只有第一层是共享的，多层嵌套的需要中间变量间接赋值才可以，代码里有</p>
</div>
<p>整体组织
<img src="./static/Twitter爬虫_images_6.jpeg" alt="">
<strong>数据截图</strong>：
<img src="./static/Twitter爬虫_images_7.png" alt="900"></p>
<h3 id="多进程" tabindex="-1">多进程 <a class="header-anchor" href="#多进程" aria-label="Permalink to &quot;多进程&quot;">&ZeroWidthSpace;</a></h3>
<p>数据大致是这样，生产者1-&gt;消费者1-&gt;消费者2，通过队列连接进程，生产者1一个，消费者1三个，消费者2三个<br>
此时生产者1完成之后，先检查数据是否完全放到队列中了，然后把状态表里自己的状态改为停止<br>
消费者1取队列取不到之后等待三秒，try住错误，检查表中生产者1的状态，如果全关闭了那就是数据取完了，自己也关闭，改变表的状态。<br>
后续消费者都如此。<br>
这个程序启停是这样设计的。</p>
<h3 id="反爬机制" tabindex="-1">反爬机制 <a class="header-anchor" href="#反爬机制" aria-label="Permalink to &quot;反爬机制&quot;">&ZeroWidthSpace;</a></h3>
<p>推特主要就是频率限制和cookie，15秒一次动不动就reset connection，需要try之后等待再去请求，不要让进程里出现错误，否则进程就挂了<br>
再就是请求头和cookie，都要带上，不然就过不去</p>
<h2 id="问题" tabindex="-1">问题 <a class="header-anchor" href="#问题" aria-label="Permalink to &quot;问题&quot;">&ZeroWidthSpace;</a></h2>
<p>错误处理，日志方面还不完美，出现的错误都是直接try到了之后，打印信息跳过，继续下一次，没有设计足够的排查信息<br>
日志没用logger，状态管理都是实时打印，很多冗余信息，也不知道应该打印哪些信息<br>
线程状态管理应该配合错误处理</p>
<p>解析数据的时候其实我是直接写死的拿key，很不灵活，碰到的问题有 已经封禁账号发消息，不知道哪些请求没有数据，会报key error，写个try做一下处理，还有不知道这些json那个key没获取到的，没有评论数据，不过这种东西都不是必须的了，数据下来了想要就是早晚的事，这些也不是重点。</p>
<div class="info custom-block"><p class="custom-block-title">[ℹ️Info]</p>
<p>爬虫有实效性，网站一变爬虫基本就跟着变</p>
</div>
<h2 id="第二版v2" tabindex="-1">第二版v2 <a class="header-anchor" href="#第二版v2" aria-label="Permalink to &quot;第二版v2&quot;">&ZeroWidthSpace;</a></h2>
<p>不是demo了，得拿上去部署，很多模块都得重新设计。</p>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[clickhouse]]></title>
            <link>http://ooowl.fun/blogs/Web%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/%E5%AD%98%E5%82%A8%E6%8A%80%E6%9C%AF/clickhouse.html</link>
            <guid isPermaLink="false">http://ooowl.fun/blogs/Web%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/%E5%AD%98%E5%82%A8%E6%8A%80%E6%9C%AF/clickhouse.html</guid>
            <pubDate>Tue, 07 Jun 2022 15:49:50 GMT</pubDate>
            <content:encoded><![CDATA[<h1 id="clickhouse" tabindex="-1">clickhouse <a class="header-anchor" href="#clickhouse" aria-label="Permalink to &quot;clickhouse&quot;">&ZeroWidthSpace;</a></h1><p class="article-meta">创建于 2022年6月7日 23:49:50 · 约200字</p>
<p>定位是OLAP离线处理,真列式存储数据库，每列一个文件，使用场景数据量很大，单次导入分析，查询多响应快修改少。
对系统资源尤其是内存和CPU消耗大，简单的查询占用也不低，最好作为单独机器单独数据</p>
<ul>
<li><a href="https://clickhouse.com/docs/en/intro" target="_blank" rel="noreferrer">文档</a></li>
<li><a href="https://play.clickhouse.com/play?user=play" target="_blank" rel="noreferrer">playground</a></li>
<li><a href="https://repo.yandex.ru/clickhouse/tgz/stable/" target="_blank" rel="noreferrer">官网源压缩包</a></li>
</ul>
<h2 id="安装" tabindex="-1">安装 <a class="header-anchor" href="#安装" aria-label="Permalink to &quot;安装&quot;">&ZeroWidthSpace;</a></h2>
<p>clickhouse一共有四个组件，<code>clickhouse-common-static</code>，<code>clickhouse-common-static-dbg</code>，<code>clickhouse-server</code>，<code>clickhouse-client</code>,下载对应版本的就可以，下载解压完后分别进入四个文件夹中的install文件夹，运行<code>doinstall.sh</code>脚本就完了。
不知道原因，我没有clickhouse-server和client命令，但是直接clickhouse server client是可以的
默认端口9000，默认用户default</p>
<p><a href="https://juejin.cn/post/7118755909505040391" target="_blank" rel="noreferrer">clickhouse建宽表多少列最合适？ - 掘金</a></p>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[PythonCheatSheet]]></title>
            <link>http://ooowl.fun/blogs/Python/%E8%AF%AD%E6%B3%95%E5%92%8C%E5%BA%93/PythonCheatSheet.html</link>
            <guid isPermaLink="false">http://ooowl.fun/blogs/Python/%E8%AF%AD%E6%B3%95%E5%92%8C%E5%BA%93/PythonCheatSheet.html</guid>
            <pubDate>Wed, 25 May 2022 09:42:46 GMT</pubDate>
            <content:encoded><![CDATA[<h1 id="pythoncheatsheet" tabindex="-1">PythonCheatSheet <a class="header-anchor" href="#pythoncheatsheet" aria-label="Permalink to &quot;PythonCheatSheet&quot;">&ZeroWidthSpace;</a></h1><p class="article-meta">创建于 2022年5月25日 17:42:46 · 约732字</p>
<div class="info custom-block"><p class="custom-block-title">[📝Note]</p>
<p>积累一些技巧，比如读写超大文件这种小技巧</p>
</div>
<p>🕊<a href="https://www.bilibili.com/video/BV1QE411u7vK" target="_blank" rel="noreferrer">python 进阶技能_哔哩哔哩_bilibili</a><br>
<a href="https://www.bilibili.com/video/BV1jz411b7DH" target="_blank" rel="noreferrer">Python 进阶视频_哔哩哔哩_bilibili</a></p>
<h2 id="零散的记忆缓存" tabindex="-1">零散的记忆缓存 <a class="header-anchor" href="#零散的记忆缓存" aria-label="Permalink to &quot;零散的记忆缓存&quot;">&ZeroWidthSpace;</a></h2>
<h3 id="好习惯" tabindex="-1">好习惯 <a class="header-anchor" href="#好习惯" aria-label="Permalink to &quot;好习惯&quot;">&ZeroWidthSpace;</a></h3>
<ul>
<li>禁止使用<code>&quot;a&quot;+b+&quot;c&quot;</code>使用<code>&quot;a{b}c&quot;</code></li>
<li>不要<code>except:</code>空Error</li>
<li>检查参数是否为不可变</li>
<li>使用推导式注意可读性</li>
<li>替换原则，子类代替父类</li>
<li>不要用<code>═ ═</code>检查布尔值,用is，用if检查bool直接if x</li>
<li>使用<code>for i,v in enumerate(list)</code>代替<code>for i in range(len(list))</code>获取索引+元素
<ul>
<li>甚至可以zip<code>for i,(v1,v2) in enumerate(zip(list1,list2))</code></li>
</ul>
</li>
<li>约定优于配置</li>
<li>tuple解包<code>x,y=atuple</code></li>
<li>测试运行时间使用<code>time.perf_counter</code>时钟时间代替<code>time.time</code>更加精确</li>
<li>试运行使用log模块而不是打印</li>
<li>多进程不要总是<code>shell=True</code>，这会让进程在shell里运行（他是这么说的，但是我也不知道是啥问题）</li>
<li>不要<code>import *</code>会命名空间混乱</li>
<li>python虽然是解释型语言但也不是不编译，他只是编译到字节码阶段</li>
<li>遵守<a href="https://peps.python.org/pep-0008/" target="_blank" rel="noreferrer">PEP8</a></li>
<li>看到奇怪语法，想想是不是python2的遗留代码</li>
<li>查看文件(夹)是否存在,使用os.path或pathlib里的函数，这样不用打开文件性能高</li>
<li>不要在循环过程中修改可变类型etc数组</li>
<li>两个字符串中间没东西会自动合并</li>
<li>给俩变量一块赋值，发现不对劲检查括号</li>
<li>使用tuple函数声明传入可迭代类型会挨个构建</li>
</ul>
<h3 id="命名" tabindex="-1">命名 <a class="header-anchor" href="#命名" aria-label="Permalink to &quot;命名&quot;">&ZeroWidthSpace;</a></h3>
<p>驼峰法使用大小写来命名变量的方法，分为大驼峰和小驼峰<br>
特点
大驼蜂: UserName</p>
<ul>
<li>第一个字母大写，后边也大写
<ul>
<li>类名</li>
<li>函数名</li>
<li>属性名</li>
<li>命名空间</li>
</ul>
</li>
</ul>
<p>小驼蜂userName</p>
<ul>
<li>第一个字母小写，后边大写
<ul>
<li>变量</li>
</ul>
</li>
</ul>
<p>循环记得打括号</p>
<h3 id="pythonic" tabindex="-1">Pythonic <a class="header-anchor" href="#pythonic" aria-label="Permalink to &quot;Pythonic&quot;">&ZeroWidthSpace;</a></h3>
<p><code>#coding=utf-8</code>
<code>#-*- coding: utf-8 -*-</code></p>
<p>一直搞不清楚这俩头什么区别。直觉上一样。今天特意查了一下，大致明白了：<br>
对于python解释器来说，这两种写法一样。但是对于编辑器来讲，可能会出现识别问题。</p>
<p><a href="http://www.python.org/dev/peps/pep-0263/" target="_blank" rel="noreferrer">参考PEP-0236</a> Defining the Encoding</p>
<details class="details custom-block"><summary>Click to see more</summary>
<p>Python will default to ASCII as standard encoding if no other
encoding hints are given.</p>
<pre><code>To define a source code encoding, a magic comment must
be placed into the source files either as first or second
line in the file, such as:

      # coding=&lt;encoding name&gt;

or (using formats recognized by popular editors)

      #!/usr/bin/python
      # -*- coding: &lt;encoding name&gt; -*-

or

      #!/usr/bin/python
      # vim: set fileencoding=&lt;encoding name&gt; :

More precisely, the first or second line must match the regular
expression &quot;coding[:=]\s*([-\w.]+)&quot;. The first group of this
expression is then interpreted as encoding name. If the encoding
is unknown to Python, an error is raised during compilation. There
must not be any Python statement on the line that contains the
encoding declaration.

To aid with platforms such as Windows, which add Unicode BOM marks
to the beginning of Unicode files, the UTF-8 signature
'\xef\xbb\xbf' will be interpreted as 'utf-8' encoding as well
(even if no magic encoding comment is given).

If a source file uses both the UTF-8 BOM mark signature and a
magic encoding comment, the only allowed encoding for the comment
is 'utf-8'.  Any other encoding will cause an error.
</code></pre>
</details>
<h3 id="链式调用" tabindex="-1">链式调用 <a class="header-anchor" href="#链式调用" aria-label="Permalink to &quot;链式调用&quot;">&ZeroWidthSpace;</a></h3>
<p>类中的一些函数没有返回值的时候，可以返回self使用方法链，如果是不修改自身实例，返回一个新的，可以使用type创建新实例使用方法链</p>
<details class="details custom-block"><summary>链式调用</summary>
<p>式调用</p>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Player</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __init__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self,name,x,y):  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.name</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">name  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.x</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">x  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.y</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">y  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> zero</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self):  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.x</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.y</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> self</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 返回自身，使用链式调用  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> moveX</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self,offset):  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.x</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">offset  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> self</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 返回自身，使用链式调用  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        # return type(self)(self.name,self.x+offset,self.x) # 不改变自身返回新对象的链式调用  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> moveY</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self,offset):  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.y</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">offset  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> self</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 返回自身，使用链式调用  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __str__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self):  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        return</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%s</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">:(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%s</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%s</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">)"</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">%</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.name,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.x,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.y)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">p</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Player(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"player1"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">5</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">5</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">   p.zero()  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 也可以用\</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    .moveX(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    .moveY(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 等价于 p.zero().moveX(3).moveY(1)</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(p)</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br></div></div><p>运行结果</p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>player1:(3,1)</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div></details>
<h3 id="时间日期格式化" tabindex="-1">时间日期格式化 <a class="header-anchor" href="#时间日期格式化" aria-label="Permalink to &quot;时间日期格式化&quot;">&ZeroWidthSpace;</a></h3>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">date_obj </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> datetime.strptime(datetime_str,</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'%Y-%m-</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%d</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">T%H:%M:%S.</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%f</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">Z'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 尝试将字符串解析为ISO日期</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">result_str </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> date_obj.strftime(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'%Y-%m-</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%d</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 将日期转换为所需的格式'%y-%m-%d'</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br></div></div>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[深入Python]]></title>
            <link>http://ooowl.fun/blogs/Python/%E8%AF%AD%E6%B3%95%E5%92%8C%E5%BA%93/%E6%B7%B1%E5%85%A5python.html</link>
            <guid isPermaLink="false">http://ooowl.fun/blogs/Python/%E8%AF%AD%E6%B3%95%E5%92%8C%E5%BA%93/%E6%B7%B1%E5%85%A5python.html</guid>
            <pubDate>Mon, 23 May 2022 09:46:14 GMT</pubDate>
            <content:encoded><![CDATA[<h1 id="深入python" tabindex="-1">深入Python <a class="header-anchor" href="#深入python" aria-label="Permalink to &quot;深入Python&quot;">&ZeroWidthSpace;</a></h1><p class="article-meta">创建于 2022年5月23日 17:46:14 · 约634字</p>
<div class="tip custom-block"><p class="custom-block-title">[💡Tip]</p>
<p>深入这个概念和大数据是一样的，多深入才叫深入？<br>
这里会放一些自觉比较深的知识点和技巧，有些时候会和踩坑联动</p>
</div>
<p>%%toc%%</p>
<p><a href="https://gist.github.com/baymaxium/53af1bca2123dbd0cb82154455e7d48e" target="_blank" rel="noreferrer">深入理解 Python 异步编程（上） · GitHub</a></p>
<h2 id="gc原理剖析" tabindex="-1">GC原理剖析 <a class="header-anchor" href="#gc原理剖析" aria-label="Permalink to &quot;GC原理剖析&quot;">&ZeroWidthSpace;</a></h2>
<p>^08132d
#TODO GC看这里
<a href="https://zhuanlan.zhihu.com/p/83251959" target="_blank" rel="noreferrer">Python垃圾回收机制！非常实用 - 知乎</a><br/>
<a href="https://testerhome.com/topics/16556" target="_blank" rel="noreferrer">记一次面试问题——Python 垃圾回收机制 · TesterHome</a><br/>
<a href="https://www.bilibili.com/video/BV1Ei4y1b7mo?spm_id_from=333.337.search-card.all.click" target="_blank" rel="noreferrer">2小时吃透python内存管理和垃圾回收机制_哔哩哔哩_bilibili</a></p>
<h3 id="环形数据结构" tabindex="-1">环形数据结构 <a class="header-anchor" href="#环形数据结构" aria-label="Permalink to &quot;环形数据结构&quot;">&ZeroWidthSpace;</a></h3>
<p>著名的环形引用
<a href="https://ijackey.com/python-%E5%A6%82%E4%BD%95%E5%9C%A8%E7%8E%AF%E7%8A%B6%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%AD%E7%AE%A1%E7%90%86%E5%86%85%E5%AD%98-956.html" target="_blank" rel="noreferrer">Python 如何在环状数据结构中管理内存 - i'm jackey - i'm jackey</a></p>
<h2 id="编译器相关扩展了解" tabindex="-1">编译器相关扩展了解 <a class="header-anchor" href="#编译器相关扩展了解" aria-label="Permalink to &quot;编译器相关扩展了解&quot;">&ZeroWidthSpace;</a></h2>
<p>如果以后接触C的话可能就会再深入了解源码和python的机制<br>
<a href="https://www.bilibili.com/video/BV1134y1h7ED?p=1&amp;share_medium=android_b&amp;share_plat=android&amp;share_source=QQ&amp;share_tag=s_i&amp;timestamp=1653319758&amp;unique_k=3P15feM" target="_blank" rel="noreferrer">python语言编译原理相关的杂谈bilibili</a></p>
<h2 id="网络编程详解" tabindex="-1">网络编程详解 <a class="header-anchor" href="#网络编程详解" aria-label="Permalink to &quot;网络编程详解&quot;">&ZeroWidthSpace;</a></h2>
<h2 id="异步进阶" tabindex="-1">异步进阶 <a class="header-anchor" href="#异步进阶" aria-label="Permalink to &quot;异步进阶&quot;">&ZeroWidthSpace;</a></h2>
<p>^347f89
异步的内容其实还有很多，这里只放已经收集到的<br>
gevent的缺点，使用C实现底层协程，使用猴子将普通库打补丁，会导致有些错误无法捕捉</p>
<h3 id="使用线程池异步" tabindex="-1">使用线程池异步 <a class="header-anchor" href="#使用线程池异步" aria-label="Permalink to &quot;使用线程池异步&quot;">&ZeroWidthSpace;</a></h3>
<p>有些时候外部接口只提供了阻塞方法，没有提供异步方法，还是需要使用线程，但是一般不是特别常用</p>
<details class="details custom-block"><summary>Click to see more</summary>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> asyncio,time,random  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> concurrent.futures </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> ThreadPoolExecutor  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> socket  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> urllib.parse </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> urlparse  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> func</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(a):  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    # 阻塞方法  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    t</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">random.randint(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">5</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"arg is </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%s</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">%</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">a)  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"start sleep </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%s</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">%</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">t)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    time.sleep(t)  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"end sleep </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%s</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">%</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">t)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">if</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __name__</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> ==</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "__main__"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    start_time </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> time.time()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    loop </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> asyncio.get_event_loop()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    executor </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> ThreadPoolExecutor(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 申请线程池  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    tasks </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> []  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> range</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">20</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">):  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        task </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> loop.run_in_executor(executor, func, i)  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        # 注意协程的这个函数，传入的是executor，返回是封装的Future对象，可以直接放在协程中使用  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        tasks.append(task)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    loop.run_until_complete(asyncio.wait(tasks))  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"last time:</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">{}</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.format(time.time()</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">start_time))</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br></div></div><p>运行结果</p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>arg is 0</span></span>
<span class="line"><span>start sleep 4</span></span>
<span class="line"><span>arg is 1</span></span>
<span class="line"><span>start sleep 4</span></span>
<span class="line"><span>arg is 2</span></span>
<span class="line"><span>start sleep 3</span></span>
<span class="line"><span>end sleep 3</span></span>
<span class="line"><span>arg is 19</span></span>
<span class="line"><span>start sleep 3</span></span>
<span class="line"><span>end sleep 4</span></span>
<span class="line"><span>end sleep 4</span></span>
<span class="line"><span>...</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br></div></div></details>
<p><a href="https://blog.csdn.net/General_zy/article/details/122337018" target="_blank" rel="noreferrer">协程模块asyncio和gevent的基本使用_Generalzy的博客-CSDN博客</a></p>
<h3 id="多进程异步" tabindex="-1">多进程异步 <a class="header-anchor" href="#多进程异步" aria-label="Permalink to &quot;多进程异步&quot;">&ZeroWidthSpace;</a></h3>
<p>这才是重点，因为GIL的原因多线程和异步没有耦合的必要，但是多进程+协程可以榨干CPU</p>
<h3 id="twisted" tabindex="-1">twisted <a class="header-anchor" href="#twisted" aria-label="Permalink to &quot;twisted&quot;">&ZeroWidthSpace;</a></h3>
<h3 id="gevent" tabindex="-1">gevent <a class="header-anchor" href="#gevent" aria-label="Permalink to &quot;gevent&quot;">&ZeroWidthSpace;</a></h3>
<h2 id="混合编程" tabindex="-1">混合编程 <a class="header-anchor" href="#混合编程" aria-label="Permalink to &quot;混合编程&quot;">&ZeroWidthSpace;</a></h2>
<p>起初是一个同学然你给我帮他java调用python，python调java，发现并不是很好用<br>
go建议直接RPC</p>
<h3 id="java混合编程" tabindex="-1">java混合编程 <a class="header-anchor" href="#java混合编程" aria-label="Permalink to &quot;java混合编程&quot;">&ZeroWidthSpace;</a></h3>
<h3 id="c混合编程" tabindex="-1">C混合编程 <a class="header-anchor" href="#c混合编程" aria-label="Permalink to &quot;C混合编程&quot;">&ZeroWidthSpace;</a></h3>
<h2 id="热加载" tabindex="-1">热加载 <a class="header-anchor" href="#热加载" aria-label="Permalink to &quot;热加载&quot;">&ZeroWidthSpace;</a></h2>
<p>python程序的热加载还是程序的热加载？</p>
<h2 id="pythonic的约定" tabindex="-1">pythonic的约定 <a class="header-anchor" href="#pythonic的约定" aria-label="Permalink to &quot;pythonic的约定&quot;">&ZeroWidthSpace;</a></h2>
<p><a href="https://www.bilibili.com/video/BV135411R7ru" target="_blank" rel="noreferrer">Pythonic的方式全方位提升Python技能</a></p>
<p><a href="https://www.jianshu.com/p/98caca0b0f19" target="_blank" rel="noreferrer">python中一切皆对象的本质</a> # py的对象底层</p>
<p><a href="https://github.com/piglei/one-python-craftsman" target="_blank" rel="noreferrer">GitHub - piglei/one-python-craftsman: 来自一位 Pythonista 的编程经验分享，内容涵盖编码技巧、最佳实践与思维模式等方面。</a></p>
<p><a href="https://www.piglei.com/" target="_blank" rel="noreferrer">Blog | Piglei</a></p>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Python库]]></title>
            <link>http://ooowl.fun/blogs/Python/%E8%AF%AD%E6%B3%95%E5%92%8C%E5%BA%93/Python%E5%BA%93.html</link>
            <guid isPermaLink="false">http://ooowl.fun/blogs/Python/%E8%AF%AD%E6%B3%95%E5%92%8C%E5%BA%93/Python%E5%BA%93.html</guid>
            <pubDate>Wed, 18 May 2022 10:16:08 GMT</pubDate>
            <description><![CDATA[首当其冲，这个高性能扩展数据类型库是每一个pythoner必须的]]></description>
            <content:encoded><![CDATA[<h1 id="python库" tabindex="-1">Python库 <a class="header-anchor" href="#python库" aria-label="Permalink to &quot;Python库&quot;">&ZeroWidthSpace;</a></h1><p class="article-meta">创建于 2022年5月18日 18:16:08 · 约328字</p>
<h2 id="collections" tabindex="-1">collections <a class="header-anchor" href="#collections" aria-label="Permalink to &quot;collections&quot;">&ZeroWidthSpace;</a></h2>
<p>首当其冲，这个高性能扩展数据类型库是每一个pythoner必须的</p>
<h2 id="numbers" tabindex="-1">numbers <a class="header-anchor" href="#numbers" aria-label="Permalink to &quot;numbers&quot;">&ZeroWidthSpace;</a></h2>
<p>列举出了基本的数据类型</p>
<h2 id="bisect序列排序" tabindex="-1">bisect序列排序 <a class="header-anchor" href="#bisect序列排序" aria-label="Permalink to &quot;bisect序列排序&quot;">&ZeroWidthSpace;</a></h2>
<p>^194418</p>
<p><a href="https://docs.python.org/zh-cn/3.9/library/bisect.html" target="_blank" rel="noreferrer">文档</a><br>
<code>insort</code>是<code>insort_right</code>默认方式<br>
<code>bisect</code>是<code>bisect_right</code>默认方式<br>
一共四个算法，二分查找<code>bisect</code>和插入<code>insort</code>，分别是从左或者右<br>
可以用来维护一个排序序列<br>
<code>insort</code>不会返回值，<code>bisect</code>会返回适合插入的位置，可以直接用序列的<code>insert</code>插入</p>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> bisect  </span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">a</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[]  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">bisect.insort_right(a,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">6</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">bisect.insort_right(a,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">7</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">bisect.insort_right(a,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">bisect.insort_right(a,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">4</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">a.insert(bisect.bisect_right(a,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">5</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">),</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">5</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(a)</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#----结果----</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">4</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">5</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">6</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">7</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br></div></div><p>用来查找的时候按照官方文档包装一下</p>
<h2 id="functools" tabindex="-1">functools <a class="header-anchor" href="#functools" aria-label="Permalink to &quot;functools&quot;">&ZeroWidthSpace;</a></h2>
<p><a href="https://www.jianshu.com/p/15757099a395" target="_blank" rel="noreferrer">functools模块学习 - 简书</a></p>
<h3 id="偏函数" tabindex="-1">偏函数 <a class="header-anchor" href="#偏函数" aria-label="Permalink to &quot;偏函数&quot;">&ZeroWidthSpace;</a></h3>
<p>^ff28bf</p>
<p>提前把函数的参数固定住，配合闭包看</p>
<h3 id="cache" tabindex="-1">cache <a class="header-anchor" href="#cache" aria-label="Permalink to &quot;cache&quot;">&ZeroWidthSpace;</a></h3>
<p>加速缓存</p>
<h2 id="itertools" tabindex="-1">itertools <a class="header-anchor" href="#itertools" aria-label="Permalink to &quot;itertools&quot;">&ZeroWidthSpace;</a></h2>
<p>用于更好遍历和封装的库
itertools.groupby数组只会去相邻的重，groupby的本质是使用前使用前先排序
<a href="https://www.bilibili.com/video/BV19V4y1F7if" target="_blank" rel="noreferrer">【python技巧059】用itertools处理各种花样的迭代_哔哩哔哩_bilibili</a></p>
<h2 id="时间和日期" tabindex="-1">时间和日期 <a class="header-anchor" href="#时间和日期" aria-label="Permalink to &quot;时间和日期&quot;">&ZeroWidthSpace;</a></h2>
<h3 id="测试程序性能" tabindex="-1">测试程序性能 <a class="header-anchor" href="#测试程序性能" aria-label="Permalink to &quot;测试程序性能&quot;">&ZeroWidthSpace;</a></h3>
<h3 id="arrow" tabindex="-1">arrow <a class="header-anchor" href="#arrow" aria-label="Permalink to &quot;arrow&quot;">&ZeroWidthSpace;</a></h3>
<h2 id="try-except的使用规范" tabindex="-1">try-except的使用规范 <a class="header-anchor" href="#try-except的使用规范" aria-label="Permalink to &quot;try-except的使用规范&quot;">&ZeroWidthSpace;</a></h2>
<h2 id="哈希" tabindex="-1">哈希 <a class="header-anchor" href="#哈希" aria-label="Permalink to &quot;哈希&quot;">&ZeroWidthSpace;</a></h2>
<h2 id="文件和序列化io" tabindex="-1">文件和序列化IO <a class="header-anchor" href="#文件和序列化io" aria-label="Permalink to &quot;文件和序列化IO&quot;">&ZeroWidthSpace;</a></h2>
<h2 id="图像音视频" tabindex="-1">图像音视频 <a class="header-anchor" href="#图像音视频" aria-label="Permalink to &quot;图像音视频&quot;">&ZeroWidthSpace;</a></h2>
<p>pillow
opencv
moviepy
musicpy
pydub</p>
<h2 id="网络" tabindex="-1">网络 <a class="header-anchor" href="#网络" aria-label="Permalink to &quot;网络&quot;">&ZeroWidthSpace;</a></h2>
<p>pywifi
paramiko</p>
<h2 id="有趣的包" tabindex="-1">有趣的包 <a class="header-anchor" href="#有趣的包" aria-label="Permalink to &quot;有趣的包&quot;">&ZeroWidthSpace;</a></h2>
<h3 id="tqdm进度条" tabindex="-1">tqdm进度条 <a class="header-anchor" href="#tqdm进度条" aria-label="Permalink to &quot;tqdm进度条&quot;">&ZeroWidthSpace;</a></h3>
<p>提供文本动画进度条，使用方法：</p>
<div class="language-Python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">Python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> time</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> tqdm </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> tqdm</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> tqdm(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">range</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1000</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)):</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    time.sleep(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">.01</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#----------</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">65</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">%|</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">██████████████████▏           </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">|</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 649</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">/</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1000</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> [</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">00</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#B31D28;--shiki-light-font-style:italic;--shiki-dark:#FDAEB7;--shiki-dark-font-style:italic">7</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x3C;</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">00</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#B31D28;--shiki-light-font-style:italic;--shiki-dark:#FDAEB7;--shiki-dark-font-style:italic">4</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">86.</span><span style="--shiki-light:#B31D28;--shiki-light-font-style:italic;--shiki-dark:#FDAEB7;--shiki-dark-font-style:italic">51it</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">/</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">s]</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br></div></div><h3 id="代码流程可视化" tabindex="-1">代码流程可视化 <a class="header-anchor" href="#代码流程可视化" aria-label="Permalink to &quot;代码流程可视化&quot;">&ZeroWidthSpace;</a></h3>
<h4 id="pycallgraph" tabindex="-1">pycallgraph <a class="header-anchor" href="#pycallgraph" aria-label="Permalink to &quot;pycallgraph&quot;">&ZeroWidthSpace;</a></h4>
<h4 id="code2flow" tabindex="-1">code2flow <a class="header-anchor" href="#code2flow" aria-label="Permalink to &quot;code2flow&quot;">&ZeroWidthSpace;</a></h4>
<h3 id="python分析调试" tabindex="-1">python分析调试 <a class="header-anchor" href="#python分析调试" aria-label="Permalink to &quot;python分析调试&quot;">&ZeroWidthSpace;</a></h3>
<p><a href="https://www.bilibili.com/video/BV1d34y1C78W" target="_blank" rel="noreferrer">Python分析调试神器【VizTracer】之作者精讲_哔哩哔哩_bilibili</a><br/>
<a href="https://github.com/gaogaotiantian/viztracer" target="_blank" rel="noreferrer">gaogaotiantian/viztracer</a></p>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Python语言进阶]]></title>
            <link>http://ooowl.fun/blogs/Python/%E8%AF%AD%E6%B3%95%E5%92%8C%E5%BA%93/Python%E8%AF%AD%E8%A8%80%E8%BF%9B%E9%98%B6.html</link>
            <guid isPermaLink="false">http://ooowl.fun/blogs/Python/%E8%AF%AD%E6%B3%95%E5%92%8C%E5%BA%93/Python%E8%AF%AD%E8%A8%80%E8%BF%9B%E9%98%B6.html</guid>
            <pubDate>Wed, 18 May 2022 10:15:21 GMT</pubDate>
            <description><![CDATA[[💡Tip]]]></description>
            <content:encoded><![CDATA[<h1 id="python语言进阶" tabindex="-1">Python语言进阶 <a class="header-anchor" href="#python语言进阶" aria-label="Permalink to &quot;Python语言进阶&quot;">&ZeroWidthSpace;</a></h1><p class="article-meta">创建于 2022年5月18日 18:15:21 · 约27,437字</p>
<div class="tip custom-block"><p class="custom-block-title">[💡Tip]</p>
<p>python的进阶提高，波比很经典的课了，配合<a href="https://python3-cookbook.readthedocs.io/zh_CN/latest/index.html" target="_blank" rel="noreferrer">cookbook</a>和<a href="https://docs.python.org/zh-cn/3.9/" target="_blank" rel="noreferrer">文档</a><br>
写的可能会很长</p>
</div>
<p>动态语言只有在运行的时候才能发现错误，这是固有缺点</p>
<h2 id="初始化-模块-和包" tabindex="-1">初始化,模块,和包 <a class="header-anchor" href="#初始化-模块-和包" aria-label="Permalink to &quot;初始化,模块,和包&quot;">&ZeroWidthSpace;</a></h2>
<h3 id="资料源" tabindex="-1">资料源 <a class="header-anchor" href="#资料源" aria-label="Permalink to &quot;资料源&quot;">&ZeroWidthSpace;</a></h3>
<ul>
<li><a href="https://python3-cookbook.readthedocs.io/zh_CN/latest/index.html" target="_blank" rel="noreferrer">cookbook</a></li>
<li><a href="https://docs.python.org/zh-cn/3/library/index.html" target="_blank" rel="noreferrer">官方文档#第三方包</a></li>
<li><a href="https://docs.python.org/3/library/functions.html" target="_blank" rel="noreferrer">内置函数Built-in Functions</a></li>
<li><a href="https://pypi.org/" target="_blank" rel="noreferrer">第三方包查询pypi</a></li>
<li><a href="https://peps.python.org/" target="_blank" rel="noreferrer">Python Enhancement Proposals-PEP</a></li>
</ul>
<h3 id="python编码风格规范" tabindex="-1">python编码风格规范 <a class="header-anchor" href="#python编码风格规范" aria-label="Permalink to &quot;python编码风格规范&quot;">&ZeroWidthSpace;</a></h3>
<p><a href="https://zh-google-styleguide.readthedocs.io/en/latest/google-python-styleguide/contents/" target="_blank" rel="noreferrer">Python 风格指南 — Google 开源项目风格指南</a><br>
<a href="https://peps.python.org/pep-0008/" target="_blank" rel="noreferrer">PEP 8 – Style Guide for Python Code</a><br>
Python的创始人为Guido van Rossum。1989年圣诞节期间，在阿姆斯特丹，Guido为了打发圣诞节的无趣，决心开发一个新的脚本解释程序，作为ABC 语言的一种继承。之所以选中Python（大蟒蛇的意思）作为该编程语言的名字，是取自英国20世纪70年代首播的电视喜剧《蒙提.派森干的飞行马戏团》（Monty Python's Flying Circus）。</p>
<div class="tip custom-block"><p class="custom-block-title">[✅Success] python之禅</p>
<p>ython之禅
写pythonic的代码</p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>The Zen of Python, by Tim Peters</span></span>
<span class="line"><span></span></span>
<span class="line"><span>Beautiful is better than ugly.</span></span>
<span class="line"><span>Explicit is better than implicit.</span></span>
<span class="line"><span>Simple is better than complex.</span></span>
<span class="line"><span>Complex is better than complicated.</span></span>
<span class="line"><span>Flat is better than nested.</span></span>
<span class="line"><span>Sparse is better than dense.</span></span>
<span class="line"><span>Readability counts.</span></span>
<span class="line"><span>Special cases aren't special enough to break the rules.</span></span>
<span class="line"><span>Although practicality beats purity.</span></span>
<span class="line"><span>Errors should never pass silently.</span></span>
<span class="line"><span>Unless explicitly silenced.</span></span>
<span class="line"><span>In the face of ambiguity, refuse the temptation to guess.</span></span>
<span class="line"><span>There should be one-- and preferably only one --obvious way to do it.</span></span>
<span class="line"><span>Although that way may not be obvious at first unless you're Dutch.</span></span>
<span class="line"><span>Now is better than never.</span></span>
<span class="line"><span>Although never is often better than *right* now.</span></span>
<span class="line"><span>If the implementation is hard to explain, it's a bad idea.</span></span>
<span class="line"><span>If the implementation is easy to explain, it may be a good idea.</span></span>
<span class="line"><span>Namespaces are one honking great idea -- let's do more of those!</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br></div></div><p><strong>翻译</strong></p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>优美优于丑陋，</span></span>
<span class="line"><span>明了优于隐晦；</span></span>
<span class="line"><span>简单优于复杂，</span></span>
<span class="line"><span>复杂优于繁杂，</span></span>
<span class="line"><span>扁平优于嵌套，</span></span>
<span class="line"><span>稀疏优于稠密，</span></span>
<span class="line"><span>可读性很重要！</span></span>
<span class="line"><span>特例亦不可违背原则，</span></span>
<span class="line"><span>即使实用比纯粹更优。</span></span>
<span class="line"><span>错误绝不能悄悄忽略，</span></span>
<span class="line"><span>除非它明确需要如此。</span></span>
<span class="line"><span>面对不确定性，</span></span>
<span class="line"><span>拒绝妄加猜测。</span></span>
<span class="line"><span>任何问题应有一种，且最好只有一种，显而易见的解决方法。</span></span>
<span class="line"><span>尽管这方法一开始并非如此直观，除非你是荷兰人。</span></span>
<span class="line"><span>做优于不做，</span></span>
<span class="line"><span>然而不假思索还不如不做。</span></span>
<span class="line"><span>很难解释的，必然是坏方法。</span></span>
<span class="line"><span>很好解释的，可能是好方法。</span></span>
<span class="line"><span>命名空间是个绝妙的主意，我们应好好利用它。</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br></div></div></div>
<h3 id="包和模块" tabindex="-1">包和模块 <a class="header-anchor" href="#包和模块" aria-label="Permalink to &quot;包和模块&quot;">&ZeroWidthSpace;</a></h3>
<ul>
<li><code>if __name__ == &quot;__main__&quot;:</code> 可以避免在被引入的时候直接被执行代码</li>
<li>基本信息
<ul>
<li><code># -*-coding:utf-8-*-</code> 指明文件的编码</li>
<li><code>__author__ = &quot;a_little_rubbish&quot;</code></li>
<li><code>__date__ = &quot;2022/5/19 18:06&quot;</code></li>
</ul>
</li>
<li>包/模块的存放位置：<code>print(xx.__file__)</code></li>
<li>查看包/模块里的内容：<code>print(dir(xx))</code></li>
</ul>
<p>正在运行的文件会被python添加到PATH中去</p>
<ul>
<li>模块(module)其实就是py文件，里面定义了一些函数、类、变量等。文件是os层面的东西，module是语言层面的东西</li>
<li>包(package)是多个模块的聚合体形成的文件夹，里面可以是多个py文件，也可以嵌套文件夹</li>
<li>库是参考其他编程语言的说法，是指完成一定功能的代码集合，在python中的形式就是模块和包</li>
</ul>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> builtins  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 其实命名空间就是builtins</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">builtins.print(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Hello world."</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br></div></div><p>引入就要用import，import from，import as。<br>
导入其实是要将 被导入模块所有的顶格代码都执行一遍，遇到函数和类的定义会作申明。<mark>import会把文件变成module</mark><br>
文件夹中新建一个<code>__init__.py</code>文件里面可以什么都不填，就被python当成包python3.3+可以省略但是不建议。<br>
正常import了啥东西才可以用啥，除非<code>import *</code> 但是import包之后可以直接调用在<code>__init__.py</code>文件文件中定义的变量，所以可以把想要导入后直接出现在命名空间的包内变量提前导入init使用<code>from . import 包中的模块</code>可保证移植性<br>
<code>import *</code>的方式无法导入以下划线开头的变量名，但可以指定变量导入<br>
<code>import *</code>只会导入<code>__all__=[variable，valriable]</code>中指定的变量，无论是否以下划线开头，这样限制可以防止<code>import *</code>命令导入太多变量污染命名空间</p>
<p>PATH搜索顺序</p>
<ul>
<li>pycharm marked as source root告诉IDE编译器此文件夹及其子文件夹包含应作为构建过程的一部分进行编译的源代码。
<ul>
<li>就可以从这下面找包了</li>
</ul>
</li>
<li>首先搜寻内置模块是否有<code>hello</code>（所以我们定义的模块名不要和内置模块相同）</li>
<li>如果内置模块没有，则看PATH(即<code>sys.path</code>)里有没有
<ul>
<li><code>''</code>表示当前的工作路径</li>
<li>环境变量PYTHONPATH中指定的路径列表
<ul>
<li>正在运行的文件会被python添加到PATH中去</li>
</ul>
</li>
<li>特定路径下的.pth文件中指定的路径列表
<ul>
<li>Python 在遍历已知的库文件目录过程中，如果遇到 <code>.pth</code> 文件，便会将其中的路径加入到 <code>sys.path</code> 中</li>
<li>一行一个，可空行可注释，相对路径是本.pth文件的位置为起始</li>
</ul>
</li>
<li>在python安装路径的lib库中搜索</li>
</ul>
</li>
<li>绝对引用从包的位置开始</li>
<li>相对路径导入时
自定义模块和非内置模块重名：按sys.path路径，优先级高的覆盖低的。
​自定义模块和内置模块重名：内置模块覆盖自定义模块。</li>
</ul>
<p><a href="https://www.bilibili.com/video/BV1YweNe2EGa" target="_blank" rel="noreferrer">[Python] 一个视频弄明白import, package, module 包管理_哔哩哔哩_bilibili</a></p>
<p><strong>第一次导入时</strong>：<br>
​ 1、在所导的模块下的命名空间中执行所有代码；
​ 2、创建一个module对象，并将模块内所有的顶级变量以属性的形式绑定到该对象上；
​ 3、在import语句所处的命名空间引入第2步创建的module对象的变量名称。<br>
<strong>第二次导入时</strong>：直接执行第3步。（1、2步创建的module对象放到<code>sys.modules</code>里了）<br>
<strong>互相导入</strong>:  不会像递归一样死循环，因为import的模块对象只创建一遍，不会再去执行第二遍。</p>
<ul>
<li><code>from folder1.abcd import b</code>其实也执行了<code>__init__.py</code>文件文件与<code>abcd.py</code>文件
<ul>
<li>实际上是import了两次，第二次检查<code>sys.modules</code>就忽略了，所以里面的东西只会执行一次</li>
</ul>
</li>
<li>如果import这个文件夹下的子文件下的某个模块时，则先按顺序执行父文件夹的所有<code>__init__.py</code>，再执行该文件的<code>__init__.py</code>，再执行该模块</li>
</ul>
<p><code>help(module)</code>查看模块的帮助手册<br>
在python的目录下有Doc文件夹有语言使用手册</p>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">try</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> other_1 </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">as</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> o </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 有1导1</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">except</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> ModuleNotFoundError</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> other_2 </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">as</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> o </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 没1导2</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br></div></div><p><img src="./static/Python语言进阶_images_1.png" alt="800"></p>
<h4 id="循环导入" tabindex="-1">循环导入 <a class="header-anchor" href="#循环导入" aria-label="Permalink to &quot;循环导入&quot;">&ZeroWidthSpace;</a></h4>
<p><img src="./static/python语言进阶_images_2.png" alt="">
此时<code>from test2 import c</code>报错 ，先引用test之后就不会了</p>
<ol>
<li>引用<code>test2/c</code>模块</li>
<li>由于是第一次引用<code>test2/c</code>模块，此时会执行<code>test2/c.py</code>文件，此时会执行<code>from test import a</code></li>
<li>此时执行了包<code>test/__init__.py</code>的代码，执行了<code>from . import b</code>，引用了模块<code>test/b</code></li>
<li>模块<code>test/b</code>由于是第一次被引用，会执行其中的代码，执行<code>from test2 import c</code>，循环引用出现，报错</li>
<li>分析一下为什么先引入test就没关系了</li>
</ol>
<p>在引入没有完成的时候，又回来了就产生错误，如果已经引入完了，就没事和上面<strong>互相导入</strong>结合看</p>
<div class="info custom-block"><p class="custom-block-title">[📝Note]</p>
<p><code>from a.b.c import </code>的时候他会把路径上每一个package都引进来一次</p>
<p>相对引入的时候.package原理是通过获取当前的绝对路径来引入的，pythonenv也就是python解释器寻找资源的起始路径</p>
<p>相对引入的时候，<code>python a/b.py</code> 如果b中使用了相对引入<code>from .c import C</code>，他会直接在package a的同级目录下寻找c，必然报错，但是如果b这个文件是 <code>import a</code> a.b这样就没问题，因为python总是翻译成绝对路径进行引入，那么此时的package是a，会往b同级下寻找c就找到了</p>
<p>运行文件之前可以先指定运行的pwd，这样就不容易出错了</p>
</div>
<h3 id="os" tabindex="-1">os <a class="header-anchor" href="#os" aria-label="Permalink to &quot;os&quot;">&ZeroWidthSpace;</a></h3>
<p><a href="https://docs.python.org/3.9/library/os.html" target="_blank" rel="noreferrer">先放文档</a><br>
os是和操作系统相关的包，里面有对文件夹和系统信息的调用，这里整理一点常用的<br>
和linux里面的命令一样的我就简单放一下<br>
<code>os.rename</code>,<code>os.mkdir[s]</code>,<code>os.rmove</code>,<code>os.chdir</code>，<code>os.chmod(_path_, 755）</code>,<code>os.getcwd()</code>,<code>os.chcwd()</code>,<code>os.chown(_path_, _uid_, _gid_)</code>,<code>os.listdir(path='.')</code>,<code>os.removedirs(_name_)</code>,<code>os.rmdir</code>.</p>
<table tabindex="0">
<thead>
<tr>
<th style="text-align:left">函数变量</th>
<th style="text-align:left">作用</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:left"><code>os.name</code></td>
<td style="text-align:left">导入的依赖特定操作系统的模块的名称。以下名称目前已注册:<code>posix</code>,<code>nt</code>,<code>java</code>.</td>
</tr>
<tr>
<td style="text-align:left"><code>os.cpu_count()</code></td>
<td style="text-align:left">返回cpu内核数</td>
</tr>
<tr>
<td style="text-align:left"><code>os.walk(top, topdown=True)</code></td>
<td style="text-align:left">遍历文件夹返回<code>dirpath, dirnames, filenames</code></td>
</tr>
<tr>
<td style="text-align:left"><code>os.curdir</code></td>
<td style="text-align:left">操作系统用来表示当前目录的常量字符串</td>
</tr>
<tr>
<td style="text-align:left"><code>os.pardir</code></td>
<td style="text-align:left">操作系统用来表示父目录的常量字符串</td>
</tr>
<tr>
<td style="text-align:left"><code>os.sep</code></td>
<td style="text-align:left">操作系统用来分隔路径不同部分的字符。在 POSIX 上是 <code>'/'</code>，在 Windows 上是是 <code>'\\'</code>。<br/>注意，仅了解它不足以能解析或连接路径，请使用 <a href="https://docs.python.org/zh-cn/3.9/library/os.path.html#os.path.split" title="os.path.split" target="_blank" rel="noreferrer"><code>os.path.split()</code></a> 和 <a href="https://docs.python.org/zh-cn/3.9/library/os.path.html#os.path.join" title="os.path.join" target="_blank" rel="noreferrer"><code>os.path.join()</code></a>，<br/>但它有时是有用的。在 <a href="https://docs.python.org/zh-cn/3.9/library/os.path.html#module-os.path" title="os.path: Operations on pathnames." target="_blank" rel="noreferrer"><code>os.path</code></a> 中也可用。</td>
</tr>
<tr>
<td style="text-align:left"><code>os.altsep</code></td>
<td style="text-align:left">操作系统用来分隔路径不同部分的替代字符。<br/>如果仅存在一个分隔符，则为 <code>None</code>。<br/>在 <code>sep</code> 是反斜杠的 Windows 系统上，该值被设为 <code>'/'</code>。在 <a href="https://docs.python.org/zh-cn/3.9/library/os.path.html#module-os.path" title="os.path: Operations on pathnames." target="_blank" rel="noreferrer"><code>os.path</code></a> 中也可用。</td>
</tr>
<tr>
<td style="text-align:left"><code>os.extsep</code></td>
<td style="text-align:left">分隔基本文件名与扩展名的字符，<br/>如 <code>os.py</code> 中的 <code>'.'</code>。在 <a href="https://docs.python.org/zh-cn/3.9/library/os.path.html#module-os.path" title="os.path: Operations on pathnames." target="_blank" rel="noreferrer"><code>os.path</code></a> 中也可用。</td>
</tr>
<tr>
<td style="text-align:left"><code>os.pathsep</code></td>
<td style="text-align:left">操作系统通常用于分隔搜索路径<br/>（如 <code>PATH</code>）中不同部分的字符，<br/>如 POSIX 上是 <code>':'</code>，Windows 上是 <code>';'</code>。在 <a href="https://docs.python.org/zh-cn/3.9/library/os.path.html#module-os.path" title="os.path: Operations on pathnames." target="_blank" rel="noreferrer"><code>os.path</code></a> 中也可用。</td>
</tr>
<tr>
<td style="text-align:left"><code>os.linesep</code></td>
<td style="text-align:left">当前平台用于分隔（或终止）行的字符串。<br/>它可以是单个字符，如 POSIX 上是 <code>'\n'</code>，也可以是多个字符，如 Windows 上是 <code>'\r\n'</code>。<br/>在写入以文本模式（默认模式）打开的文件时，请不要使用 <em>os.linesep</em> 作为行终止符，<br/>请在所有平台上都使用一个 <code>'\n'</code> 代替。</td>
</tr>
<tr>
<td style="text-align:left"><code>os.devnull</code></td>
<td style="text-align:left">空设备的文件路径。<br/>如 POSIX 上为 <code>'/dev/null'</code>，Windows 上为 <code>'nul'</code>。在 <code>os.path</code>中也可用。</td>
</tr>
</tbody>
</table>
<h4 id="os-path" tabindex="-1">os.path <a class="header-anchor" href="#os-path" aria-label="Permalink to &quot;os.path&quot;">&ZeroWidthSpace;</a></h4>
<p><a href="https://docs.python.org/zh-cn/3/library/os.path.html" target="_blank" rel="noreferrer">os.path</a>模块是和路径相关的模块</p>
<table tabindex="0">
<thead>
<tr>
<th style="text-align:center">函数和变量</th>
<th style="text-align:center">功能</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center"><code>os.path.abspath(PATH)</code></td>
<td style="text-align:center">获取绝对路径</td>
</tr>
<tr>
<td style="text-align:center"><code>os.path.split(f)</code></td>
<td style="text-align:center">分割路径文件名</td>
</tr>
<tr>
<td style="text-align:center"><code>os.path.splitext(f)</code></td>
<td style="text-align:center">分割文件后缀名</td>
</tr>
<tr>
<td style="text-align:center"><code>os.path.dirname</code></td>
<td style="text-align:center">返回路径名</td>
</tr>
<tr>
<td style="text-align:center"><code>os.path.basename(_path_)</code></td>
<td style="text-align:center">获得文件/最后路径名<br/>此函数的结果与Unix <strong>basename</strong> 程序不同。<br/><strong>UNIX basename</strong> <br/>在 <code>'/foo/bar/'</code> 上返回 <code>'bar'</code>，而<br/> <a href="https://docs.python.org/zh-cn/3/library/os.path.html#os.path.basename" title="os.path.basename" target="_blank" rel="noreferrer"><code>os.path.basename()</code></a> 函数返回一个空字符串 (<code>''</code>)</td>
</tr>
<tr>
<td style="text-align:center"><code>os.path.commonpath(_paths_)</code></td>
<td style="text-align:center">接受包含多个路径的序列 <em>paths</em>，返回 <em>paths</em> 的最长公共子路径。</td>
</tr>
<tr>
<td style="text-align:center"><code>os.path.commonprefix(_list_)</code></td>
<td style="text-align:center">接受包含多个路径的 <em>列表</em>，返回所有路径的最长公共前缀（逐字符比较）</td>
</tr>
<tr>
<td style="text-align:center"><code>os.path.join(_path_, _*paths_)</code></td>
<td style="text-align:center">智能地拼接一个或多个路径部分。 返回值是 <em>path</em> 和 <em>*paths</em> 的所有成员的拼接</td>
</tr>
<tr>
<td style="text-align:center">isdir,isfile,isabs,islink,exists,ismount</td>
<td style="text-align:center">判断是啥</td>
</tr>
</tbody>
</table>
<h4 id="内置的变量" tabindex="-1">内置的变量 <a class="header-anchor" href="#内置的变量" aria-label="Permalink to &quot;内置的变量&quot;">&ZeroWidthSpace;</a></h4>
<ul>
<li><code>vars()</code> 以字典方式返回内置全局变量</li>
<li><code>__doc__</code> 获取文件开头的注释</li>
<li><code>__file__</code>完整的文件和路径名</li>
<li><code>__package__</code>获取导入文件的路径，多层目录以点分割，注意：对当前文件返回None</li>
<li><code>__cached__</code> 获取导入文件的缓存路径</li>
<li><code>__name__</code> 获取导入文件的路径加文件名称，路径以点分割，注意:获取当前文件返回__main__</li>
</ul>
<h3 id="sys" tabindex="-1">sys <a class="header-anchor" href="#sys" aria-label="Permalink to &quot;sys&quot;">&ZeroWidthSpace;</a></h3>
<p><a href="https://docs.python.org/zh-cn/3/library/sys.html" target="_blank" rel="noreferrer">文档</a>，这里面是和解释器运行相关的东西</p>
<table tabindex="0">
<thead>
<tr>
<th style="text-align:center">函数和变量</th>
<th style="text-align:center">功能</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center"><code>sys.getfilesystemencoding()</code></td>
<td style="text-align:center">获取文件系统编码</td>
</tr>
<tr>
<td style="text-align:center"><code>sys.getdefaultencoding()</code></td>
<td style="text-align:center">当前 Unicode 实现所使用的默认字符串编码名称</td>
</tr>
<tr>
<td style="text-align:center"><code>sys.copyright</code></td>
<td style="text-align:center">打印python的版权信息</td>
</tr>
<tr>
<td style="text-align:center"><code>sys.argv</code></td>
<td style="text-align:center">返回运行的参数列表，<code>sys.argv[0]</code>是脚本名</td>
</tr>
<tr>
<td style="text-align:center"><code>sys.version</code></td>
<td style="text-align:center">获取py版本号</td>
</tr>
<tr>
<td style="text-align:center"><code>sys.maxsize</code></td>
<td style="text-align:center">本系统能表示的int最大值</td>
</tr>
<tr>
<td style="text-align:center"><code>sys.path</code></td>
<td style="text-align:center">获取系统路径</td>
</tr>
<tr>
<td style="text-align:center"><code>sys.platform</code></td>
<td style="text-align:center">获取python的平台</td>
</tr>
<tr>
<td style="text-align:center"><code>sys.exit(0)</code></td>
<td style="text-align:center">退出(程序代码)</td>
</tr>
<tr>
<td style="text-align:center"><code>sys.executable</code></td>
<td style="text-align:center">当前python解释器绝对路径</td>
</tr>
<tr>
<td style="text-align:center"><code>sys.getrecursionlimit()</code></td>
<td style="text-align:center">可以递归的最大层数，可以在递归里用</td>
</tr>
<tr>
<td style="text-align:center"><code>sys.setrecursionlimit()</code></td>
<td style="text-align:center">设定最大层数</td>
</tr>
<tr>
<td style="text-align:center"><code>sys.getrefcount(object)</code></td>
<td style="text-align:center">返回 object 的引用计数。通常比预期的多一，<br/>因为包括了getrefcount()参数的这一次（临时）引用</td>
</tr>
<tr>
<td style="text-align:center"><code>sys.modules</code></td>
<td style="text-align:center">返回已经被引入的模块列表</td>
</tr>
<tr>
<td style="text-align:center"><code>sys.getsizeof(object[, default])</code></td>
<td style="text-align:center">返回对象的大小（以字节为单位）,<br/>只计算直接分配给对象的内存消耗，<br/>不计算它所引用的对象的内存消耗,<br/>对象不提供计算大小的方法时指定default</td>
</tr>
<tr>
<td style="text-align:center"><code>sys.stdin</code></td>
<td style="text-align:center">获取标准输入流，list转化一下打印出来看看是什么(一般的项目不会用到)</td>
</tr>
</tbody>
</table>
<hr>
<h2 id="常见的内置类型一览" tabindex="-1">常见的内置类型一览 <a class="header-anchor" href="#常见的内置类型一览" aria-label="Permalink to &quot;常见的内置类型一览&quot;">&ZeroWidthSpace;</a></h2>
<p>后面会详细讲解一些类型<br>
python的对象会有三个特征，身份，类型，值</p>
<div class="info custom-block"><p class="custom-block-title">[ℹ️Info]</p>
<p>python的内置函数都是<strong>内嵌在解释器里</strong>面的，是使用C编写的，正常情况下你是无法查看的，只不过pycharm这种智能编辑器对其进行了一个抽象罢了，可以让你查看相应的注释。<br>
代码的具体实现是通过C实现的，该文件只是起到一个让你学习的辅助作用。</p>
</div>
<h3 id="身份-内存" tabindex="-1">身份(内存) <a class="header-anchor" href="#身份-内存" aria-label="Permalink to &quot;身份(内存)&quot;">&ZeroWidthSpace;</a></h3>
<p>理解为对象在内存中的地址，可以使用<code>id()</code>查看</p>
<h4 id="isinstance-is-的区分" tabindex="-1">isinstance,is,== 的区分 <a class="header-anchor" href="#isinstance-is-的区分" aria-label="Permalink to &quot;isinstance,is,== 的区分&quot;">&ZeroWidthSpace;</a></h4>
<ul>
<li><code>isinstance(obj,type)</code> 不仅可以判断是否实现了ABC，也会顺着继承链判断，判断是不是父类型也是用它，子类型对象是父类型的，倒过来不是是不是父类型也是用它，子类型对象是父类型的，倒过来不是</li>
<li><code>issubclass(class,type)</code>判断是否为子类。<br>
这俩函数第二个参数可以为tuple，只要其中有一个符合即为True，自己判断也算。</li>
<li><code>is</code> 判断的是id是否相同</li>
<li><code>═ ═</code> 判断的是值相等</li>
</ul>
<h4 id="深浅拷贝" tabindex="-1">深浅拷贝 <a class="header-anchor" href="#深浅拷贝" aria-label="Permalink to &quot;深浅拷贝&quot;">&ZeroWidthSpace;</a></h4>
<p>深拷贝需要引入<code>copy</code>包</p>
<ol>
<li><strong>b = a:</strong> 赋值引用，a 和 b 都指向同一个对象。</li>
<li><strong>b = a.copy():</strong> 浅拷贝, a 和 b 是一个独立的对象，但他们的子对象还是指向同一引用,dict套list，拷贝完后俩dict的list指向原先的同一个list</li>
<li><strong>b = copy.deepcopy(a):</strong> 深度拷贝, a 和 b 完全拷贝了对象及其子对象，两者是完全独立的。</li>
</ol>
<h3 id="类型" tabindex="-1">类型 <a class="header-anchor" href="#类型" aria-label="Permalink to &quot;类型&quot;">&ZeroWidthSpace;</a></h3>
<p>这些类型和java有一定区别<br>
None在python启动解释器的时候，会使用None class声明一个None，全局只有一个，是不可变对象，无论赋值给多少个变量使用id查看是一样的<br>
<strong>常见类型</strong></p>
<ul>
<li>数值
<ul>
<li>int</li>
<li>float</li>
<li>complex
<ul>
<li>c.real &amp; c.image</li>
</ul>
</li>
<li>bool</li>
</ul>
</li>
<li>迭代类型</li>
<li>序列类型
<ul>
<li>list</li>
<li>bytes、bytearray、memoryview（二进制序列）</li>
<li>range</li>
<li>tuple
<ul>
<li>collections.namedtuple</li>
</ul>
</li>
<li>str</li>
<li>array</li>
</ul>
</li>
<li>映射类型(dict)</li>
<li>集合类型(性能很高)
<ul>
<li>set</li>
<li>frozenset(不可修改的set)</li>
</ul>
</li>
<li>上下文管理类型(with语句)</li>
<li>其他类型
<ul>
<li>模块类型</li>
<li>class和实例</li>
<li>函数类型</li>
<li>方法类型(区别于函数)</li>
<li>代码类型</li>
<li>object对象</li>
<li>type类型</li>
<li>ellipsis类型(<code>...</code>省略号)</li>
<li>notimplemented类型</li>
<li>enum枚举类</li>
</ul>
</li>
</ul>
<h4 id="常见类型转换快速复习" tabindex="-1">常见类型转换快速复习 <a class="header-anchor" href="#常见类型转换快速复习" aria-label="Permalink to &quot;常见类型转换快速复习&quot;">&ZeroWidthSpace;</a></h4>
<ul>
<li><code>float-&gt;int</code>
<ul>
<li><code>int(float)</code> 直接舍弃小数</li>
<li><code>math.round(float)</code>小数四舍五入</li>
<li><code>math.floor(float)</code>向下取整</li>
<li><code>math.ceil(float) </code>向上取整</li>
</ul>
</li>
<li><code>float/int-&gt;bool</code> 0为假1为真,虚数必须是0+0i是False，None是False
<img src="./static/Python语言进阶_images_3.png" alt="800"></li>
<li><code>str-&gt;other</code>
<ul>
<li>直接转换会挨个字符转，符合形状的用<code>list(eval(String))</code></li>
<li>所有类型转<code>str(other)</code>都是直接打印</li>
</ul>
</li>
<li><code>dict&lt;-&gt;other</code>
<ul>
<li>set不能转dict，<code>dict.keys()</code>可以获取keyset</li>
<li>str转dict用eval解析或者counter统计字符数量</li>
<li>list转dict使用counter</li>
</ul>
</li>
</ul>
<h3 id="值" tabindex="-1">值 <a class="header-anchor" href="#值" aria-label="Permalink to &quot;值&quot;">&ZeroWidthSpace;</a></h3>
<p><code>a=1</code> python会把1用<code>int</code>封装为对象，然后把a这变量指向了它<br>
<code>优先级顺序为 NOT、AND、OR</code>，<code>_</code>指向上一次运行的表达式的值</p>
<h4 id="对象引用-可变性-gc" tabindex="-1">对象引用,可变性,GC <a class="header-anchor" href="#对象引用-可变性-gc" aria-label="Permalink to &quot;对象引用,可变性,GC&quot;">&ZeroWidthSpace;</a></h4>
<p>java和py中的变量本质不一样，JVM需要对这类型的描述然后申请空间，所以有强制类型检查空间大小也是预定的<br>
python的变量实质上是个指针，指针大小是固定的，所以指向是任意的，而且是首先申请了对象再指上去</p>
<h4 id="两种参数传递-和-不可变对象" tabindex="-1">两种参数传递 和 不可变对象 <a class="header-anchor" href="#两种参数传递-和-不可变对象" aria-label="Permalink to &quot;两种参数传递 和 不可变对象&quot;">&ZeroWidthSpace;</a></h4>
<p>Python根据实际参数的类型不同，分别使用值传递和引用（地址）传递：</p>
<ol>
<li>值传递：适用于实参类型为不可变类型（<strong>字符串、数字、元组</strong>）</li>
<li>引用（地址）传递：适用于实参类型为可变类型（<strong>列表，字典</strong>）</li>
</ol>
<p>区别是，函数参数进行值传递后，若形参变，实参不变；<br>
而函数参数继续引用传递后，若形参变，实参也变</p>
<p>python内部有intern优化机制，将一定范围的小整数小字符串，全局化存储，其他对象再申请小整数直接指向这个整数对象
自定义的类本身也是全剧唯一的对象，所以这时候使用id查看会发现是同一个<br>
当对不可变对象重新赋值的时候，会重新开辟一段内存空间，并将地址引用指向新开辟的空间，原有的内存空间将被回收</p>
<h4 id="gc垃圾回收" tabindex="-1">GC垃圾回收 <a class="header-anchor" href="#gc垃圾回收" aria-label="Permalink to &quot;GC垃圾回收&quot;">&ZeroWidthSpace;</a></h4>
<p>采用引用计数算法引用数量为0的时候回收，引用计数期间会暂停程序，python使用分代的垃圾回收标记-清除法，提高回收效率减少暂停时间。
del本质上调用的是<code>__del__</code>删除的,可以重载比如删除时释放资源<br>
在C中维护了Raphael循环双向链表，保存所有对象，在每个节点内部有ob_ref保存当前对象的引用计数器，频繁的回收和创建会降低效率，使用缓存机制(比如小int和str)优化</p>
<blockquote>
<p>1.标记清除算法：算法分为“标记”和“清除”两个阶段，首先标记所有需要回收的对象，在标记完成后统一回收所有被标记的对象。有两个不足：一是效率问题，标记和清除两个过程的效率都不高；另一个是空间问题，标记清除之后会产生大量不连续的内存碎片，空间碎片太多可能会导致以后在程序运行过程中需要分配较大对象时，无法找到足够的连续内存而不得不提前触发一次垃圾收集动作</p>
<p>2.复制算法：将内存分为两块，每次只使用其中的一块。当这一块内存用完了，就将还存活的对象复制到另一块上，然后再把已使用过的内存空间一次清理掉。这样使得每次都是对一整块内存回收，内存分配时候也不用考虑内存碎片等复杂情况，只要移动堆顶指针，按顺序分配即可，实现简单，运行高效。缺点是一次只能使用一部分内存，会有一些浪费。一般新生代会选择这种算法。</p>
<p>3.标记-整理算法：复制算法存在两个问题，1）会浪费50%的空间 2）如果被使用的内存中所有对象都100%存活的极端情况，就需要有额外的空间进行分配担保，因此老年代一般不能直接选用复制算法。有人提出了另外一种“标记-整理”（Mark-Compact）算法，标记过程仍然与“标记-清除”一样，后续步骤让所有存活的对象都向一端移动，然后直接清理掉端边界以外的内存。</p>
<p>4.分代回收算法：分代回收算法并没有什么新的思想，只是根据对象存活周期的不同将内存划分为几块。比如新生代和老年代，不同代使用不同的回收算法。比如新生代使用复制算法，而老年代使用标记-清除或标记-整理算法</p>
</blockquote>
<p><a href="./深入python.html#^08132d">深入python-&gt;GC</a></p>
<h2 id="深入oop" tabindex="-1">深入OOP <a class="header-anchor" href="#深入oop" aria-label="Permalink to &quot;深入OOP&quot;">&ZeroWidthSpace;</a></h2>
<p>多深才能叫深入呢？<br>
保持谦抑</p>
<h3 id="python中的一切皆对象" tabindex="-1">python中的一切皆对象 <a class="header-anchor" href="#python中的一切皆对象" aria-label="Permalink to &quot;python中的一切皆对象&quot;">&ZeroWidthSpace;</a></h3>
<p>python比java的一切皆对象更加彻底，所以更加灵活，其灵活性就是靠这实现的<br>
java中Object是class的一个实例，但是在py中<strong>类class</strong>也是对象，<strong>函数</strong>，代码和模块也是对象。都可以被动态的赋值，所以才会有python的迷惑操作<a href="https://www.bilibili.com/video/BV1pU4y1m7kf" target="_blank" rel="noreferrer">我写我自己</a><br>
一切都是&quot;一等公民&quot;意味着可以</p>
<ol>
<li>赋值给一个变量</li>
<li>可以添加到集合对象中</li>
<li>可以作为参数传递给函数</li>
<li>可以当做函数的返回值（闭包原理）</li>
</ol>
<p>按照内存模型理解所有的<strong>变量</strong>都是彻底的“引用”，指向实际的内存，变量可以被任意引用<br>
所以python不用实现多态，鸭子就已经很多态了。python支持多继承，封装的注意在基础部分有</p>
<h3 id="类的源头" tabindex="-1">类的源头 <a class="header-anchor" href="#类的源头" aria-label="Permalink to &quot;类的源头&quot;">&ZeroWidthSpace;</a></h3>
<p>梳理一下关系<br>
type是可以创建类的<br>
type类生成了class，class生成了对象，<code>type-&gt;class-&gt;otherObject</code><br>
内置类型基本都是class类型，type套娃两次返回的就是type类<br>
<code>type(type(int)) : &lt;class 'type'&gt;</code></p>
<p><code>object</code>是所有类都要继承的顶层基类，<code>class Class()</code>后面括号不写东西默认继承顶层基类 ps现在加不加都一样但是有些人的代码会有所区分，因为py2中是不一样</p>
<p><img src="./static/Python语言进阶_images_4.png" alt=""></p>
<div class="info custom-block"><p class="custom-block-title">[📝Note] type和object的关系</p>
<p>ype和object的关系
<code>type</code>本身既是类又是对象，<code>type</code>继承自<code>object</code><br>
<code>object.__base__</code>返回是()空,而<code>type(object)</code>是<code>type</code>类型</p>
<p>上图中很奇怪的点，也就是python中有两个神同时纠缠出现</p>
<p><code>type</code>的父类是<code>type</code>实例化的，然而<code>type</code>继承了父类，时间在此时消失了。
从C的角度理解，一开始申请了俩内存块，再开始解释python</p>
<p><code>type</code>此时可以开始构建万物，所有的类，对象，都是他派生的，自己(类)实例化生成自己(类)<br>
从C的角度理解，<code>type</code>的指针指向一个内存块，内存块自行复制一次就可以。</p>
</div>
<h3 id="类属性和实例属性" tabindex="-1">类属性和实例属性 <a class="header-anchor" href="#类属性和实例属性" aria-label="Permalink to &quot;类属性和实例属性&quot;">&ZeroWidthSpace;</a></h3>
<h4 id="变量权限命名规范" tabindex="-1">变量权限命名规范 <a class="header-anchor" href="#变量权限命名规范" aria-label="Permalink to &quot;变量权限命名规范&quot;">&ZeroWidthSpace;</a></h4>
<p><code>_</code>可以访问但不建议<br>
<code>__</code>私有变量（private）不能直接访问<code>__name</code>是因为Python解释器对外把<code>__name</code>变量改成了<code>ClassName._ClassName__name</code><br>
<code>__xxx__</code>是特殊变量。</p>
<h4 id="变量查找顺序" tabindex="-1">变量查找顺序 <a class="header-anchor" href="#变量查找顺序" aria-label="Permalink to &quot;变量查找顺序&quot;">&ZeroWidthSpace;</a></h4>
<p>^5e3db7</p>
<p>大致是 <mark>由下而上查找</mark>
优先查找 <strong>对象</strong> 变量，找不到就向上查找 <strong>类</strong> 变量。<br>
修改 <strong>对象</strong> 的 <strong>类变量</strong> 时不会更改 <strong>类</strong> 的 <strong>类变量</strong> ，只是给对象自己添加了一个 <strong>对象变量</strong> 覆盖了 <strong>类变量</strong> ，所以其他对象和类的 <strong>类变量</strong> 不变</p>
<p>修改 <strong>类变量</strong> 的时候，所有的 <strong>对象</strong> 的 <strong>变量</strong> 都变，因为类变量是共享的<br>
子类修改了类变量时只有子类链条下生效</p>
<h4 id="多继承下搜索" tabindex="-1">多继承下搜索 <a class="header-anchor" href="#多继承下搜索" aria-label="Permalink to &quot;多继承下搜索&quot;">&ZeroWidthSpace;</a></h4>
<p>在单继承这样就够了，但是多继承就寄了。<br>
py的<strong>方法解析顺序</strong>（Method Resolution Order，<strong>MRO</strong>）使用的是C3算法，python2.3前使用的是DFS或BFS，但是这样无法解决菱形继承<br>
C3算法实现了三种重要特性：</p>
<ul>
<li>保持继承<a href="https://link.zhihu.com/?target=https%3A//zh.wikipedia.org/w/index.php%3Ftitle%3D%25E6%258B%2593%25E6%2589%2591%25E5%259B%25BE%26action%3Dedit%26redlink%3D1" target="_blank" rel="noreferrer">拓扑图</a>的一致性。</li>
<li>保证局部优先原则（比如A--&gt;C--&gt;B，那么A读取父类方法，应该优先使用C的方法而不是B的方法）。</li>
<li>保证单调性原则（即子类不改变父类的方法搜索顺序）。</li>
</ul>
<p>类的<code>__mro__</code>属性或<code>mro()</code>方法可以直接查看搜索顺序，C3会按照多继承的参数顺序进行搜索。三角继承会直接报错无法进行mro
<img src="./static/Python语言进阶_images_5.png" alt=""></p>
<h3 id="构造析构" tabindex="-1">构造析构 <a class="header-anchor" href="#构造析构" aria-label="Permalink to &quot;构造析构&quot;">&ZeroWidthSpace;</a></h3>
<h4 id="实例方法" tabindex="-1">实例方法 <a class="header-anchor" href="#实例方法" aria-label="Permalink to &quot;实例方法&quot;">&ZeroWidthSpace;</a></h4>
<p>一般的方法都是实例方法，只针对实例进行操作，会传入self，<code>cls.func()</code>调用的时候，python会自动转成<code>func(cls)</code></p>
<h4 id="静态方法" tabindex="-1">静态方法 <a class="header-anchor" href="#静态方法" aria-label="Permalink to &quot;静态方法&quot;">&ZeroWidthSpace;</a></h4>
<p>对象构造前处理输入，对象还没有构造出来，每次都要处理不是很规范<br>
使用装饰器<code>@staticmethod</code><br>
在类中定义方法，不需要传入self，可以通过类直接调用，好处是将命名空间和处理拿到了类里面去，可以直接返回对象。<br>
坏处就是类名是硬编码，修改类名的时候需要去修改，如果只是处理和判断是否规范，不需要返回对象，就可以用静态方法<br>
所以在这种动态的构造需求下，就需要用类方法<code>@classmethod</code><br>
第一个参数为cls，代表类本身。</p>
<details class="details custom-block"><summary>Click to see more</summary>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Dates</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 假设要拿到时间  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __init__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self, yy, mm, dd):  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.yy </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> yy  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.mm </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> mm  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.dd </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> dd  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __str__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self):  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        return</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">{yy}</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">年,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">{mm}</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">月,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">{dd}</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">日"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.format(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">yy</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.yy, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">mm</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.mm, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">dd</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.dd)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    @</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">staticmethod</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  # 静态方法装饰器  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> test_string</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(string):  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 不用传入self等  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        # l = string.split("-")  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        # return Dates(l[0], l[1], l[2]) # 硬编码创建  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        try</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            l </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> string.split(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"-"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> l:  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">                int</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(i)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> True</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        except</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> Exception</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> as</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> e:  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> False</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    @</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">classmethod</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  # 类方法装饰器  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> create_from_string</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(cls, string):  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 第一个参数为cls  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        l </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> string.split(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"-"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> cls</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(l[</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">], l[</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">], l[</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">])  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 动态创建  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">d1 </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Dates(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">21</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(d1)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">check </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Dates.test_string(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"21-2-3"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">d2 </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Dates.create_from_string(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"21-2-4"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(d2, check)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"------------"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> MordenDate</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Dates</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">): </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 是可以继承的  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    morden </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    @</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">staticmethod</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  # 静态方法装饰器  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> test_string</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(string):  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 继承之后  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"I am a ModernDate"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        try</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            l </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> string.split(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"-"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> l:  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">                int</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(i)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> True</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        except</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> Exception</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> as</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> e:  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> False</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">md1 </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> MordenDate(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">22</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">5</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(md1)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">mcheck </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> MordenDate.test_string(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"22-5-8"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">md2 </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> MordenDate.create_from_string(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"22-5-8"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">excheck</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">isinstance</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(md2,MordenDate) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 继承后是否动态创建  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(md2,excheck, mcheck)</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br><span class="line-number">50</span><br><span class="line-number">51</span><br><span class="line-number">52</span><br><span class="line-number">53</span><br><span class="line-number">54</span><br><span class="line-number">55</span><br><span class="line-number">56</span><br><span class="line-number">57</span><br></div></div><p>运行结果</p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>21年,2月,3日</span></span>
<span class="line"><span>21年,2月,4日 True</span></span>
<span class="line"><span>------------</span></span>
<span class="line"><span>22年,5月,3日</span></span>
<span class="line"><span>I am a ModernDate</span></span>
<span class="line"><span>22年,5月,8日 True True</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br></div></div></details>
<h4 id="new-和-init" tabindex="-1"><code>__new__</code>和<code>__init__</code> <a class="header-anchor" href="#new-和-init" aria-label="Permalink to &quot;`__new__`和`__init__`&quot;">&ZeroWidthSpace;</a></h4>
<p>^e46b78</p>
<p><code>__new__</code>的第一个参数是类本身，而<code>__init__</code>第一个参数传入的是对象本身，new是管对象生成前的动作，init是完善对象本身<br>
new会通过可变参数提前获取到初始化传入的属性，必须return<code>super().__new__(cls)</code>回去，不然没法调用init继续创建</p>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> A</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">():  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __new__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(cls, </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">args, </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">**</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">kwargs):  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 第一个参数指向的是类本身  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"new..."</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> super</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">().</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">__new__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">cls</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 注意返回什么  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __init__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self,name):  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Initializing..."</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.name</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">name  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">a</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">A(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">name</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"hhh"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#----结果----</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">new</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">...</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Initializing</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">...</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br></div></div><p>主要是在元类编程中用的多</p>
<h4 id="析构函数" tabindex="-1">析构函数 <a class="header-anchor" href="#析构函数" aria-label="Permalink to &quot;析构函数&quot;">&ZeroWidthSpace;</a></h4>
<ul>
<li>del本质上调用的是<code>__del__</code>删除的
<ul>
<li>可以重载比如删除时释放资源</li>
</ul>
</li>
</ul>
<h4 id="定制属性" tabindex="-1">定制属性 <a class="header-anchor" href="#定制属性" aria-label="Permalink to &quot;定制属性&quot;">&ZeroWidthSpace;</a></h4>
<p>定制属性使用slots ^144b67</p>
<p>类在动态添加属性的时候，给class绑定方法后，所有实例均可调用，我们不想让他乱添加，可以用<code>__slots__</code>指定，翻译过来是插槽很好理解</p>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Student</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    __slots__</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'name'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'age'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">s</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Student()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">s.name</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"aba"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(s.name)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">s.value</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"ss"</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#----结果----</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">aba</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Traceback (most recent call last):</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  File </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"slots.py"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, line </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">7</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> &#x3C;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">module</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    s.value</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"ss"</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">AttributeError</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'Student'</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> object</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> has no attribute </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'value'</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br></div></div><h3 id="自省-反射-机制" tabindex="-1">自省(反射)机制 <a class="header-anchor" href="#自省-反射-机制" aria-label="Permalink to &quot;自省(反射)机制&quot;">&ZeroWidthSpace;</a></h3>
<p>反射的概念是由Smith在1982年首次提出的，主要是指程序可以访问、检测和修改它本身状态或行为的一种能力。
<a href="#^5e3db7">变量查找顺序</a><br>
使用<code>obj.__dict__</code>查看 <mark>对象</mark>所有的属性,此时发现类和父类中的属性都没有出现，因为他是之查看这个对象的。<br>
查看 <strong>类对象</strong> 的属性，同时可以当字典取出属性<br>
之所以能调用就是MRO做的<br>
使用<code>__dict__</code>可以查看甚至修改已有的属性添加新的， <mark>只有对象实例才能添加</mark>，给类添加被解释器阻止了<br>
使用<code>dir(obj)</code>可以列出所有属性，包括类系统内建的，但是没有值只有名称<br>
一些内置类型没有<code>__dict__</code>但是都可以使用<code>dir()</code>(会寻找包括从父类中继承的属性)</p>
<details class="details custom-block"><summary>Click to see more</summary>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 私有变量  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> A</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">():  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    a</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    pass</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> B</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">A</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">):  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    """ # 注意'__doc__' 属性</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    doc    </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    """</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    b</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __init__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self,x):  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.x</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">x  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">b</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">B(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">5</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(b.</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">__dict__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">\n</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,B.</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">__dict__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">\n</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">b.</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">__dict__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"add"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"add success"</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  # 对象添加属性</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(b.</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">__dict__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">\n</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">dir</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(B),)</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br></div></div><p>运行结果</p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>{'x': 5} </span></span>
<span class="line"><span> {'__module__': '__main__', '__doc__': '\n    doc\n    ', 'b': 2, '__init__': &#x3C;function B.__init__ at 0x10e5e0820>}  </span></span>
<span class="line"><span></span></span>
<span class="line"><span>{'x': 5, 'add': 'add success'} </span></span>
<span class="line"><span> ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'a', 'b']</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br></div></div></details>
<h4 id="super-的用法" tabindex="-1">super()的用法 <a class="header-anchor" href="#super-的用法" aria-label="Permalink to &quot;super()的用法&quot;">&ZeroWidthSpace;</a></h4>
<p>在继承中，如果重定义某方法，该方法会覆盖父类的同名方法，但有时我们希望能同时实现父类的功能，这时，我们就需要调用父类的方法了。<br>
调用父类同名方法有两种方式：</p>
<ol>
<li>调用未绑定的父类方法
<ul>
<li>多继承时会导致多次调用方法</li>
</ul>
</li>
<li>使用super函数来调用
<ul>
<li>最常见的就是使用<code>super().__init__()</code>
Python 3 可以使用直接使用 <code>super().xxx</code>代替 <code>super(Class, self).xxx</code><br>
<code>super()</code>不是直接调用父类，而是按照MRO顺序进行构造</li>
</ul>
</li>
</ol>
<h3 id="mixin混合模式" tabindex="-1">Mixin混合模式 <a class="header-anchor" href="#mixin混合模式" aria-label="Permalink to &quot;Mixin混合模式&quot;">&ZeroWidthSpace;</a></h3>
<ul>
<li>混合优于继承</li>
<li>Mixin功能单一
<ul>
<li>Mixin只实现了某些单一的功能，可以利用继承来组合这些功能</li>
<li>联想魔法函数基于协议的编程，oop中就使用mixin</li>
</ul>
</li>
<li>不和基类关联，可以任意组合</li>
<li>在Mixin中不要使用super</li>
<li>混入类不能直接被实例化使用。</li>
<li>混入类没有自己的状态信息，也就是说它们并没有定义 <code>__init__()</code> 方法，并且没有实例属性。</li>
</ul>
<p>主要是掌握编程思想，cookbook里有<a href="https://python3-cookbook.readthedocs.io/zh_CN/latest/c08/p18_extending_classes_with_mixins.html" target="_blank" rel="noreferrer">这一章</a>的示例。</p>
<h3 id="抽象基类-掌握思想" tabindex="-1">抽象基类(掌握思想) <a class="header-anchor" href="#抽象基类-掌握思想" aria-label="Permalink to &quot;抽象基类(掌握思想)&quot;">&ZeroWidthSpace;</a></h3>
<p>abc抽象基类(abstract base class)是无法实例化的，继承抽象基类必须要实现基类规定的某些方法<br>
所有的抽象基类的metaclass参数都必须是<code>metaclass=ABCMeta</code><br>
两种情况下需要抽象基类</p>
<ul>
<li>一是判定能不能使用某些方法，比如是否实现了len</li>
<li>二是规定子类必须实现某些方法。<br>
这样在实现某些功能的替代和扩展的时候，就无需修改原来的代码，直接继承并且实现预留的接口就可以了<br>
引入内置包<code>abc</code></li>
</ul>
<details class="details custom-block"><summary>Click to see more</summary>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 假设我们继承Cache实现RedisCache  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> abc</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Cache</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">object</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">metaclass</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">abc</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">ABCMeta</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">):  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    @abc.abstractmethod</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> get</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self):  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        pass</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    @abc.abstractmethod</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> set</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self):  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        pass</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> RedisCache</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Cache</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">):  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    pass</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">rdc </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> RedisCache() </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 实例化的时候没有实现这俩方法就报错</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br></div></div><p>运行结果</p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>Traceback (most recent call last):</span></span>
<span class="line"><span>  File "/Users/jack/code/py/AdvancedPython/main.py", line 69, in &#x3C;module></span></span>
<span class="line"><span>    rdc = RedisCache()</span></span>
<span class="line"><span>TypeError: Can't instantiate abstract class RedisCache with abstract methods get, set</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br></div></div></details>
<p>在判断类型的时候，比如判断<code>isinstance(obj,Sized)</code> 实际上是判断了obj是否实现<code>__len__</code> 使用的是<code>__subclasshook__(cls, C)</code><br>
摘一下<code>collection/abc.py Sized</code>源码</p>
<details class="details custom-block"><summary>Click to see more</summary>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># collections/abc.py中的源码</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Sized</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">metaclass</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">ABCMeta</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">):</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    __slots__</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> ()</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    @abstractmethod</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __len__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self):</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 0</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    @</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">classmethod</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> __subclasshook__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(cls, C): </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 注意这个方法</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        if</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> cls</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> is</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Sized:</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> _check_methods(C, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"__len__"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> NotImplemented</span></span>
<span class="line"></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 示例代码</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> collections.abc </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Sized  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">isinstance</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(c, Sized) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># c的类实现了__len__ 所以返回为True</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br></div></div><p>运行结果</p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>True</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div></details>
<p>抽象基类使用了元类来进类型检查，collections.abc里面都使用了metaclass<br>
实际上内置的常用类型也不是使用抽象基类实现的，Cpython实现的更加精妙</p>
<div class="tip custom-block"><p class="custom-block-title">[💡Tip]</p>
<p>更推荐使用Mixin和鸭子类型实现功能，<strong>组合优于继承</strong><br>
不实现就抛出错误实现类似接口的功能，更加灵活</p>
</div>
<h2 id="魔法函数" tabindex="-1">魔法函数 <a class="header-anchor" href="#魔法函数" aria-label="Permalink to &quot;魔法函数&quot;">&ZeroWidthSpace;</a></h2>
<p>在类中<code>__func__()</code>类似的函数就是魔法函数，一般不需要自定义，系统提前定义好自己重载即可，可以用来定制特性.
<em><strong>魔法函数不是object的方法</strong></em>,不是继承来的<br>
python的语法和内置函数会识别自定义对象里面的魔法函数，隐式调用，通过魔法函数定义，可以使对象具有某些特性，&quot;成为&quot;某些类型，实际上不是这些类型，是鸭子类型的功能，区别于java中需要继承特定的类或者接口</p>
<p>这种做法叫做 <mark>协议</mark>，尽量遵守协议编程</p>
<h3 id="实现适应len和for" tabindex="-1">实现适应len和for <a class="header-anchor" href="#实现适应len和for" aria-label="Permalink to &quot;实现适应len和for&quot;">&ZeroWidthSpace;</a></h3>
<p><code>__len__(self)</code>会被内置函数<code>len()</code>调用，要求返回一个整数<br>
实际上len内置数据结构的时候list set这种，直接读取cpython维护在内存中记录，很快就返回，不会傻乎乎去数长度。所以尽量使用内部定义的东西。</p>
<p><code>__getitem__(self,item)</code>,使用for的时候，解释器先找<code>__iter__()</code>找不到就会寻找这个函数，从1开始取直到<code>StopIteration</code><br>
实际上通过这个函数成为了序列类型，就可切片了。</p>
<details class="details custom-block"><summary>Click to see more</summary>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Company</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">object</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">):  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __init__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self, employee_list):  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.employee </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> employee_list  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __getitem__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self, item):  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        # 这里可以放一些检查代码，随你了  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.employee[item]  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __len__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self):  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 10</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">c </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Company([</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"1"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"2"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"3"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">])  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> c:  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(i)  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"长度是"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">len</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(c))</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br></div></div><p>运行结果</p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>1</span></span>
<span class="line"><span>2</span></span>
<span class="line"><span>3</span></span>
<span class="line"><span>长度是 10</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br></div></div></details>
<h3 id="控制打印对象的输出" tabindex="-1">控制打印对象的输出 <a class="header-anchor" href="#控制打印对象的输出" aria-label="Permalink to &quot;控制打印对象的输出&quot;">&ZeroWidthSpace;</a></h3>
<p><code>__repr__()</code>在开发模式比如jupyter直接调用显示的<br>
<code>__str__()</code>print它显示啥</p>
<details class="details custom-block"><summary>Click to see more</summary>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Demo2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">object</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">):  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __str__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self):  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        return</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "我是🦈"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __repr__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self):  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        return</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "你猜我是😦个"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">d </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Demo2()  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(d)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">d</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br></div></div><p>运行结果</p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>我是🦈</span></span>
<span class="line"><span>你猜我是😦个</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br></div></div></details>
<h3 id="数学运算" tabindex="-1">数学运算 <a class="header-anchor" href="#数学运算" aria-label="Permalink to &quot;数学运算&quot;">&ZeroWidthSpace;</a></h3>
<p>不是重点，需要啥现查自己试试。<br>
<code>__ads__()</code>，由abs()调用<br>
<code>__add__()</code>,+调用</p>
<details class="details custom-block"><summary>Click to see more</summary>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Vector</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">object</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">):  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 坐标相加  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __init__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self, x, y):  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.x </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> x  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.y </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> y  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __str__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self):  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        return</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">{0}</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">{1}</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.format(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.x, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.y)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __add__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self, other):  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Vector(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.x </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> other.x, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.y </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> other.y)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __abs__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self):  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Vector(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">abs</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.x), </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">abs</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.y))  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">v1 </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Vector(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">v2 </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Vector(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">4</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">v2 </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> abs</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(v2)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">v1 </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> v1 </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> v2  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(v1,v2)</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br></div></div><p>运行结果</p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>4,6 3,4</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div></details>
<h3 id="实现with语句和简化" tabindex="-1">实现with语句和简化 <a class="header-anchor" href="#实现with语句和简化" aria-label="Permalink to &quot;实现with语句和简化&quot;">&ZeroWidthSpace;</a></h3>
<h4 id="try-finally语句" tabindex="-1">try-finally语句 <a class="header-anchor" href="#try-finally语句" aria-label="Permalink to &quot;try-finally语句&quot;">&ZeroWidthSpace;</a></h4>
<p>正常的finally是用作资源释放的，比如写文件数据库发生错误，在finally中close释放资源。<br>
在函数中try-finally多个return的时候，注意顺序</p>
<details class="details custom-block"><summary>Click to see more</summary>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> fun</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">():  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    try</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"rise"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)   </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        raise</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> KeyError</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  # 1 出错了</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">   # 不执行</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    except</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> KeyError</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> as</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> e:  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"catch"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 捕获执行</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 2</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  # 压栈</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    else</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"other Error"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    finally</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"finally"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 必执行</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 4</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  # 压栈</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(fun()) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 从栈顶取一个，所以最后fun返回是4，如果finally没返回语句，那么栈顶是2，返回的就是2</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br></div></div><p>运行结果</p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>rise</span></span>
<span class="line"><span>catch</span></span>
<span class="line"><span>finally</span></span>
<span class="line"><span>4 # 返回值</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br></div></div></details>
<h4 id="实现with" tabindex="-1">实现with <a class="header-anchor" href="#实现with" aria-label="Permalink to &quot;实现with&quot;">&ZeroWidthSpace;</a></h4>
<p>上下文管理器就是简化了try-finally整出来的<br>
实现了上下文管理，类似于with-open<br>
实现<code>__enter__(self)</code>最后要返回self<br>
同时实现<code>__exit__(self, exc_type, exc_val, exc_tb)</code> 可以不返回</p>
<details class="details custom-block"><summary>Click to see more</summary>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> ContextManager</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __enter__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self):  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"开始"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __exit__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self, exc_type, exc_val, exc_tb):  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"退出"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> func</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self):  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"功能代码"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">with</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> ContextManager() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">as</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> cm:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    cm.func()</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br></div></div><p>运行结果</p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>开始</span></span>
<span class="line"><span>功能代码</span></span>
<span class="line"><span>退出</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br></div></div></details>
<h4 id="contextlib简化with" tabindex="-1">contextlib简化with <a class="header-anchor" href="#contextlib简化with" aria-label="Permalink to &quot;contextlib简化with&quot;">&ZeroWidthSpace;</a></h4>
<p>python内置了装饰器  <code>@contextlib.contextmanager</code>可以直接简化这东西<br>
被装饰函数中需要含有一个<code>yield</code>，<code>yield</code>之前的是<code>__enter__</code>的处理，之后是<code>__exit__</code>的处理<br>
使用了yeild生成器，后面会写到，这里就有样学样yield空字典就行</p>
<details class="details custom-block"><summary>Click to see more</summary>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> contextlib </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> contextmanager  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">@contextmanager</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> ContextManager</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">():  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"开始"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    yield</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {}  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"退出"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">with</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> ContextManager() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">as</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> cm:  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"功能代码"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br></div></div><p>运行结果</p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>开始</span></span>
<span class="line"><span>功能代码</span></span>
<span class="line"><span>退出</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br></div></div></details>
<h3 id="属性操作三剑客" tabindex="-1">属性操作三剑客 <a class="header-anchor" href="#属性操作三剑客" aria-label="Permalink to &quot;属性操作三剑客&quot;">&ZeroWidthSpace;</a></h3>
<p><code>__ getattribute__</code>方法、<code>__setattr__方法、</code> <code>__delattr__方法</code><br>
<a href="#^25cbec">元类编程-&gt;</a></p>
<ul>
<li><code>setattr(obj, k, v)</code>: obj.k=v</li>
<li><code>getattr(obj, k)</code>: obj.k</li>
<li><code>hasattr(obj,k)</code>:返回bool，就是看看有没有，也可以看字典的，使用过捕获getattr错误实现的</li>
</ul>
<h3 id="构造析构-1" tabindex="-1">构造析构 <a class="header-anchor" href="#构造析构-1" aria-label="Permalink to &quot;构造析构&quot;">&ZeroWidthSpace;</a></h3>
<p><code>__new__</code>和<code>__init__</code><br>
在thread里面已经写了init方法，直接<code>super().__init__(para)</code>就可以构建了<br>
<a href="#^e46b78">深入OOP-&gt;构造析构-&gt;</a></p>
<h3 id="定制类属性" tabindex="-1">定制类属性 <a class="header-anchor" href="#定制类属性" aria-label="Permalink to &quot;定制类属性&quot;">&ZeroWidthSpace;</a></h3>
<p><code>__slots__</code><br>
<a href="#^144b67">深入OOP-&gt;构造析构-&gt;</a></p>
<h3 id="迭代器和生成器" tabindex="-1">迭代器和生成器 <a class="header-anchor" href="#迭代器和生成器" aria-label="Permalink to &quot;迭代器和生成器&quot;">&ZeroWidthSpace;</a></h3>
<p><a href="#^a159bd">迭代器和生成器-&gt;</a></p>
<h3 id="零散的功能" tabindex="-1">零散的功能 <a class="header-anchor" href="#零散的功能" aria-label="Permalink to &quot;零散的功能&quot;">&ZeroWidthSpace;</a></h3>
<ul>
<li>实现了<code>__contains__</code>可以in判断,找不到就找<code>__getitem__</code>，所以实现了这也可以</li>
<li>反转实现的是<code>__reversed__</code></li>
<li>类属性<code>cls.__base__</code>查看一个类的父类</li>
<li>使用<code>obj.__dict__</code>查看对象所有的属性</li>
<li>使用<code>cls.__init__.__default__</code>查看默认参数</li>
<li><code>BOOL: hasattr(class,&quot;funcName&quot;)</code>判断是否有这个属性</li>
<li><code>getattr(obj,k)</code>等价于<code>obj.k</code></li>
<li>函数和类的<code>__name__</code>属性，可以拿到名字</li>
<li><code>__class__</code>获取类型</li>
<li>只要定义类型的时候，实现<code>__call__</code>函数，这个类型就成为可调用的。换句话说相当于重载了括号运算符。</li>
<li>函数注解的信息，保存在 <code>__annotations__</code> 属性中可以来调用。</li>
</ul>
<div class="info custom-block"><p class="custom-block-title">[ℹ️Info]</p>
<p>其实魔法函数和类内置属性很多，这里整理一下他讲到的和我自己实验到的<br>
剩下的去看文档搜吧</p>
</div>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 根据第一个列表过滤第二个列表</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">filter_data </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> [x </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> x </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> list2 </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">if</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">              all</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(y  </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">not</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> in</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> x </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> y </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> list1)]</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br></div></div><h2 id="元类编程" tabindex="-1">元类编程 <a class="header-anchor" href="#元类编程" aria-label="Permalink to &quot;元类编程&quot;">&ZeroWidthSpace;</a></h2>
<p>控制类实例化的过程</p>
<h3 id="计算属性-property" tabindex="-1">计算属性@property <a class="header-anchor" href="#计算属性-property" aria-label="Permalink to &quot;计算属性@property&quot;">&ZeroWidthSpace;</a></h3>
<p>使用<code>@property</code>装饰器将函数包装成动态变量，更容易调用</p>
<details class="details custom-block"><summary>Click to see more</summary>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> datetime </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> date, datetime  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> User</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">():  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __init__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self, name, birth):  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.name </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> name  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.birth </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> birth  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">._age </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> old_get_age</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self):  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 老式代码需要调用函数比较麻烦  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> datetime.now().year </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.birth.year  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    @</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">property</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> age</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self):  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 装饰之后函数名就是属性名直接调用  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">._age  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    @age.setter</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  # set方法  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> age</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self, value):  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">._age </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> value  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">user1 </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> User(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"a"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, date(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">year</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1988</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">month</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">5</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">day</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">25</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">))  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">user1.age </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 2</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  # 直接设置  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(user1.old_get_age(), user1.age)</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br></div></div><p>运行结果</p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>34 2</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div></details>
<h3 id="属性操作三剑客-1" tabindex="-1">属性操作三剑客 <a class="header-anchor" href="#属性操作三剑客-1" aria-label="Permalink to &quot;属性操作三剑客&quot;">&ZeroWidthSpace;</a></h3>
<p><code>__getattr__</code> 尝试获取不存在的属性的时候，如果定义了此方法，就不会报错会运行这个方法,这个若是运行了那下面那个必备运行<br>
<code>__getattribute__</code> 这个只要找就会进入，一般不建议重载，很容易崩，只要重写必然会无限递归，为了避免无限递归，应该把获取属性的方法指向一个更高的超类，例如<code>object</code><br>
<code>return super().__getattribute__(item)</code></p>
<p>Python中属性操作捕获的三剑客：<code>__getattribute__</code>方法、<code>__setattr__</code>方法 <code>__delattr__</code>方法 ^25cbec</p>
<details class="details custom-block"><summary>Click to see more</summary>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> User1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">():  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __init__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self, name):  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.name </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> name  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __getattr__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self, item): </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 找不到才进来  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">type</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(item))  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        return</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "get </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">{0}</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> error"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.format(item)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __getattribute__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self, item): </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 只要找就进来  这里有BUG</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"seeking attr"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> item  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">user1 </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> User1(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"a"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(user1.name)</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br></div></div><p>运行结果</p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>seeking attr</span></span>
<span class="line"><span>&#x3C;class 'str'></span></span>
<span class="line"><span>a get age error</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br></div></div></details>
<h3 id="属性描述符descriptor" tabindex="-1">属性描述符descriptor <a class="header-anchor" href="#属性描述符descriptor" aria-label="Permalink to &quot;属性描述符descriptor&quot;">&ZeroWidthSpace;</a></h3>
<p>这里有一篇<a href="https://www.waynerv.com/posts/python-descriptor-in-detail/" target="_blank" rel="noreferrer">别人的</a><br>
当我们的类有很多属性，都需要写检查方法的时候，一个属性一套检查方法代码重复度很高，此时可以定义一个类专门进行属性检查处理等，实现<code>__get__</code> <code>__set__</code> <code>__delete__</code>中的任意一个，这个类就成了属性描述符<br>
和django里面module的逻辑是一致的，但是django写的更加动态和灵活，也是大部分ORM的实现原理</p>
<details class="details custom-block"><summary>Click to see more</summary>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> numbers  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> IntField</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">():  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __get__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self, instance, owner):  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"getting。。。"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.value </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 获取的时候就返回存储的值  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __set__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self, instance, value):  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"setting。。。"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        if</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> not</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> isinstance</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(value,numbers.Integral):  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            raise</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> ValueError</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"int is needed"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        #注意检查完了不要赋给instance,  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        #因为instance就是User对象，又回来了会死循环  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.value</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">value  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __delete__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self, instance):  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"delete。。。"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        pass</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> User</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">():  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    age</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">IntField()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">user</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">User()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">user.age</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">4</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(user.age)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">del</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(user.age)</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br></div></div><p>运行结果</p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>setting。。。</span></span>
<span class="line"><span>getting。。。</span></span>
<span class="line"><span>4</span></span>
<span class="line"><span>delete。。。</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br></div></div></details>
<p>根据所实现的协议方法不同，描述符又可分为两类：</p>
<ul>
<li>若实现了 <code>__set__()</code> 或 <code>__delete__()</code> 任一方法，该描述符是一个数据描述符（<code>data descriptor</code>）。</li>
<li>若仅实现 <code>__get__()</code> 方法，该描述符是一个非数据描述符（<code>non-data descriptor</code>）。</li>
</ul>
<p>两者的在表现行为上存在差异：</p>
<ul>
<li>数据描述符总是会覆盖实例字典 <code>__dict__</code> 中的属性。
<ul>
<li>定义实例 <code>__dict__[attr]</code>之后调用 <code>__dict__[attr]</code>或<code>obj.attr</code>还是会使用描述符</li>
<li>使用了数据描述符会被存储在类的数据描述符中，不进入实例的 <code>__dict__</code> 属性列表</li>
</ul>
</li>
<li>而非数据描述可能会被实例字典 <code>__dict__</code> 中定义的属性所覆盖。
<ul>
<li>优先级不如类高，注意下面说明顺序</li>
</ul>
</li>
</ul>
<div class="info custom-block"><p class="custom-block-title">[ℹ️Info] 描述符查找过程</p>
<p>述符查找过程</p>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">user.age等价于getattr(user,’age’)</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">而对于描述符__get__的调用是发生在__getattribute__内部的。</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">调用顺序</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">调用__getattribute__</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> 类定义了__getattr__方法 </span><span style="--shiki-light:#B31D28;--shiki-light-font-style:italic;--shiki-dark:#FDAEB7;--shiki-dark-font-style:italic">&#x26;&#x26;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> 调用抛出 </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">AttributeError</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> :</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    调用__getattr__</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">user </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> User(), 那么user.age 顺序如下：</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> “age”是出现在User或其基类的__dict__中 </span><span style="--shiki-light:#B31D28;--shiki-light-font-style:italic;--shiki-dark:#FDAEB7;--shiki-dark-font-style:italic">&#x26;&#x26;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> age是data descriptor : </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    调用其__get__方法</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">elif</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> “age”出现在user对象的__dict__中 :</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    直接返回 obj.</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">__dict__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[‘age’]</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">elif</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> “age”出现在User或其基类的__dict__中 : </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> “age”是non</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">data descriptor : </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        那么调用其__get__方法</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    else</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> :返回 __dict__[‘age’]</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">elif</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> User有__getattr__方法 : </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    调用__getattr__方法</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">else</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> : 抛出AttributeError</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br></div></div></div>
<h3 id="元类metaclass" tabindex="-1">元类metaclass <a class="header-anchor" href="#元类metaclass" aria-label="Permalink to &quot;元类metaclass&quot;">&ZeroWidthSpace;</a></h3>
<p>把class定义语句放在函数内，根据传入的字符串不同返回不同的类引用，然后创建对应的实例，这种动态创建实例的机制在java这种静态语言中很难实现。<br>
但是python做的不止于此，还能继续动态</p>
<p><code>type(name ,base,dict)</code>类名，基类没有就空tuple，属性没有就空字典<br>
这种创建类的类就是元类，<code>type</code>是一种元类，继承type之后就可以创建一个特殊的类(其他都继承自object): 元类，利用创建类时的<strong>metaclass</strong>参数就可以控制类的生成过程，可以注入很多东西</p>
<details class="details custom-block"><summary>type生成</summary>
<p>ype生成</p>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> BaseClass</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> echo</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self):  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"I am BaseClass"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> boundFun</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self,string): </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 注意绑定的时候第一个参数默认传入对象  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.att)  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(string)  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#使用type创建了一个类  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">T</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">type</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"T"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,(BaseClass,),{</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"bound"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:boundFun,</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"att"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"dynamic att"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">})  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">t</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">T()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">t.echo()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">t.bound(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"para fun"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br></div></div><p>运行结果</p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>I am BaseClass</span></span>
<span class="line"><span>dynamic att</span></span>
<span class="line"><span>para fun</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br></div></div></details>
<p>类的生成过程<br>
metaclass可以隐式地继承到子类，但子类自己却感觉不到<br>
创建类时会首先寻找metaclass，，通过metaclass创建，类找不到就去父类找，先找到那个就使用哪个metaclass，都找不到就会去用type创建<br>
抽象基类使用了元类来进类型检查，collections.abc里面都使用了metaclass</p>
<details class="details custom-block"><summary>Click to see more</summary>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> MetaClass</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">type</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">):  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __new__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(cls, </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">args, </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">**</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">kwargs):  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"new..."</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'this is args : '</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,args) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#打印一下  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'this is kwargs : '</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,kwargs)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        kwargs</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{} </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 把他置为{}因为原先就是空，如果不置空x传进去报错  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> super</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">().</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">__new__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">cls</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">args, </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">**</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">kwargs)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> M</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">metaclass</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">MetaClass</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">x</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">5</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">): </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 传入了额外的x=5  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __init__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self,name):  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.name</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">name  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">m</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">M(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">name</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"ha"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(m.name)</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br></div></div><p>运行结果</p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>new...</span></span>
<span class="line"><span>this is args :  ('M', (), {'__module__': '__main__', '__qualname__': 'M', '__init__': &#x3C;function M.__init__ at 0x10a7f7280>})</span></span>
<span class="line"><span>this is kwargs :  {'x': 5}</span></span>
<span class="line"><span>ha</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br></div></div></details>
<p>new的参数arg<code>def __new__(cls,  name类名, bases父类, attrs属性们, **kwargs):</code></p>
<h3 id="example-1元类实现orm" tabindex="-1">example-1元类实现ORM <a class="header-anchor" href="#example-1元类实现orm" aria-label="Permalink to &quot;example-1元类实现ORM&quot;">&ZeroWidthSpace;</a></h3>
<p>利用元类自己写个ORM<br>
就不连SQL了，打印一下就好<br>
要求</p>
<ol>
<li>使用数据描述符来定义字段</li>
<li>字段要指明
<ul>
<li>字段最大长度(检查)</li>
<li>插入数据库的字段，不指明就默认变量名</li>
<li>类型，最大最小值(检查)</li>
</ul>
</li>
<li>使用内部类指明表，注释等其他信息</li>
<li>save即获取格式化的所有表，字段的信息，并打印</li>
</ol>
<details class="details custom-block"><summary>元类实现ORM</summary>
<p>类实现ORM</p>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> numbers  </span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> check_args</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(value, types):  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 检查参数的类型  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    if</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> isinstance</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(value, types):  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> value  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    else</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        raise</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> TypeError</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"need a </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%s</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> Type"</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> %</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> types.</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">__name__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Field</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 使用这个来判断类型是否正确  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    pass</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> IntegerField</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Field</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">):  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __init__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self, min, max):  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.min </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> check_args(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">min</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, numbers.Integral)  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.max </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> check_args(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">max</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, numbers.Integral)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __get__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self, instance, owner):  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.value  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __set__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self, instance, value):  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        value </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> check_args(value, numbers.Integral)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        if</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.min </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x3C;=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> value </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x3C;=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.max:  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">            self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.value </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> value  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        else</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            raise</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> ValueError</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"number is illagel"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __delete__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self, instance):  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"delete attribute"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        pass</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> StringField</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Field</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">):  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __init__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self, max_size</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">100</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">):  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.max_size </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> check_args(max_size, numbers.Integral)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __get__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self, instance, owner):  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># instance 传的是module  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.value  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __set__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self, instance, value):  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        value </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> check_args(value, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">str</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 类型检查  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        if</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> len</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(value) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">>=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.max_size:  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            raise</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> ValueError</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"value too large"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        else</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">            self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.value </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> value  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __delete__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self, instance):  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"delete attribute"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        pass</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> ModuleMetaClass</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">type</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">):  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __new__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(cls, name, bases, attrs, </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">**</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">kwargs):  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    #元类中可以获得属性，放到attr中带到基类中</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> name </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">==</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 'BaseModule'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 如果是Module基类原路返回  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> super</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">().</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">__new__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">cls</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, name, bases, attrs, </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">**</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">kwargs)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        fields </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {}  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 表的字段信息  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        # print(name, bases, attrs)  # 看一看属性都藏在哪</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> k, v </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> attrs.items():  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 找  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">            # print(k)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            if</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> isinstance</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(v, Field):  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 如果是Field类型就添加进这个表属性里面  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">                fields[k] </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> v  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        # print(fields)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        table </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {}  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 表的信息  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        meta </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> attrs.get(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Meta"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">None</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 是否定义了meta  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> meta </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">is</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> not</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> None</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            attrs[</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"table_name"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">] </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> meta.table_name  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 定义了meta就用meta的表名  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        else</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            attrs[</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"table_name"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">] </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> name.lower()  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 没定义就用类名小写  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        attrs[</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"fields"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">] </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> fields  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        del</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> attrs[</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Meta"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 删除Meta  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> super</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">().</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">__new__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">cls</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, name, bases, attrs, </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">**</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">kwargs)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> BaseModule</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">metaclass</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">ModuleMetaClass</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">):  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __init__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self, </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">args, </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">**</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">kwargs):  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> key, value </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> kwargs.items():  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 在debug里面看到的还是正常的属性，但是已经可以自己检查数据类型了  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">            setattr</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, key, value)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> super</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">().</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">__init__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> save</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self):  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        columns_ </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> []  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        values_ </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> []  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> k, v </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.fields.items():  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            columns_.append(k)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            values_.append(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">str</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">getattr</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,k))) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 转一次字符串  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">r</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#032F62;--shiki-dark:#DBEDFF">INSERT INTO </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">{0}</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> (</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">{1}</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">)</span><span style="--shiki-light:#032F62;--shiki-dark:#DBEDFF">VALUES </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">{2}</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">)</span><span style="--shiki-light:#032F62;--shiki-dark:#DBEDFF">;</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.format(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.table_name,</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">","</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.join(columns_), </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">","</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.join(values_)))  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        # 这里知识简单的打印，其实没有做很多sql的工作  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> User</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">BaseModule</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">):  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    age </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> IntegerField(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">100</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    name </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> StringField()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Meta</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        table_name </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "vip_user"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">user </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> User(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">name</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"寄了😦"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">age</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">100</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">user.age </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 15</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  # 改变这个值里面的也会跟着变  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(user.name)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">user.save()</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br><span class="line-number">50</span><br><span class="line-number">51</span><br><span class="line-number">52</span><br><span class="line-number">53</span><br><span class="line-number">54</span><br><span class="line-number">55</span><br><span class="line-number">56</span><br><span class="line-number">57</span><br><span class="line-number">58</span><br><span class="line-number">59</span><br><span class="line-number">60</span><br><span class="line-number">61</span><br><span class="line-number">62</span><br><span class="line-number">63</span><br><span class="line-number">64</span><br><span class="line-number">65</span><br><span class="line-number">66</span><br><span class="line-number">67</span><br><span class="line-number">68</span><br><span class="line-number">69</span><br><span class="line-number">70</span><br><span class="line-number">71</span><br><span class="line-number">72</span><br><span class="line-number">73</span><br><span class="line-number">74</span><br><span class="line-number">75</span><br><span class="line-number">76</span><br><span class="line-number">77</span><br><span class="line-number">78</span><br><span class="line-number">79</span><br><span class="line-number">80</span><br><span class="line-number">81</span><br><span class="line-number">82</span><br><span class="line-number">83</span><br><span class="line-number">84</span><br><span class="line-number">85</span><br><span class="line-number">86</span><br><span class="line-number">87</span><br><span class="line-number">88</span><br><span class="line-number">89</span><br><span class="line-number">90</span><br><span class="line-number">91</span><br><span class="line-number">92</span><br><span class="line-number">93</span><br><span class="line-number">94</span><br><span class="line-number">95</span><br><span class="line-number">96</span><br><span class="line-number">97</span><br><span class="line-number">98</span><br><span class="line-number">99</span><br></div></div><p>运行结果</p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span></span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div></details>
<hr>
<h2 id="序列类型" tabindex="-1">序列类型 <a class="header-anchor" href="#序列类型" aria-label="Permalink to &quot;序列类型&quot;">&ZeroWidthSpace;</a></h2>
<h3 id="分类" tabindex="-1">分类 <a class="header-anchor" href="#分类" aria-label="Permalink to &quot;分类&quot;">&ZeroWidthSpace;</a></h3>
<ul>
<li>序列类型的类型分类
<ul>
<li>容器序列 (放置任意类型)
<ul>
<li>list、tuple、deque</li>
</ul>
</li>
<li>扁平序列（必须指明数据类型）
<ul>
<li>str、bytes、bytearray、array.array</li>
</ul>
</li>
</ul>
</li>
<li>属性分类
<ul>
<li>可变序列
<ul>
<li>list， deque，bytearray、array</li>
</ul>
</li>
<li>不可变
<ul>
<li>str、tuple、bytes</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="序列协议" tabindex="-1">序列协议 <a class="header-anchor" href="#序列协议" aria-label="Permalink to &quot;序列协议&quot;">&ZeroWidthSpace;</a></h3>
<p>用法可以看<a href="./Python库.html">Python库</a>的collections部分，这里主要探讨原理<br>
<code>collectios.abc</code>里查看各种类型实现了什么协议<br>
比如序列实现的ABC是</p>
<p><img src="./static/Python语言进阶_images_6.svg" alt=""></p>
<h4 id="序列-和" tabindex="-1">序列+=和+ <a class="header-anchor" href="#序列-和" aria-label="Permalink to &quot;序列+=和+&quot;">&ZeroWidthSpace;</a></h4>
<p>+不会改变原序列，而+=是就地加，无返回值直接加进原来的<br>
+必须为两个list相加，而+=后面可以是任意的序列<br>
+=是通过<code>__iadd__</code> 调用的<strong>extend</strong>，一个个append进来的，所以只要是<code>Iterable</code>就可以<br>
<code>append([1,2])</code>会整体加进去不会一个个加</p>
<h4 id="切片" tabindex="-1">切片 <a class="header-anchor" href="#切片" aria-label="Permalink to &quot;切片&quot;">&ZeroWidthSpace;</a></h4>
<details class="details custom-block"><summary>用法复习</summary>
<p>法复习</p>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#模式[start:end:step]</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"""</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    其中，第一个数字start表示切片开始位置，默认为0；</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    第二个数字end表示切片截止（但不包含）位置（默认为列表长度）；</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    第三个数字step表示切片的步长（默认为1）。</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    当start为0时可以省略，当end为列表长度时可以省略，</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    当step为1时可以省略，并且省略步长时可以同时省略最后一个冒号。</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    另外，当step为负整数时，表示反向切片，这时start应该比end的值要大才行。</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"""</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">aList </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> [</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">4</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">5</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">6</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">7</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">9</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">11</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">13</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">15</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">17</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (aList[::])  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 返回包含原列表中所有元素的新列表</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (aList[::</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">])  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 返回包含原列表中所有元素的逆序列表</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (aList[::</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">])  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 隔一个取一个，获取偶数位置的元素</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (aList[</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">::</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">])  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 隔一个取一个，获取奇数位置的元素</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (aList[</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">6</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">])  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 指定切片的开始和结束位置</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">aList[</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">100</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 切片结束位置大于列表长度时，从列表尾部截断</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">aList[</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">100</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:]  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 切片开始位置大于列表长度时，返回空列表</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">aList[</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">len</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(aList):] </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> [</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">9</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 在列表尾部增加元素</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">aList[:</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">] </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> [</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 在列表头部插入元素</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">aList[</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">] </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> [</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">4</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 在列表中间位置插入元素</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">aList[:</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">] </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> [</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 替换列表元素，等号两边的列表长度相等</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">aList[</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:] </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> [</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">4</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">5</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">6</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 等号两边的列表长度也可以不相等</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">aList[::</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">] </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> [</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">] </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 3</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  # 隔一个修改一个</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (aList)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">aList[::</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">] </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> [</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'a'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'b'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'c'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 隔一个修改一个</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">aList[::</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">] </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> [</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 左侧切片不连续，等号两边列表长度须相等,例子报错了</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">aList[:</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">] </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> []  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 删除列表中前3个元素</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">del</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> aList[:</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 切片元素连续</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">del</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> aList[::</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 切片元素不连续，隔一个删一个</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br></div></div></details>
<p>如何实现自定义类的切片<br>
<code>slice</code>是一种对象，<code>[::]</code>切片时先初始化一个slice对象然后交给<code>__getitem__</code>使用，<code>[0]</code>传入的是数字，直接判断类型针对处理</p>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __getitem__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self, item):</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        cls</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> type</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        if</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> isinstance</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(item, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">slice</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">):</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> cls</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">...</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 构建构建</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        elif</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> isinstance</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(item, numbers.Integral):</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> cls</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">...</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 构建构建</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br></div></div><p><a href="./Python库.html#^194418">bisect维护序列有序</a></p>
<h3 id="数组array" tabindex="-1">数组array <a class="header-anchor" href="#数组array" aria-label="Permalink to &quot;数组array&quot;">&ZeroWidthSpace;</a></h3>
<p>这个数组是C写的，性能很不错，思考一下什么时候不应该用数组可以用array代替<br>
array只能存放指定类型的数组，申请时先指定好类型<br>
<code>a=array.array(&quot;i&quot;)</code></p>
<table tabindex="0">
<thead>
<tr>
<th style="text-align:center">Type code</th>
<th style="text-align:center">C Type</th>
<th style="text-align:center">Minimum size in bytes</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center">'b'</td>
<td style="text-align:center">signed integer</td>
<td style="text-align:center">1</td>
</tr>
<tr>
<td style="text-align:center">'B'</td>
<td style="text-align:center">unsigned integer</td>
<td style="text-align:center">1</td>
</tr>
<tr>
<td style="text-align:center">'u'</td>
<td style="text-align:center">Unicode character</td>
<td style="text-align:center">2 (see note)</td>
</tr>
<tr>
<td style="text-align:center">'h'</td>
<td style="text-align:center">signed integer</td>
<td style="text-align:center">2</td>
</tr>
<tr>
<td style="text-align:center">'H'</td>
<td style="text-align:center">unsigned integer</td>
<td style="text-align:center">2</td>
</tr>
<tr>
<td style="text-align:center">'i'</td>
<td style="text-align:center">signed integer</td>
<td style="text-align:center">2</td>
</tr>
<tr>
<td style="text-align:center">'I'</td>
<td style="text-align:center">unsigned integer</td>
<td style="text-align:center">2</td>
</tr>
<tr>
<td style="text-align:center">'l'</td>
<td style="text-align:center">signed integer</td>
<td style="text-align:center">4</td>
</tr>
<tr>
<td style="text-align:center">'L'</td>
<td style="text-align:center">unsigned integer</td>
<td style="text-align:center">4</td>
</tr>
<tr>
<td style="text-align:center">'q'</td>
<td style="text-align:center">signed integer</td>
<td style="text-align:center">8 (see note)</td>
</tr>
<tr>
<td style="text-align:center">'Q'</td>
<td style="text-align:center">unsigned integer</td>
<td style="text-align:center">8 (see note)</td>
</tr>
<tr>
<td style="text-align:center">'f'</td>
<td style="text-align:center">floating point</td>
<td style="text-align:center">4</td>
</tr>
<tr>
<td style="text-align:center">'d'</td>
<td style="text-align:center">floating point</td>
<td style="text-align:center">8</td>
</tr>
</tbody>
</table>
<p>用法注释里头有用法，点进去看源码<br>
指定了类型然后再添加元素，那个initializer没看懂是在干啥，可能是利用这序列初始化</p>
<h3 id="列表生成式" tabindex="-1">列表生成式 <a class="header-anchor" href="#列表生成式" aria-label="Permalink to &quot;列表生成式&quot;">&ZeroWidthSpace;</a></h3>
<p>列表生成式性能是高于列表普通操作的，可以用函数来进行操作，但是代码可读性会下降。</p>
<ul>
<li>用()产生的是生成器</li>
<li>{}产生的是set，如果带k:v产生的就是字典
<ul>
<li>把数字当作key让dict看起来会像序列，有病啊</li>
</ul>
</li>
</ul>
<p><em>分类里的内置类型都能用，想到的时候看文档</em></p>
<h2 id="mapping类型" tabindex="-1">Mapping类型 <a class="header-anchor" href="#mapping类型" aria-label="Permalink to &quot;Mapping类型&quot;">&ZeroWidthSpace;</a></h2>
<h3 id="字典" tabindex="-1">字典 <a class="header-anchor" href="#字典" aria-label="Permalink to &quot;字典&quot;">&ZeroWidthSpace;</a></h3>
<h4 id="abc和日常用法" tabindex="-1">ABC和日常用法 <a class="header-anchor" href="#abc和日常用法" aria-label="Permalink to &quot;ABC和日常用法&quot;">&ZeroWidthSpace;</a></h4>
<p><img src="./static/Python语言进阶_images_7.svg" alt=""><br>
点进源码看有哪些方法，先列几个</p>
<ul>
<li><code>fromkeys(iterable,value)</code>
<ul>
<li>把iterable作为key，value作为默认的value，生成字典</li>
</ul>
</li>
<li><code>keys()</code></li>
<li><code>iterms()</code></li>
<li><code>get()</code></li>
<li><code>setdefault(k:v)</code>
<ul>
<li>取值，取不到就设置这对kv进去并且返回v</li>
<li>强化的get</li>
</ul>
</li>
<li><code>upadte()</code>
<ul>
<li>合并字典可以接受多种参数</li>
<li><code>k=v,[(k,v),(k,v)],{k:v}</code></li>
</ul>
</li>
</ul>
<h4 id="dict的子类" tabindex="-1">dict的子类 <a class="header-anchor" href="#dict的子类" aria-label="Permalink to &quot;dict的子类&quot;">&ZeroWidthSpace;</a></h4>
<div class="warning custom-block"><p class="custom-block-title">[⚠️Warning]</p>
<p>不要直接继承内置的类型，他们都是C写的有些魔法函数在子类里不生效<br>
使用collections库中的模块进行自定义修改</p>
</div>
<p><code>collections.defaultdict</code>的实现是使用<code>__missing__</code>魔法函数，如果取值的时候找不到值就去调用missing魔法函数</p>
<div class="warning custom-block"><p class="custom-block-title">[❓Question] userdict源码</p>
<p>serdict源码</p>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># userdict源码</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __getitem__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self, key):  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> key </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.data:  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.data[key]  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    if</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> hasattr</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">__class__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"__missing__"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">):  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">__class__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">__missing__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, key)  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 调用Missing</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    raise</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> KeyError</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(key)</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># defaultdict方法</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __missing__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self, key): </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># real signature unknown; restored from __doc__</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">        """</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">        __missing__(key) # Called by __getitem__ for missing key; pseudo-code:</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">          if self.default_factory is None: raise KeyError((key,))</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">          self[key] = value = self.default_factory()</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">          return value</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">        """</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        pass</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br></div></div></div>
<p>defaultdict具体用法看colletcions包</p>
<h4 id="set集合" tabindex="-1">set集合 <a class="header-anchor" href="#set集合" aria-label="Permalink to &quot;set集合&quot;">&ZeroWidthSpace;</a></h4>
<p>无序不重复，frozenset是不可添加修改的值，使用hash实现查找性能O(1)，可以作为dict的key，调用和set一样</p>
<ul>
<li><code>s1.difference(s2)</code>
<ul>
<li>返回一个差集</li>
</ul>
</li>
<li>集合的常见运算
<ul>
<li><code>|并集</code> <code>&amp;交集</code> <code>-差集</code></li>
<li>并交叉的魔法函数用到了再去查，是数学相关魔法函数</li>
</ul>
</li>
<li>超集或子集
<ul>
<li>“小于”符号（&lt;、&lt;=）用来判断子集</li>
<li>“大于”符号（&gt;、 &gt;= ）用来判断超集</li>
<li>等于号允许非严格定义的子集和超集，“小于” 和 “大于”意味着两个集合在比较时不能相等。</li>
</ul>
</li>
</ul>
<h3 id="如何实现set和dict" tabindex="-1">如何实现set和dict <a class="header-anchor" href="#如何实现set和dict" aria-label="Permalink to &quot;如何实现set和dict&quot;">&ZeroWidthSpace;</a></h3>
<ul>
<li>可哈希的(是不可变类型)才能当作key,在内部是使用红黑树实现的</li>
<li>内存花销大
<ul>
<li>当表小于1/3的时候，就会另申请空间使用数据迁移算法移动过去</li>
<li>在python3.7之后dict默认有序了</li>
</ul>
</li>
<li>优先使用set进行去重，占用比dict小，速度比list快</li>
<li><strong>set的去重是通过两个函数__hash__和__eq__结合实现的。</strong></li>
</ul>
<details class="details custom-block"><summary>Click to see more</summary>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Uniq</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __init__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self,name,count):</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.name </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> name</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.count </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> count</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __hash__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self):</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%s</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">调用了哈希方法"</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">%</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.name)</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> hash</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.count)</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __eq__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self, other):</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%s</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">调用了eq方法"</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">%</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.name)</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">__dict__</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> ==</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> other.</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">__dict__</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">u1 </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Uniq(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'u1'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">u2 </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Uniq(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'u2'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">u3 </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Uniq(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'u3'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'u1'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,u1)</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'u2'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,u2)</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'u3'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,u3)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">alist </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> [u1,u2,u3]</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">set</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(alist))</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br></div></div><p>运行结果</p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>u1 &#x3C;__main__.Uniq object at 0x00000226FA0996A0></span></span>
<span class="line"><span>u2 &#x3C;__main__.Uniq object at 0x00000226FA0999E8></span></span>
<span class="line"><span>u3 &#x3C;__main__.Uniq object at 0x00000226FA0C3710></span></span>
<span class="line"><span>u1调用了哈希方法</span></span>
<span class="line"><span>u2调用了哈希方法</span></span>
<span class="line"><span>u1调用了eq方法</span></span>
<span class="line"><span>u3调用了哈希方法</span></span>
<span class="line"><span>{&#x3C;__main__.Uniq object at 0x00000226FA0996A0>, &#x3C;__main__.Uniq object at 0x00000226FA0C3710>, &#x3C;__main__.Uniq object at 0x00000226FA0999E8>}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br></div></div></details>
<hr>
<h2 id="闭包装饰器" tabindex="-1">闭包装饰器 <a class="header-anchor" href="#闭包装饰器" aria-label="Permalink to &quot;闭包装饰器&quot;">&ZeroWidthSpace;</a></h2>
<h3 id="闭包" tabindex="-1">闭包 <a class="header-anchor" href="#闭包" aria-label="Permalink to &quot;闭包&quot;">&ZeroWidthSpace;</a></h3>
<blockquote>
<p>在计算机科学中，闭包（英语：Closure），又称词法闭包（Lexical Closure）或函数闭包（function closures），是引用了自由变量的函数。这个被引用的自由变量将和这个函数一同存在，即使已经离开了创造它的环境也不例外。所以，有另一种说法认为闭包是由函数和与其相关的引用环境组合而成的实体。闭包在运行时可以有多个实例，不同的引用环境和相同的函数组合可以产生不同的实例。
内部函数对外部函数作用域变量的引用</p>
</blockquote>
<p>函数内部的属性生命周期是执行期间，执行完之后就寄了，但是闭包可以返回函数的句柄，字节码内保留了外层函数使用的变量(私有化)这样就在第二次调用的时可以继续用，可以用来做装饰器@<br>
C++中有static关键字，函数中的static关键字定义的变量独立于函数之外，而且会保留函数中值的变化。函数中使用的全局变量也有类似的性质。</p>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> func1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(arg1):  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"in func1"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> func2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(num):  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        num</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">arg1  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(num)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> func2  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">var</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">func1(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">var(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#----结果----</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> func1</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">5</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br></div></div><h4 id="可见与绑定" tabindex="-1">可见与绑定 <a class="header-anchor" href="#可见与绑定" aria-label="Permalink to &quot;可见与绑定&quot;">&ZeroWidthSpace;</a></h4>
<p>这两篇文章仔细阅读，记住闭包的坑和过程<br>
<a href="https://www.linuxidc.com/Linux/2020-02/162395.htm" target="_blank" rel="noreferrer">Python UnboundLocalError和NameError错误根源解析</a><br>
<a href="https://www.linuxidc.com/Linux/2020-02/162394.htm" target="_blank" rel="noreferrer">深入理解Python闭包概念</a><br>
在C或者C++中，只要声明并定义了一个变量或者函数，便可以直接使用。但是在Python中要想引用一个name，该name必须要可见而且是绑定的。Free variable是一个比较重要的概念，在闭包中引用的父函数中的局部变量是一个free variable，而且该free variable被存放在一个cell对象中。这个会在闭包相关的文章中介绍。scope在函数中具有可扩展性，但在类定义中不具有可扩展性。闭包中的free variable可不可以被引用取决于它们有没有被绑定到具体的对象。<br>
这段代码会报错，想想为什么。</p>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> outer_func</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">():  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    loc_var </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "local variable"</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 绑定并声明  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> inner_func</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">():</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 这里穿进去也没用  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        loc_var</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">" in inner func"</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 必须新申请一个变量才可以解决  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> loc_var  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> inner_func</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> sys  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> add_path</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(new_path):  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    path_list </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> sys.path  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 这里会报错</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> new_path </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">not</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> in</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> path_list:  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> sys  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        sys.path.append(new_path)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">add_path(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'./'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br></div></div><ul>
<li>闭包中的引用的自由变量只和具体的闭包有关联，闭包的每个实例引用的自由变量互不干扰。</li>
<li>一个闭包实例对其自由变量的修改会被传递到下一次该闭包实例的调用。</li>
</ul>
<details class="details custom-block"><summary>闭包的自由变量</summary>
<p>包的自由变量</p>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> outer_func</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">():  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    loc_list </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> []  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> inner_func</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(name):  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        loc_list.append(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">len</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(loc_list) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%s</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> loc_list = </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%s</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> %</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(name, loc_list))</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> inner_func</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">clo_func_0 </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> outer_func()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">clo_func_0(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'clo_func_0'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">clo_func_0(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'clo_func_0'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">clo_func_0(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'clo_func_0'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">clo_func_1 </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> outer_func()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">clo_func_1(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'clo_func_1'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">clo_func_0(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'clo_func_0'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">clo_func_1(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'clo_func_1'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br></div></div><p>运行结果</p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>clo_func_0 loc_list = [1]  </span></span>
<span class="line"><span>clo_func_0 loc_list = [1, 2]  </span></span>
<span class="line"><span>clo_func_0 loc_list = [1, 2, 3]  </span></span>
<span class="line"><span>clo_func_1 loc_list = [1]  </span></span>
<span class="line"><span>clo_func_0 loc_list = [1, 2, 3, 4]  </span></span>
<span class="line"><span>clo_func_1 loc_list = [1, 2]</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br></div></div></details>
<p>经过上面的分析，我们得出下面一个重要的经验：返回闭包中不要引用任何循环变量，或者后续会发生变化的变量。<br>
这条规则本质上是在返回闭包前，闭包中引用的父函数中定义变量的值可能会发生不是我们期望的变化。<br>
正确的做法便是将父函数的local variable赋值给函数的形参。函数定义时，对形参的不同赋值会保留在当前函数定义中，不会对其他函数有影响。<br>
另外注意一点，如果返回的函数中没有引用父函数中定义的local variable，那么返回的函数不是闭包函数。<br>
简而言之闭包是惰性的，如果循环中i的值变了，那闭包里面也会变<br>
python闭包中引用的自由变量实际存放在一个Cell对象中，当自由变元被闭包引用时，便将Cell中存放的自由变量的引用放入栈顶。</p>
<details class="details custom-block"><summary>闭包使用循环中变量的例子</summary>
<p>包使用循环中变量的例子</p>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> my_func</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">args):  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    fs </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> []  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70"> xrange</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">):  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> func</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">():  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> i  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        fs.append(func)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> fs</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">fs1, fs2, fs3 </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> my_func()  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(fs1())</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(fs2())</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(fs3())</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br></div></div><p>运行结果</p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>4</span></span>
<span class="line"><span>4</span></span>
<span class="line"><span>4</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br></div></div><p>改写</p>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> my_func</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">args):  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    fs </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> []  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> range</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">):  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> func</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(_i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> i):  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> _i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> _i  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        fs.append(func)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> fs</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 或者</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> my_func</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">args):</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    fs </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> []</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> range</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">):</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        func </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> lambda</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> _i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> i : _i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> _i</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        fs.append(func)</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> fs</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br></div></div></details>
<h3 id="装饰器" tabindex="-1">装饰器 <a class="header-anchor" href="#装饰器" aria-label="Permalink to &quot;装饰器&quot;">&ZeroWidthSpace;</a></h3>
<p>装饰器是闭包实现的<br>
如果我们想对一个函数或者类进行修改重定义，最简单的方法就是直接修改其定义。但是这种做法的缺点也是显而易见的</p>
<ul>
<li>可能看不到函数或者类的定义</li>
<li>会破坏原来的定义，导致原来对类的引用不兼容</li>
<li>如果多人想在原来的基础上定制自己函数，很容易冲突
装饰器格式</li>
</ul>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(func):</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> wrapper</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">args, </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">**</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">kw):</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'call </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%s</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">():'</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> %</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> func.</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">__name__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 功能代码</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> func(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">args, </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">**</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">kw)</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> wrapper</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#----三层嵌套----</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(text): </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 可以带参数了</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> decorator</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(func):</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> wrapper</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">args, </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">**</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">kw):</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">            print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%s</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> %s</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">():'</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> %</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (text, func.</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">__name__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">))</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> func(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">args, </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">**</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">kw)</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> wrapper</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> decorator</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">@log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'execute'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> now</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">():</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'2015-3-25'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">now </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> log(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'execute'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)(now)</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br></div></div><p>以上两种decorator的定义都没有问题，但经过decorator装饰之后的函数，它们的<code>__name__</code>已经从原来的<code>'now'</code>变成了<code>'wrapper'</code></p>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(now.</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">__name__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'wrapper'</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br></div></div><p>因为返回的那个<code>wrapper()</code>函数名字就是<code>'wrapper'</code>，所以，需要把原始函数的<code>__name__</code>等属性复制到<code>wrapper()</code>函数中，否则，有些依赖函数签名的代码执行就会出错。<br>
不需要编写<code>wrapper.__name__ = func.__name__</code>这样的代码，Python内置的<code>functools.wraps</code>就是干这个事的，所以，一个完整的decorator的写法如下：</p>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> functools</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(func):</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    @functools.wraps</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(func)</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> wrapper</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">args, </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">**</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">kw):</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'call </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%s</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">():'</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> %</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> func.</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">__name__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> func(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">args, </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">**</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">kw)</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> wrapper</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br></div></div><p>经过装饰器修饰后，我们定义的类my_cls已经成为一个函数，和上面一个错误，它不仅改变了函数的名字，而且改变了类型<br>
闭包和装饰器引用了linux公社的俩文章和廖雪峰的</p>
<h3 id="偏函数" tabindex="-1">偏函数 <a class="header-anchor" href="#偏函数" aria-label="Permalink to &quot;偏函数&quot;">&ZeroWidthSpace;</a></h3>
<p><a href="./Python库.html#^ff28bf">python库-&gt;functools</a></p>
<h2 id="迭代器和生成器-1" tabindex="-1">迭代器和生成器 <a class="header-anchor" href="#迭代器和生成器-1" aria-label="Permalink to &quot;迭代器和生成器&quot;">&ZeroWidthSpace;</a></h2>
<h3 id="迭代器" tabindex="-1">迭代器 <a class="header-anchor" href="#迭代器" aria-label="Permalink to &quot;迭代器&quot;">&ZeroWidthSpace;</a></h3>
<p>^a159bd</p>
<p>可迭代类型(Iterable)都是实现了迭代协议<code>__iter__</code>,就是ABC中的<code>Iterable</code><br>
迭代器(Iterator)是惰性返回区别于下标，实现的是<code>__iter__</code>,<code>__next__</code>,ABC中的<code>Iterator</code>就是实现了这两个函数，访问数据使用的是<code>__next__</code>，一般用来遍历<br>
可以使用<code>iter(list)</code>将Iterable转为Iterator<br>
如果对只实现了<code>__getitem__</code>的对象直接使用for，实际上是一个编译器优化退行寻找<br>
解释器先调用<code>iter(obj)</code>-&gt;找不到<code>__iter__</code>-&gt;创建<code>__iter__</code>并从0遍历<code>__getitem__</code><br>
所以如果你把<code>__iter__</code>重载了不返回<code>Iterator</code>的话那就报错。</p>
<p>自己实现iterator的时候，自定义<code>__iter__</code>和<code>__next__</code>就可以了，实际上for就是不停调用next.<br>
自己设计迭代对象的时候，<code>Iterable</code>里面不要写<code>__next__</code>，<code>__iter__</code>返回<code>Iterator</code>进行维护</p>
<details class="details custom-block"><summary>Click to see more</summary>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> collections.abc </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Iterator   </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Company</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">object</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">):  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __init__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self, employee_list):  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.employee </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> employee_list  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __iter__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self): </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 返回一个迭代器维护  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> MyIterator(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.employee)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    # def __getitem__(self, item): # 可迭代对象  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    #     return self.employee[item]  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> MyIterator</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Iterator</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">):  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __init__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self, employee_list):  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.iter_list </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> employee_list  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.index </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    # def __iter__(self): #这是Iterator替你做的事情  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    #     return self  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __next__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self):  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 必须实现的函数</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        #真正返回迭代值的逻辑  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        try</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            word </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.iter_list[</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.index]  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        except</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> IndexError</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            raise</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> StopIteration</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # for迭代协议中遇到这个错误就停止  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.index </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> word  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">company </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Company([</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"tom"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"bob"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"jane"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">])  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">my_itor </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> iter</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(company)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> item </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> company:  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (item)</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br></div></div><p>运行结果</p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>tom</span></span>
<span class="line"><span>bob</span></span>
<span class="line"><span>jane</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br></div></div></details>
<p>list推导式应该是先确定大小，再开辟内存，所以快，for循环加尾插的话要扩容多次，所以慢<br>
这里学的不太牢靠，多看看想想</p>
<h3 id="生成器" tabindex="-1">生成器 <a class="header-anchor" href="#生成器" aria-label="Permalink to &quot;生成器&quot;">&ZeroWidthSpace;</a></h3>
<p>只要存在yield替换掉return就转换成了生成器，也可以return，调用函数实际上返回的是生成器对象</p>
<h4 id="函数运行原理" tabindex="-1">函数运行原理 <a class="header-anchor" href="#函数运行原理" aria-label="Permalink to &quot;函数运行原理&quot;">&ZeroWidthSpace;</a></h4>
<p>解释器python.exe会使用C函数<code>PyEval_EvalFramEX()</code>去执行函数，首先创建栈帧压栈，使用<code>dis.dis()</code>可以查看对象的生成的字节码对象，全局唯一，当函数嵌套时，就会继续创建栈帧压栈，这样出栈保持函数可以执行顺序，所有的栈帧都存放在堆内存上，这就决定了栈帧可以独立于调用者存在</p>
<p>静态语言中函数是存放在栈内存中的，调用完就会销毁。</p>
<details class="details custom-block"><summary>不用掌握,知道就行</summary>
<p>用掌握,知道就行</p>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> inspect </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 查看栈帧的包  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">frame </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> None</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> foo</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">():  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    bar() </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 套娃一个函数  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> bar</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">():  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    global</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> frame  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    frame </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> inspect.currentframe() </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 获取当前函数栈帧  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> dis  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(dis.dis(foo)) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 查看函数字节码对象  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">foo() </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 调用完之后并没有销毁  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(frame.f_code.co_name) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 查看栈帧对象  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">caller_frame </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> frame.f_back </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 查看上级?栈帧对象  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(caller_frame.f_code.co_name)</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br></div></div><p>运行结果</p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>  4           0 LOAD_GLOBAL              0 (bar)</span></span>
<span class="line"><span>              2 CALL_FUNCTION            0</span></span>
<span class="line"><span>              4 POP_TOP</span></span>
<span class="line"><span>              6 LOAD_CONST               0 (None)</span></span>
<span class="line"><span>              8 RETURN_VALUE</span></span>
<span class="line"><span>None</span></span>
<span class="line"><span>bar</span></span>
<span class="line"><span>foo</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br></div></div></details>
<p><img src="./static/Python语言进阶_images_8.png" alt=""></p>
<h4 id="生成器原理" tabindex="-1">生成器原理 <a class="header-anchor" href="#生成器原理" aria-label="Permalink to &quot;生成器原理&quot;">&ZeroWidthSpace;</a></h4>
<p>生成器正是利用了函数是存放在堆这一特性实现的，解释器找到yield就标记函数为生成器对象<br>
<img src="./static/Python语言进阶_images_9.png" alt="">
PyFrameObject会记录最近执行的代码和变量，以此可以用yield来暂停函数<br>
实际上UserList就是利用yield实现的在collections.abc的Sequence可看源码</p>
<div class="tip custom-block"><p class="custom-block-title">[💡Tip]</p>
<p>range()返回的是一个list对象，而xrange返回的是一个生成器对象(xrange object)<br>
在python3 中没有xrange，只有range。range和python2 中的xrange()一样</p>
</div>
<h4 id="example-2读取大文件" tabindex="-1">example-2读取大文件 <a class="header-anchor" href="#example-2读取大文件" aria-label="Permalink to &quot;example-2读取大文件&quot;">&ZeroWidthSpace;</a></h4>
<p>某文本文件只有一行，100G+，每条数据按照分割符分割长度不固定，如果直接open会加载到内存卡死，read可以按固定大小字节读取。<br>
要求使用for遍历所有行</p>
<details class="details custom-block"><summary>大文件读取</summary>
<p>文件读取</p>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> read_large_line</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(uri):  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    buffer</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">""</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 变量缓冲字符串  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    with</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> open</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(uri,</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"r"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">encoding</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"utf8"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">as</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> f: </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 打开文件  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        while</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> True</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 循环  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            while</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> buffer.find(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"{|}"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">==-</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 如果buff里没有分割符  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">                # 假设一行不会特别大，这样buffer好操作，一次性只读取20B  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">                readtemp</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">f.read(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">20</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">                if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> readtemp</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">==</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">""</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 返回这个就是读完了  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">                    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(buffer) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 读完了把最后一个也打印一下  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">                    return</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "打印完毕"</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 结束生成器  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">                buffer</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">readtemp </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># buffer上次剩下的接上新读的  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">            # 读出来三种情况，正好切割完，剩个尾巴,分割符被切了 </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            buffer</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">buffer.split(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"{|}"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 跳出循环说明有个分割符  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> buffer[:</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]:</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 最后一个可能是半截，不出去  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">                yield</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> i </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 出去一行  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            buffer</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">buffer[</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 赋值半截进入下次循环  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> read_large_line(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"a.txt"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">):  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(i)</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br></div></div><p>运行结果</p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>阿斯顿撒过的杜甫地方官</span></span>
<span class="line"><span>sadhashdisgbiasdmbfgisadhashdisg...</span></span>
<span class="line"><span>ahndsaidbi</span></span>
<span class="line"><span>阿斯sdsadas甫地方官</span></span>
<span class="line"><span>sad566849694dmbfgi</span></span>
<span class="line"><span>ahndwqewq34assadbi</span></span>
<span class="line"><span>阿斯7去沃尔特呕吐病地方官</span></span>
<span class="line"><span>sadha分萨斯的iasdmbfgi</span></span>
<span class="line"><span>ahn萨芬萨达到了分aidbi</span></span>
<span class="line"><span>阿斯sds的圣彼得堡官</span></span>
<span class="line"><span>sad566fghdfdgsaaahjkmbfgi</span></span>
<span class="line"><span>ahn8956895bi</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br></div></div></details>
<h3 id="生成器进阶" tabindex="-1">生成器进阶 <a class="header-anchor" href="#生成器进阶" aria-label="Permalink to &quot;生成器进阶&quot;">&ZeroWidthSpace;</a></h3>
<h4 id="yield的其他用法" tabindex="-1">yield的其他用法 <a class="header-anchor" href="#yield的其他用法" aria-label="Permalink to &quot;yield的其他用法&quot;">&ZeroWidthSpace;</a></h4>
<p>生成器不仅可以yield出值，还可以接收值<br>
使用<code>y=yield value</code>就可以拿到y，此时外部调用就不能是next，而是用<code>send</code>。<br>
<code>gen.close()</code>之后就无法next了，抛出错误<br>
BaseException 是 Exception 的父类，作为子类的Exception无法截获父类BaseException类型的错误</p>
<details class="details custom-block"><summary>Click to see more</summary>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> y</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">():  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    h</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=yield</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "a"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    yield</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> h  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    yield</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "c"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    yield</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "d"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">gen</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">y()  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">next</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(gen),  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">      # 第一次先yield出来，第一次不yield函数根本没有执行成yield对象  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">      # 否则会报错不能send非None对象，先next或者send(None)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      gen.send(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"off"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">),  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">      # 这里的send是延迟传入的，先给上一个h赋值进去，在获取这个yield，过程都是惰性的  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">      next</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(gen)  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">      # 没了就抛StopIteration  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      )  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">gen.throw(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">Exception</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"custom-error"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 让gen抛出异常，在没打印的那个yield之前  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">gen.close() </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 关闭生成器  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">next</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(gen)</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 抛出StopIteration</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br></div></div><p>运行结果</p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>a off c</span></span>
<span class="line"><span>Traceback (most recent call last):</span></span>
<span class="line"><span>  File "/Users/jack/code/py/AdvancedPython/asyncio_prac/yeild-senior.py", line 17, in &#x3C;module></span></span>
<span class="line"><span>    gen.throw(Exception,"custom-error")</span></span>
<span class="line"><span>  File "/Users/jack/code/py/AdvancedPython/asyncio_prac/yeild-senior.py", line 5, in y</span></span>
<span class="line"><span>    yield "c"</span></span>
<span class="line"><span>Exception: custom-error</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br></div></div></details>
<h4 id="yield-from" tabindex="-1">yield from <a class="header-anchor" href="#yield-from" aria-label="Permalink to &quot;yield from&quot;">&ZeroWidthSpace;</a></h4>
<p>调用方和子生成器之间建立通道，处理一大堆边界异常。</p>
<details class="details custom-block"><summary>Click to see more</summary>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> G</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">():  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 子生成器  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    temp</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=yield</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "yy"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    yield</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> temp  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    yield</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "yy"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    yield</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "yy"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> g1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(gen):  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 委托生成器  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    yield from</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> gen </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 会在调用方和子生成器间建立一个双向通道  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> main</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">():  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 调用方  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    gen </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> G()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    g </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> g1(gen)  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">next</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(g),  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">          g.send(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"what?"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">),</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># send直接发送到子生成器了  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">          )  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">main()</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br></div></div><p>运行结果</p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>yy what?</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div></details>
<p>这一节<a href="https://peps.python.org/pep-0380/" target="_blank" rel="noreferrer">PEP 380 – Syntax for Delegating to a Subgenerator | peps.python.org</a> 代码讲的是原理<br>
<a href="https://cloud.ooowl.fun/api/v3/file/source/1097/12-9%20%E7%94%9F%E6%88%90%E5%99%A8%E8%BF%9B%E9%98%B6-yield%20from-2.mp4?sign=hcx9fkeSflcjLLy87iziaY-keyxtgTVdX6xCOHfFTrY%3D%3A0" target="_blank" rel="noreferrer">视频</a></p>
<details class="details custom-block"><summary>PEP380代码yield from翻译讲解</summary>
<p>EP380代码yield from翻译讲解</p>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#pep380  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#1. RESULT = yield from EXPR可以简化成下面这样  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#一些说明  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"""  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">_i：子生成器，同时也是一个迭代器  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">_y：子生成器生产的值  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">_r：yield from 表达式最终的值  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">_s：调用方通过send()发送的值  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">_e：异常对象  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"""</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">_i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> iter</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">EXPR</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)      </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># EXPR是一个可迭代对象，_i其实是子生成器；  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">try</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    _y </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> next</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(_i)   </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 预激子生成器，把产出的第一个值存在_y中；  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">except</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> StopIteration</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> as</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> _e:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    _r </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> _e.value   </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 如果抛出了`StopIteration`异常，那么就将异常对象的`value`属性保存到_r，这是最简单的情况的返回值；  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">else</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    while</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:    </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 尝试执行这个循环，委托生成器会阻塞；  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        _s </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> yield</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> _y   </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 生产子生成器的值，等待调用方`send()`值，发送过来的值将保存在_s中；  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        try</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            _y </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> _i.send(_s)    </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 转发_s，并且尝试向下执行；  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        except</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> StopIteration</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> as</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> _e:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            _r </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> _e.value       </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 如果子生成器抛出异常，那么就获取异常对象的`value`属性存到_r，退出循环，恢复委托生成器的运行；  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            break</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">RESULT</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> _r     </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># _r就是整个yield from表达式返回的值。  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"""  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">1. 子生成器可能只是一个迭代器，并不是一个作为协程的生成器，所以它不支持.throw()和.close()方法；  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">2. 如果子生成器支持.throw()和.close()方法，但是在子生成器内部，这两个方法都会抛出异常；  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">3. 调用方让子生成器自己抛出异常  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">4. 当调用方使用next()或者.send(None)时，都要在子生成器上调用next()函数，当调用方使用.send()发送非 None 值时，才调用子生成器的.send()方法；  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"""</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">_i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> iter</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">EXPR</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">try</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    _y </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> next</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(_i)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">except</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> StopIteration</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> as</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> _e:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    _r </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> _e.value  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">else</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    while</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        try</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            _s </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> yield</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> _y  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        except</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> GeneratorExit</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> as</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> _e:  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            try</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">                _m </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> _i.close  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            except</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> AttributeError</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">                pass</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            else</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">                _m()  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            raise</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> _e  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        except</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> BaseException</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> as</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> _e:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            _x </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> sys.exc_info()  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            try</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">                _m </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> _i.throw  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            except</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> AttributeError</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">                raise</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> _e  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            else</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">                try</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">                    _y </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> _m(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">_x)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">                except</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> StopIteration</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> as</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> _e:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">                    _r </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> _e.value  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">                    break</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        else</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            try</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">                if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> _s </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">is</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> None</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">                    _y </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> next</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(_i)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">                else</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">                    _y </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> _i.send(_s)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            except</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> StopIteration</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> as</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> _e:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">                _r </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> _e.value  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">                break</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">RESULT</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> _r  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"""  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">看完代码，我们总结一下关键点：  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">1. 子生成器生产的值，都是直接传给调用方的；调用方通过.send()发送的值都是直接传递给子生成器的；如果发送的是 None，会调用子生成器的__next__()方法，如果不是 None，会调用子生成器的.send()方法；  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">2. 子生成器退出的时候，最后的return EXPR，会触发一个StopIteration(EXPR)异常；  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">3. yield from表达式的值，是子生成器终止时，传递给StopIteration异常的第一个参数；  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">4. 如果调用的时候出现StopIteration异常，委托生成器会恢复运行，同时其他的异常会向上 "冒泡"；  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">5. 传入委托生成器的异常里，除了GeneratorExit之外，其他的所有异常全部传递给子生成器的.throw()方法；如果调用.throw()的时候出现了StopIteration异常，那么就恢复委托生成器的运行，其他的异常全部向上 "冒泡"；  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">6. 如果在委托生成器上调用.close()或传入GeneratorExit异常，会调用子生成器的.close()方法，没有的话就不调用。如果在调用.close()的时候抛出了异常，那么就向上 "冒泡"，否则的话委托生成器会抛出GeneratorExit异常。  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"""</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br><span class="line-number">50</span><br><span class="line-number">51</span><br><span class="line-number">52</span><br><span class="line-number">53</span><br><span class="line-number">54</span><br><span class="line-number">55</span><br><span class="line-number">56</span><br><span class="line-number">57</span><br><span class="line-number">58</span><br><span class="line-number">59</span><br><span class="line-number">60</span><br><span class="line-number">61</span><br><span class="line-number">62</span><br><span class="line-number">63</span><br><span class="line-number">64</span><br><span class="line-number">65</span><br><span class="line-number">66</span><br><span class="line-number">67</span><br><span class="line-number">68</span><br><span class="line-number">69</span><br><span class="line-number">70</span><br><span class="line-number">71</span><br><span class="line-number">72</span><br><span class="line-number">73</span><br><span class="line-number">74</span><br><span class="line-number">75</span><br><span class="line-number">76</span><br><span class="line-number">77</span><br><span class="line-number">78</span><br><span class="line-number">79</span><br><span class="line-number">80</span><br><span class="line-number">81</span><br><span class="line-number">82</span><br><span class="line-number">83</span><br><span class="line-number">84</span><br><span class="line-number">85</span><br></div></div></details>
<p>这也是await和async的原理</p>
<hr>
<h2 id="网络编程" tabindex="-1">网络编程 <a class="header-anchor" href="#网络编程" aria-label="Permalink to &quot;网络编程&quot;">&ZeroWidthSpace;</a></h2>
<p>#TODO socket编程应该还有进阶课，如果以后发现太多了就独立出去链接过来</p>
<blockquote>
<p>一些前置知识温习<br>
Socket是为了方便开发者直接使用更底层协议（一般是TCP或UDP）而存在的一个抽象层。Socket实际上是对TCP/IP协议的封装，本身并不是协议，而是一个调用接口（API）。<br>
WebSocket协议基于Http协议的扩展，支持长连接，用于建立客户端和服务器的双向通道。<br>
WebSocket是保证只要在服务端和客户端建立连接后任何一端发起消息，相互推送消息，效率也是极大的提高了，并且服务端和客户端之间的标头信息很小，可以降低服务端的资源浪费。<br>
对于WebSocket来说，它必须依赖Http协议进行一次握手，握手成功后，数据就直接从TCP通道传输，与Http无关了。<br>
传统的轮询方式（即采用http协议不断发送请求）的缺点：浪费流量（http请求头比较大）、浪费资源（没有更新也要请求）、消耗服务器、CPU占用（没有信息也要接收请求）。</p>
</blockquote>
<p>socket编程比较固定，流程各个语言中都通用，先bind-&gt;listen-&gt;accept-&gt;阻塞等待tcp-&gt;传输-&gt;关闭</p>
<p><img src="./static/Python语言进阶_images_10.png" alt=""></p>
<p><code>socket.socket(通信类型,对应协议)</code><br>
通信类型常用的:</p>
<ul>
<li>AF_INET = 2 ipv4</li>
<li>AF_INET6 = 23 ipv6</li>
<li>AF_IPX = 6 unix进程间通信</li>
</ul>
<p>协议就俩:</p>
<ul>
<li>socket.SOCK_STREAM 类似TCP</li>
<li>socket.SOCK_DGRAM 类似UDP</li>
</ul>
<p>这些可以现查去文档里看<br>
继承关系 requests-&gt;urlib-&gt;socket</p>
<details class="details custom-block"><summary>socket最基本的函数使用</summary>
<p>ocket最基本的函数使用</p>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#----server----</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> socket  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">server</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">socket.socket(socket.</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">AF_INET</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,socket.</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">SOCK_STREAM</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">server.bind((</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'0.0.0.0'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">8001</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">))  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">server.listen()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">sock,addr</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> server.accept()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 获取数据，一次1kb  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">data</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">sock.recv(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1024</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 参数为接收的bit数  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(data.decode(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"utf8"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">))  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">sock.send(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"hello </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">{}</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.format(data.decode(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"utf8"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)).encode(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"utf8"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">))  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">server.close()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">sock.close()</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#----client----</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> socket  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">client</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">socket.socket(socket.</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">AF_INET</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,socket.</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">SOCK_STREAM</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">client.connect((</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'127.0.0.1'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">8001</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">))  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">client.send(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"cc"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.encode(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"utf8"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">))  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">data</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">client.recv(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1024</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(data.decode(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"utf8"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">))</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#----运行结果----</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">server: cc</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">client: hello cc</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br></div></div></details>
<details class="details custom-block"><summary>多线程处理多client</summary>
<p>线程处理多client</p>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> socket  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> threading  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">server </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> socket.socket(socket.</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">AF_INET</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,socket.</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">SOCK_STREAM</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">server.bind((</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'0.0.0.0'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">8001</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">))  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">server.listen()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> handle_sock</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(sock, addr): </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#包装成个函数  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    while</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> True</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        data </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> sock.recv(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1024</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(data.decode(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"utf8"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">))  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        re_data </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> input</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        sock.send(re_data.encode(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"utf8"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">))  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#获取从客户端发送的数据  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#一次获取1k的数据  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">while</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> True</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 循环每个客户端一个线程  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    sock, addr </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> server.accept()  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    #用线程去处理新接收的连接(用户)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    client_thread </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> threading.Thread(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">target</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">handle_sock, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">args</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(sock, addr))  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    client_thread.start()</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br></div></div><p>运行结果</p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>运行多次cllient即可</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div></details>
<details class="details custom-block"><summary>socket模拟http</summary>
<p>ocket模拟http</p>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> socket  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> urllib.parse </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> urlparse  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> get_url</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(url):  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    # 通过socket请求html  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    url </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> urlparse(url) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 只是用它来解析  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    host </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> url.netloc  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    path </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> url.path  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> path </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">==</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> ""</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        path </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "/"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    # 建立socket连接  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    client </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> socket.socket(socket.</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">AF_INET</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, socket.</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">SOCK_STREAM</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    client.connect((host, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">80</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">))  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    # 不停的询问连接是否建立好， 需要while循环不停的去检查状态  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    # 做计算任务或者再次发起其他的连接请求  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    # 注意http格式，准备好需要的格式就可以了，难点在于发送和接收  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    client.send(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"GET </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">{}</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> HTTP/1.1</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">\r\n</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">Host:</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">{}\r\n</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">Connection:close</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">\r\n\r\n</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.format(path, host).encode(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"utf8"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">))  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    data </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> b</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">""</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    while</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> True</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 循环接收数据  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        d </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> client.recv(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1024</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> d:  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 没了就停  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            data </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> d  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        else</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            break</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    data </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> data.decode(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"utf8"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    html_data </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> data.split(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">\r\n\r\n</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x3C;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">br</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">/></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(html_data)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    client.close()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">if</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __name__</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> ==</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "__main__"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> time  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    start_time </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> time.time()  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> url </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> range</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">20</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">):  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        url </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "http://www.baidu.com"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.format(url)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        get_url(url)  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(time.time() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> start_time)</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br></div></div><p>运行结果</p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>&#x3C;!DOCTYPE html>&#x3C;html>&#x3C;head>&#x3C;meta http-...</span></span>
<span class="line"><span>&#x3C;!DOCTYPE html>&#x3C;html>&#x3C;head>&#x3C;meta http-...</span></span>
<span class="line"><span>&#x3C;!DOCTYPE html>&#x3C;html>&#x3C;head>&#x3C;meta http-...</span></span>
<span class="line"><span>&#x3C;!DOCTYPE html>&#x3C;html>&#x3C;head>&#x3C;meta http-...</span></span>
<span class="line"><span>...</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br></div></div></details>
<hr>
<h2 id="多线程编程" tabindex="-1">多线程编程 <a class="header-anchor" href="#多线程编程" aria-label="Permalink to &quot;多线程编程&quot;">&ZeroWidthSpace;</a></h2>
<h3 id="gil全局解释器锁" tabindex="-1">GIL全局解释器锁 <a class="header-anchor" href="#gil全局解释器锁" aria-label="Permalink to &quot;GIL全局解释器锁&quot;">&ZeroWidthSpace;</a></h3>
<p>global interpreter lock，python性能不高的原因之一<br>
python 为了简单解释器会加锁，GIL使得在一个时刻内只有一个线程在一个CUP内核上运行字节码，保证线程安全，而且隐含的是无法将多个线程映射到多CPU上<br>
Python内部对变量或数据对象使用了<strong>引用计数器</strong>,我们通过计算引用个数,当个数为0时,变量或者数据对象就被自动释放。<br>
这个引用计数器需要保护,当多个线程同时修改这个值时,可能会导致内存泄漏;我们使用锁来解决这个问题,可有时会添加多个锁来解决,这就会导致<strong>死锁</strong>;<br>
为了避免内存泄漏和死锁问题,CPython使用了<strong>单锁</strong>,即全局解释器锁(GIL),即执行Python字节码都需要获取GIL,而其他线程如果想要操作和执行相同的代码需要等某个线程操作完了，释放了GIL后，这个线程才能拿到GIL锁，并且上锁，执行代码。</p>
<ol>
<li>GIL在会根据字节码行数或者时间片释放</li>
<li>会在遇到IO操作的时候释放(异步和多线程的基础)</li>
</ol>
<p>多进程的优点是稳定性好，一个子进程崩溃了，不会影响主进程以及其余进程，操作系统对进程的总数会有一定的限制多了会假死，使用资源也多。<br>
多线程优点是效率较高一些，但是致命的缺点是任何一个线程崩溃都可能造成整个进程的崩溃，因为它们共享了进程的内存资源池，上下文切换的开销小一些。<br>
#TODO 操作系统看完的时候把OS那里链接过来<br>
<mark>进程是资源分配的最小单位，线程是CPU调度的最小单位</mark><br>
新的解释器<a href="https://doc.pypy.org/en/latest/cpython_differences.html" target="_blank" rel="noreferrer">PyPy</a>会比cpython快，也有其他的解释器jpython这种。</p>
<h3 id="多线程" tabindex="-1">多线程 <a class="header-anchor" href="#多线程" aria-label="Permalink to &quot;多线程&quot;">&ZeroWidthSpace;</a></h3>
<h4 id="原生多线程和继承thread" tabindex="-1">原生多线程和继承Thread <a class="header-anchor" href="#原生多线程和继承thread" aria-label="Permalink to &quot;原生多线程和继承Thread&quot;">&ZeroWidthSpace;</a></h4>
<p>在python中创建的线程都是子线程，实际上还有一个主线程用来执行代码，使用pycharm Debug的Frames可以查看  、
默认情况下所有线程运行完才能关闭进程</p>
<p>方法 : 情景<br>
设为守护线程 : 让主线程运行完退出进程关闭，子线程没运行完就kill掉<br>
使用阻塞方法 : 某个线程阻塞之后等待该线程执行完毕才能继续往下执行</p>
<p>注意基本API的使用，原生和继承效果是一样的，继承需要实现它的<code>run</code>方法</p>
<details class="details custom-block"><summary>原生多线程和继承线程类</summary>
<p>生多线程和继承线程类</p>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> time  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> threading  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> fun1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(arg1):  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"1 begin"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, arg1)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    time.sleep(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"1 end...."</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> fun2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(arg2):  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"2 begin"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, arg2)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    time.sleep(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">4</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"2 end...."</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">t1 </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> threading.Thread(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">target</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">fun1, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">args</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"我是线程1"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,))  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">t2 </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> threading.Thread(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">target</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">fun2, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">args</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"我是线程2"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,))  </span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># --------继承线程Thread类-----------</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> MyThread1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">threading</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Thread</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">):  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __init__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self,name):  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"定义线程:"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, name)  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.arg</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">name  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        super</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">().</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">__init__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">name</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">name) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> run</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self):  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"1 begin"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.name)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        time.sleep(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"1 end...."</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> MyThread2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">threading</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Thread</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">):  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __init__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self,name):  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"定义线程:"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, name)  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.arg</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">name  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        super</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">().</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">__init__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">name</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">name)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> run</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self):  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"2 begin"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.name)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        time.sleep(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">4</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"2 end...."</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">t1</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">MyThread1(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"我是类线程1"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">t2</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">MyThread2(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"我是类线程2"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># --------效果是一样的---------------</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">t2.setDaemon(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">True</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># t2设为守护线程，2s后t1完成会直接退出  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">start_time </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> time.time()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">t1.start()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">t2.start()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">t1.join()</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># t1 阻塞了,运行时间就是t1的时间  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">end_time </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> time.time()  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"back to main thread,time : </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">{0}</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.format(end_time</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">start_time))</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br></div></div><p>运行结果</p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>定义线程: 我是类线程1 # 类线程中init打印的</span></span>
<span class="line"><span>定义线程: 我是类线程2 # 类线程中init打印的</span></span>
<span class="line"><span>1 begin 我是线程1</span></span>
<span class="line"><span>2 begin 我是线程2</span></span>
<span class="line"><span>1 end....</span></span>
<span class="line"><span>back to main thread,time : 2.0046401023864746 s</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br></div></div></details>
<h4 id="线程通信" tabindex="-1">线程通信 <a class="header-anchor" href="#线程通信" aria-label="Permalink to &quot;线程通信&quot;">&ZeroWidthSpace;</a></h4>
<p>通信方式演化: global 全局变量-&gt;可变对象比如list放到线程的参数里<br>
把共享变量放到单独文件引用进来管理，另一个线程对变量进行修改，如果直接引用<code>变量</code>在,本文件里是看不到的，但是如果引用<code>文件.变量</code>就可以。<br>
直接共享变量实际上是线程不安全的，必须用锁自己进行设计。所以我们要用<strong>线程安全</strong>的变量</p>
<div class="info custom-block"><p class="custom-block-title">[📝Note]</p>
<p>生产者消费者模式是通过一个容器（Queue）来解决生产者和消费者的强耦合问题,如果有兴趣可以直接点进去看源码这些队列是怎么实现线程安全的，使用的是Condition<br>
<strong>在多线程开发当中，如果生产者处理速度很快，而消费者处理速度很慢，那么生产者就必须等待消费者处理完，才能继续生产数据。同样的道理，如果消费者的处理能力大于生产者，那么消费者就必须等待生产者。为了解决这个问题于是引入了生产者和消费者模式。</strong></p>
</div>
<h5 id="消息队列queue" tabindex="-1">消息队列Queue <a class="header-anchor" href="#消息队列queue" aria-label="Permalink to &quot;消息队列Queue&quot;">&ZeroWidthSpace;</a></h5>
<p>queue是阻塞的，空了就停这了，有了再动，底层实现使用的是collections的dqueue，后者在字节码层面实现线程安全<br>
join之后不要忘了taskdown 释放,带nowait方法是异步方法，默认创建先进先出，可以创建后进先出和优先级队列<br>
put和get都是可以通过参数设置超时时间和是否阻塞的，用到了再去查，queue中还有优先级队列等留意一下</p>
<details class="details custom-block"><summary>使用线程安全队列的生产消费者模型</summary>
<p>用线程安全队列的生产消费者模型</p>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> queue  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> random  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> threading  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> time  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> queue </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Queue  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">q </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> queue.Queue(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">maxsize</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">100</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 就一个参数，定义一个长度100的先进先出队列  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 使用线程安全队列的生产消费者模型  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Productor</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">threading</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Thread</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">):  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __init__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self, name):  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"初始化</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%s</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">线程:"</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> %</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> name)  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        super</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">().</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">__init__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">name</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">name)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> run</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self):  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        global</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> q  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 拿到全局的queue  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        while</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> True</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            time.sleep(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">4</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 假设每个生产者每4秒生产一个  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            value </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> random.randint(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1024</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            q.put(value)  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">            print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Product : </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%d</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> %</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> value)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Consumer</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">threading</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Thread</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">):  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __init__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self, name):  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"初始化</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%s</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">线程:"</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> %</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> name)  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        super</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">().</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">__init__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">name</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">name)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> run</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self):  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        global</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> q  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 拿到全局的queue  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        while</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> True</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            time.sleep(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 消费者每一秒消费一个  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            temp </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> q.get()  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">            print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Comsume : </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%d</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> %</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> temp)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> range</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">4</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">): </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 3个消费者 每秒消耗3个  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    c</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Consumer(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">name</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"消费者</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%d</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">%</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">i)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    c.start()  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> range</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">11</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">): </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 10个生产者 每秒产生2.5个  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    p</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Productor(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">name</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"生产者</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%d</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">%</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">i)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    p.start()</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br></div></div><p>运行结果</p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>初始化消费者1线程:</span></span>
<span class="line"><span>初始化消费者2线程:</span></span>
<span class="line"><span>初始化消费者3线程:</span></span>
<span class="line"><span>初始化生产者1线程:</span></span>
<span class="line"><span>初始化生产者2线程:</span></span>
<span class="line"><span>初始化生产者3线程:</span></span>
<span class="line"><span>初始化生产者4线程:</span></span>
<span class="line"><span>初始化生产者5线程:</span></span>
<span class="line"><span>初始化生产者6线程:</span></span>
<span class="line"><span>初始化生产者7线程:</span></span>
<span class="line"><span>初始化生产者8线程:</span></span>
<span class="line"><span>初始化生产者9线程:</span></span>
<span class="line"><span>初始化生产者10线程:</span></span>
<span class="line"><span>Product : 499</span></span>
<span class="line"><span>Comsume : 499</span></span>
<span class="line"><span>Product : 594</span></span>
<span class="line"><span>Product : 765</span></span>
<span class="line"><span>Comsume : 594</span></span>
<span class="line"><span>Comsume : 765</span></span>
<span class="line"><span>Product : 958</span></span>
<span class="line"><span>Product : 481</span></span>
<span class="line"><span>Product : 124</span></span>
<span class="line"><span>...</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br></div></div></details>
<h3 id="线程同步" tabindex="-1">线程同步 <a class="header-anchor" href="#线程同步" aria-label="Permalink to &quot;线程同步&quot;">&ZeroWidthSpace;</a></h3>
<h4 id="mutex互斥锁" tabindex="-1">Mutex互斥锁 <a class="header-anchor" href="#mutex互斥锁" aria-label="Permalink to &quot;Mutex互斥锁&quot;">&ZeroWidthSpace;</a></h4>
<p><code>Lock</code>每个锁对象是一个锁，锁会影响性能，锁使用不当会引起死锁，没释放就再次获取，AB两个线程互相等待对方的锁造成死锁<br>
<code>Rlock</code>是可重入锁，使用Lock实现的，同一个线程里面可以多次acquire，但是也要release相同次</p>
<details class="details custom-block"><summary>Click to see more</summary>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> threading  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> threading </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Lock,RLock  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">L</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Lock()  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">RL</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">RLock()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">a</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> fun1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(arg1):  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"1 begin"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, arg1)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    global</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> a  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> range</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1000000</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">):  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        L.acquire()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        RLock.acquire()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        RLock.acquire()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        a</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        L.release()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        RLock.release()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        RLock.release()  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> fun2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(arg2):  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"2 begin"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, arg2)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    global</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> a  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> range</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1000000</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">):  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        L.acquire()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        a</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        L.release()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">t1 </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> threading.Thread(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">target</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">fun1, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">args</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"我是线程1"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,))  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">t2 </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> threading.Thread(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">target</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">fun2, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">args</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"我是线程2"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,))  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">t1.start()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">t2.start()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">t1.join()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">t2.join()  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(a)</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br></div></div><p>运行结果</p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>1 begin 我是线程1</span></span>
<span class="line"><span>2 begin 我是线程2</span></span>
<span class="line"><span>0 # 没锁就是随机数</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br></div></div></details>
<h4 id="condition条件对象" tabindex="-1">Condition条件对象 <a class="header-anchor" href="#condition条件对象" aria-label="Permalink to &quot;Condition条件对象&quot;">&ZeroWidthSpace;</a></h4>
<p>条件变量允许一个或多个线程等待，知道它们被另一个线程唤醒。</p>
<ol>
<li>如果给出了<code>lock</code>参数而不是<code>None</code>，则它必须是<code>Lcok</code>或<code>RLock</code>对象，并以它作为底层的锁。否则将默认创建一个<code>RLock</code>对象。</li>
<li><code>Condition</code>遵循上下文管理协议,可以用with
<ul>
<li><code>with cond :...</code>等价于<code>cond.lock...cond.release</code></li>
<li>是通过魔法函数实现的</li>
</ul>
</li>
<li>一定要注意Condition的启动顺序，如果A notify的时候B还没启动，wait没就绪那上来就死锁了</li>
<li>注意四个方法
<ul>
<li><code>acquire/release</code>就是调用锁的<code>acquire/release</code></li>
<li><code>notify</code>和<code>wait</code> 唤醒和睡眠，唤醒之后就开始工作，wait就会等待下次唤醒
<ul>
<li>wait可以用timeout参数设置超时时间</li>
<li>一旦被唤醒或超时，它会重新获取锁并返回,返回值为<code>True</code>，如果给定<code>timeout</code>并发生超时，则返回<code>False</code></li>
</ul>
</li>
<li><code>notify</code>可以指定参数n唤醒几个，可以直接<code>notify_all()</code>唤醒所有</li>
<li><code>wait_for(predicate, timeout=None)</code>等待直到条件变量的返回值为<code>True</code>。
<ul>
<li><code>predicate</code>应该是一个返回值可以解释为布尔值的可调用对象。可以设置<code>timeout</code>以给定最大等待时间。该方法可以重复调用<code>wait()</code>，直到<code>predicate</code>的返回值解释为<code>True</code>，或发生超时。该方法的返回值就是<code>predicate</code>的最后一个返回值，如果发生超时，返回值为<code>False</code>。</li>
<li>就是每次wait的时候都检查一次<code>predicate()</code>是True才会执行。</li>
</ul>
</li>
</ul>
</li>
</ol>
<h5 id="大致实现原理" tabindex="-1">大致实现原理 <a class="header-anchor" href="#大致实现原理" aria-label="Permalink to &quot;大致实现原理&quot;">&ZeroWidthSpace;</a></h5>
<p>condition有两层锁，一把Rlock和一个waiters双端队列，用Rlock锁定要执行的块，每次wait都申请一把锁然后 <mark>acquire两次</mark>放到waiters，每次notify就是拿出一把waiter锁release,每次with-cond都会进入enter把Rlock acquire，所以不用notify释放</p>
<p>1个生产者，3个消费者,空了喊来生产，满了喊他消费</p>
<div class="warning custom-block"><p class="custom-block-title">[⚠️Warning] 一定要注意</p>
<p>定要注意
注意消费者的sleep如果在cond里面，会直接把锁锁住，不能release就会跟单线程一样的效果一个吃完了再吃<br>
多线程中不要阻塞锁<br>
考虑好cond的位置:<br>
谁运行谁有R，谁阻塞谁重锁<br>
R保证安全，waiter用来卡住<br>
由于场景是多个消费者进行抢购，如果将获取锁操作放在循环外(如生产者),<br>
那么一个消费者线程被唤醒时会锁住整个循环，无法实现另一个消费者的抢购。<br>
在循环中添加一套&quot;获取锁-释放锁&quot;,一个消费者购买完成后释放锁，其他消费者<br>
就可以获取锁来参与购买。</p>
</div>
<details class="details custom-block"><summary>使用条件变量的生产消费者模型</summary>
<p>用条件变量的生产消费者模型</p>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> threading </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Condition  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> queue  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> random  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> threading  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> time  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">q</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">queue.Queue(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">maxsize</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">15</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 就一个参数，定义一个长度50的先进先出队列  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 使用Condition的生产消费者模型  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">cond</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Condition()  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Productor</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">threading</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Thread</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">):  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __init__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self, name):  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"初始化</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%s</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">线程:"</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> %</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> name)  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        super</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">().</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">__init__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">name</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">name)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> run</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self):  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        global</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> q  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 拿到全局的queue  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        with</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> cond: </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 锁住R  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            while</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> True</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 注意 while和cond的位置 </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">                if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> q.full():  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">                    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"生产完了，快来吃"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">                    cond.notify()  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># notify卡住</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">                    cond.wait() </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 通知完之后释放R  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">                time.sleep(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0.1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 假设每个生产者每0.1秒生产一个  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">                value </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> random.randint(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1024</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">                q.put(value)  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">                print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Product : </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%d</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> %</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> value)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Consumer</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">threading</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Thread</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">):  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __init__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self, name):  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.arg</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">name  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"初始化</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%s</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">线程:"</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> %</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> name)  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        super</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">().</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">__init__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">name</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">name)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> run</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self):  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        global</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> q  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 拿到全局的queue  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        while</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> True</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            with</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> cond: </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 注意这里，sleep如果在cond里面，会直接把锁锁住，不能release就会跟单线程一样的效果  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">                if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> q.empty():  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">                    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%s</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">饿了等着吃，快生产"</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">%</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.arg)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">                    cond.notify()  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">                    # notify的时候，生产者又一次拿到了R锁</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">                    cond.wait()  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">                    # 这里虽然是三个消费者线程，但是在q空了wait状态的时候，</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">                    # R锁被释放，waiter获取两次卡住这里</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">                    # 生产者从cond又拿R锁，直到通知释放waiter才会执行</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">                    # R保证了只有一个线程在吃，所以其他两个线程进不来甚至看不到q，是安全的</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">                temp </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> q.get()  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">                print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Comsume</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%s</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> : </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%d</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> %</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.arg,temp))  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            time.sleep(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 消费者每秒消费一个  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">p</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Productor(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">name</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"生产者"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">p.start()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">c1</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Consumer(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">name</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"消费者</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%d</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">%</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">c2</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Consumer(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">name</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"消费者</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%d</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">%</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">c3</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Consumer(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">name</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"消费者</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%d</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">%</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">c1.start()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">c2.start()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">c3.start()</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br><span class="line-number">50</span><br><span class="line-number">51</span><br><span class="line-number">52</span><br><span class="line-number">53</span><br><span class="line-number">54</span><br><span class="line-number">55</span><br><span class="line-number">56</span><br><span class="line-number">57</span><br><span class="line-number">58</span><br></div></div><p>运行结果</p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>初始化生产者线程:</span></span>
<span class="line"><span>Product : 834</span></span>
<span class="line"><span>...</span></span>
<span class="line"><span>Product : 1000</span></span>
<span class="line"><span>生产完了，快来吃</span></span>
<span class="line"><span>初始化消费者1线程:</span></span>
<span class="line"><span>初始化消费者2线程:</span></span>
<span class="line"><span>初始化消费者3线程:</span></span>
<span class="line"><span>Comsume消费者1 : 834</span></span>
<span class="line"><span>Comsume消费者2 : 401</span></span>
<span class="line"><span>Comsume消费者3 : 882</span></span>
<span class="line"><span>Comsume消费者1 : 115</span></span>
<span class="line"><span>Comsume消费者2 : 800</span></span>
<span class="line"><span>Comsume消费者3 : 938</span></span>
<span class="line"><span>Comsume消费者1 : 949</span></span>
<span class="line"><span>Comsume消费者2 : 546</span></span>
<span class="line"><span>Comsume消费者3 : 30</span></span>
<span class="line"><span>Comsume消费者1 : 64</span></span>
<span class="line"><span>Comsume消费者3 : 27</span></span>
<span class="line"><span>Comsume消费者2 : 966</span></span>
<span class="line"><span>Comsume消费者1 : 598</span></span>
<span class="line"><span>Comsume消费者2 : 317</span></span>
<span class="line"><span>Comsume消费者3 : 1000</span></span>
<span class="line"><span>消费者2饿了等着吃，快生产</span></span>
<span class="line"><span>消费者3饿了等着吃，快生产</span></span>
<span class="line"><span>消费者1饿了等着吃，快生产</span></span>
<span class="line"><span>Product : 981</span></span>
<span class="line"><span>Product : 841</span></span>
<span class="line"><span>...</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br></div></div></details>
<p><img src="./static/Python语言进阶_images_11.png" alt=""></p>
<h4 id="semaphore信号量" tabindex="-1">Semaphore信号量 <a class="header-anchor" href="#semaphore信号量" aria-label="Permalink to &quot;Semaphore信号量&quot;">&ZeroWidthSpace;</a></h4>
<p>其实就是数量锁，还有剩余就获取一个开整，没锁就停着<br>
<strong>原理</strong>也是condition实现的，value不为0那就-1，那就获得cond，没了就wait，释放的时候value+1，并notify一次随机唤醒一个</p>
<p>当<code>blocking=False</code>时，不会阻塞。如果调用<code>acquire()</code>时计数器为零，则会立即返回<code>False</code>.<br>
如果设置了<code>timeout</code>参数，它将阻塞最多<code>timeout</code>秒。如果在该时间段内没有获取锁，则返回<code>False</code>，否则返回<code>True</code>。</p>
<details class="details custom-block"><summary>信号量实现控制多消费者并发数量</summary>
<p>号量实现控制多消费者并发数量</p>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> threading </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Semaphore  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> queue  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> random  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> threading  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> time  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">q </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> queue.Queue(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">maxsize</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">100</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 就一个参数，定义一个长度100的先进先出队列  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">sem</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Semaphore(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">4</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 申请信号量  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Productor</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">threading</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Thread</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">):  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __init__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self, name,sem):  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.sem</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">sem  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"初始化</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%s</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">线程:"</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> %</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> name)  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        super</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">().</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">__init__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">name</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">name)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> run</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self):  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        global</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> q  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 拿到全局的queue  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        while</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> True</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            time.sleep(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 假设每个生产者每2秒生产一个  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            value </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> random.randint(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1024</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            q.put(value)  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">            print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Product</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%s</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> : </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%d</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> %</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.name,value))  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">            self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.sem.release()  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 生产完了一个再release</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Consumer</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">threading</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Thread</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">):  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __init__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self, name,sem):  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.sem</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">sem </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 可变对象  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"初始化</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%s</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">线程:"</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> %</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> name)  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        super</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">().</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">__init__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">name</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">name)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> run</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self):  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        global</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> q  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 拿到全局的queue  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        while</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> True</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">            self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.sem.acquire() </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 消费者每次消费之前都acquire，acquire不到就停住  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            time.sleep(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 消费者每一秒消费一个  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            temp </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> q.get()  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">            print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Comsume</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%s</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> : </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%d</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> %</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.name,temp))  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> range</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">): </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 2个生产者 每个每2秒产生1  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    p</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Productor(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">name</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"生产者</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%d</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">%</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">i,</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">sem</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">sem)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    p.start()  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> range</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">10</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">): </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 10个消费者,每个每秒1个, 控制并发为4个  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    c</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Consumer(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">name</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"消费者</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%d</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">%</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">i,</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">sem</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">sem)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    c.start()</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br></div></div><p>运行结果</p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>初始化生产者1线程:</span></span>
<span class="line"><span>初始化生产者2线程:</span></span>
<span class="line"><span>初始化消费者1线程:</span></span>
<span class="line"><span>初始化消费者2线程:</span></span>
<span class="line"><span>初始化消费者3线程:</span></span>
<span class="line"><span>初始化消费者4线程:</span></span>
<span class="line"><span>初始化消费者5线程:</span></span>
<span class="line"><span>初始化消费者6线程:</span></span>
<span class="line"><span>初始化消费者7线程:</span></span>
<span class="line"><span>初始化消费者8线程:</span></span>
<span class="line"><span>初始化消费者9线程:</span></span>
<span class="line"><span>Product生产者1 : 528</span></span>
<span class="line"><span>Comsume消费者2 : 528</span></span>
<span class="line"><span>Product生产者2 : 61</span></span>
<span class="line"><span>Comsume消费者3 : 61</span></span>
<span class="line"><span>Product生产者2 : 598</span></span>
<span class="line"><span>Product生产者1 : 643Comsume消费者4 : 598</span></span>
<span class="line"><span></span></span>
<span class="line"><span>Comsume消费者1 : 643</span></span>
<span class="line"><span>Product生产者2 : 464</span></span>
<span class="line"><span>Product生产者1 : 618Comsume消费者3 : 464</span></span>
<span class="line"><span></span></span>
<span class="line"><span>Comsume消费者6 : 618</span></span>
<span class="line"><span>Product生产者2 : 213</span></span>
<span class="line"><span>Product生产者1 : 184</span></span>
<span class="line"><span>Comsume消费者7 : 213</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br></div></div></details>
<h4 id="event事件对象" tabindex="-1">Event事件对象 <a class="header-anchor" href="#event事件对象" aria-label="Permalink to &quot;Event事件对象&quot;">&ZeroWidthSpace;</a></h4>
<p>事件对象管理一个内部标志，通过<code>set()</code>方法将其设置为<code>True</code>，并使用<code>clear()</code>方法将其设置为<code>False</code>。<code>wait()</code>方法阻塞，直到标志为<code>True</code>再解除阻塞。该标志初始为<code>False</code>。</p>
<ul>
<li><code>is_set()</code>，顾名思义返回标志状态</li>
<li><code>set()</code>  将标志设置为<code>True</code>。所有等待它成为<code>True</code>的线程都被唤醒。若已经<code>True</code>状态，线程调用<code>wait()</code>不会阻塞。</li>
<li><code>clear()</code> 将标志置为<code>False</code>,并阻塞调用<code>wait()</code>的线程</li>
<li><code>wait(timeout=None)</code> 该方法总是返回<code>True</code>，除非设置了<code>timeout</code>并发生超时。</li>
</ul>
<details class="details custom-block"><summary>Click to see more</summary>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> threading  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> time  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> threading </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Event  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">ev</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Event()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">ev.clear() </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 置为False获取的会直接阻塞  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> MyThread1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">threading</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Thread</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">):  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __init__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self,name,ev):  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"初始化线程:"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, name)  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.ev</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">ev  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.arg</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">name  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        super</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">().</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">__init__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">name</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">name)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> run</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self):  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"1 begin"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.name)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        time.sleep(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.ev.wait() </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 阻塞了  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        time.sleep(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"1 end...."</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> MyThread2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">threading</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Thread</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">):  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __init__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self,name,ev):  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"初始化线程:"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, name)  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.ev</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">ev  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.arg</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">name  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        super</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">().</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">__init__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">name</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">name)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> run</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self):  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"2 begin"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.name)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        time.sleep(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">5</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.ev.set() </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 等完五秒解除线程1的阻塞  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"2 end...."</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">t1</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">MyThread1(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"线程1"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,ev)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">t2</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">MyThread2(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"线程2"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,ev)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">start_time </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> time.time()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">t1.start()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">t2.start()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">t1.join()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">t2.join()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">end_time </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> time.time()  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 最后等待时间8s  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"back to main thread,time : </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">{0}</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> s"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.format(end_time</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">start_time))</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br></div></div><p>运行结果</p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>初始化线程: 线程1</span></span>
<span class="line"><span>初始化线程: 线程2</span></span>
<span class="line"><span>1 begin 线程1</span></span>
<span class="line"><span>2 begin 线程2</span></span>
<span class="line"><span>2 end....</span></span>
<span class="line"><span>1 end....</span></span>
<span class="line"><span>back to main thread,time : 8.003741979598999 s</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br></div></div></details>
<h4 id="barrier障碍对象" tabindex="-1">Barrier障碍对象 <a class="header-anchor" href="#barrier障碍对象" aria-label="Permalink to &quot;Barrier障碍对象&quot;">&ZeroWidthSpace;</a></h4>
<p><code>Barrier(parties, action=None, timeout=None)</code><br>
每个线程通过调用<code>wait()</code>尝试通过障碍并阻塞，直到阻塞的数量达到<code>parties</code>时，阻塞的线程被同时全部释放。<br>
<code>action</code>是一个可调用对象， <mark>无参</mark>，当线程被释放时，其中随机一个线程会首先调用<code>action</code>，之后再跑自己的代码。<br>
<code>timeout</code>时默认的超时时间。</p>
<p><code>wait(timeout=None)</code> 返回值是<code>0</code>到<code>parties-1</code>范围内的整数，是等待时候的顺序</p>
<ul>
<li>其中一个线程在释放之前将调用<code>action</code>。如果此调用引发错误，则障碍将进入断开状态。</li>
<li>如果等待超时，障碍也将进入断开状态。</li>
<li>如果在线程等待期间障碍断开或重置，此方法会引发<code>BrokenBarrierError</code>错误，注意错误处理。</li>
</ul>
<p><code>reset()</code></p>
<ul>
<li>重置障碍，返回默认的空状态，即当前阻塞的线程抛出<code>BrokenBarrierError</code>错误重新开始执行，之前执行的不算数。</li>
</ul>
<p><code>abort()</code></p>
<ul>
<li>将障碍置为断开状态，导致正在等待或 <mark>之后调用</mark><code>wait()</code>引发<code>BrokenBarrierError</code>,注意和reset的区别</li>
</ul>
<p>属性：</p>
<ul>
<li><code>partier</code>  通过障碍所需的线程数</li>
<li><code>n_waiting</code>  当前在屏障中等待的线程数</li>
<li><code>broken</code>  如果Barrier处于断开状态，则返回<code>True</code></li>
</ul>
<details class="details custom-block"><summary>Click to see more</summary>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> threading  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> threading </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Barrier  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> after</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">():  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 无参的action  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"线程跨过去了"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">barrier </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Barrier(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">action</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">after, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">timeout</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">None</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Worker</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">threading</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Thread</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">):  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __init__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self, name, barrier):  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"初始化线程:"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, name)  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.barrier </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> barrier  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.arg </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> name  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        super</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">().</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">__init__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">name</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">name)  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> run</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self):  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"begin"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.name)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        try</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">            self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.barrier.wait()  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        except</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> threading.BrokenBarrierError </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">as</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> e:  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">            print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%s</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">被重置或断开了"</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">%</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.name)  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"end"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.name)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Manager</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">threading</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Thread</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">):  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __init__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self, name, barrier):  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"初始化线程:"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, name)  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.barrier </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> barrier  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.arg </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> name  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        super</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">().</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">__init__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">name</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">name)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> run</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self):  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.barrier.reset()  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        # self.barrier.abort()  # 注意他俩区别，abort之后直接跨不过去了</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"manager 重置"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"基本信息"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.barrier.parties,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.barrier.broken,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.barrier.n_waiting)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> range</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">):  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    t </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Worker(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"worker </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%s</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> %</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> i, barrier)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    t.start()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">m </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Manager(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"manager"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, barrier)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">m.start()  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> range</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">6</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">):  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    t </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Worker(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"worker </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%s</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> %</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> i, barrier)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    t.start()</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br></div></div><p>其中一个 运行结果</p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>初始化线程: worker 1</span></span>
<span class="line"><span>begin初始化线程: worker 2</span></span>
<span class="line"><span>begin初始化线程: manager</span></span>
<span class="line"><span>manager 重置</span></span>
<span class="line"><span> worker 1</span></span>
<span class="line"><span> worker 2初始化线程: worker 3基本信息 3 </span></span>
<span class="line"><span>False 1</span></span>
<span class="line"><span></span></span>
<span class="line"><span>begin初始化线程: worker 4</span></span>
<span class="line"><span>begin初始化线程:   worker 3</span></span>
<span class="line"><span>线程跨过去了</span></span>
<span class="line"><span>end worker 3</span></span>
<span class="line"><span>end worker 1</span></span>
<span class="line"><span>worker 4</span></span>
<span class="line"><span>end worker 2</span></span>
<span class="line"><span>worker 5</span></span>
<span class="line"><span>begin worker 5</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br></div></div></details>
<h4 id="threadlocal" tabindex="-1">ThreadLocal <a class="header-anchor" href="#threadlocal" aria-label="Permalink to &quot;ThreadLocal&quot;">&ZeroWidthSpace;</a></h4>
<p>本地线程的Local对象，直接赋值取值就可以</p>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 创建全局ThreadLocal对象:</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">local</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> threading.local()</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">local.a</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"123"</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(local.a)</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br></div></div><h4 id="example-3发布订阅模型" tabindex="-1">example-3发布订阅模型 <a class="header-anchor" href="#example-3发布订阅模型" aria-label="Permalink to &quot;example-3发布订阅模型&quot;">&ZeroWidthSpace;</a></h4>
<p>#TODO 多线程发布订阅模型
<a href="https://python3-cookbook.readthedocs.io/zh_CN/latest/c12/p11_implement_publish_subscribe_messaging.html" target="_blank" rel="noreferrer">12.11 实现消息发布/订阅模型 — python3-cookbook 3.0.0 文档</a></p>
<h3 id="线程池" tabindex="-1">线程池 <a class="header-anchor" href="#线程池" aria-label="Permalink to &quot;线程池&quot;">&ZeroWidthSpace;</a></h3>
<p>设计原理和java的concurrent是一样的<br>
多线程和多进程都是使用<code>from concurrent import futures</code><br>
<code>ThreadPoolExecutor</code>,<code>as_completed</code>,<code>wait</code><br>
可以使用上下文协议<code>with ThreadPoolExecutor(n) as executor:</code><br>
优点有管理数量，获得状态返回值，让主线程能知道线程已经完成，让多线程进程编码一致<br>
线程task是一个future对象，主要方法<code>cancel</code>，<code>cancelled</code>，<code>running</code>，<code>done</code>，<code>result</code>，<code>add_done_callback</code>看字面就知道啥意思<br>
线程池可以有很多个task，max_worker决定的是并发数量</p>
<p><code>as_completed</code> 是一个yield生成器，接收线程池，yield <mark>已经完成的线程结果</mark></p>
<p><code>wait</code>接收task列表，用来阻塞主进程，当task列表中的所有任务完成才会继续执行，可以使用<code>return_when</code>参数修改条件</p>
<ul>
<li><code>FIRST_COMPLETED = 'FIRST_COMPLETED'</code></li>
<li><code>FIRST_EXCEPTION = 'FIRST_EXCEPTION'</code></li>
<li><code>ALL_COMPLETED = 'ALL_COMPLETED'</code></li>
<li><code>_AS_COMPLETED = '_AS_COMPLETED'</code></li>
</ul>
<details class="details custom-block"><summary>Click to see more</summary>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> time  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> concurrent.futures </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> ThreadPoolExecutor,as_completed,wait  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> tasks</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(times):  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    time.sleep(times)  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"睡了</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%s</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">秒"</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">%</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">times)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> times  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">executor</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">ThreadPoolExecutor(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">max_workers</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 线程池同时执行几个  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 提交任务是非阻塞的  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">task1</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">executor.submit(tasks,(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">))  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">task2</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">executor.submit(tasks,(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">))  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"is done: "</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,task1.done())</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 返回是否完成  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"cancal success ?"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,task2.cancel()) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 任务在没执行才可以取消，执行完和执行中是无法取消的  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> future </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> as_completed([task1,task2]): </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 异步的，实际上就是yield出来结果pending，剩下的继续yield  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    # for data in executor.map(func ,[argList]) 也可以实现，返回的是data不是future对象  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    # 这里的map和内置的一个意思，返回顺序是和argList一样的  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    data</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">future.result()  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"future data : "</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,data)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">wait([task1,task2],</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">return_when</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'ALL_COMPLETED'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">time.sleep(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"is done: "</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,task2.done())  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"task result :"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,task1.result())</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br></div></div><p>运行结果</p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>cancal success ? False</span></span>
<span class="line"><span>睡了2秒</span></span>
<span class="line"><span>future data :  2</span></span>
<span class="line"><span>睡了3秒</span></span>
<span class="line"><span>future data :  3</span></span>
<span class="line"><span>is done:  True</span></span>
<span class="line"><span>task result : 3</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br></div></div></details>
<h4 id="线程的终止" tabindex="-1">线程的终止 <a class="header-anchor" href="#线程的终止" aria-label="Permalink to &quot;线程的终止&quot;">&ZeroWidthSpace;</a></h4>
<p>知道这个事，到时候去搜<br>
终止线程官方提供的接口实际上不是那么好用，理想方式是设置标志位，检测标志位False，写成中常用<br>
但是在项目中可能函数根本没法检查到标志位那一步就阻塞了，强制终止一个线程是很危险的<br>
callback里使用<code>res=ctypes.pythonapi.PyThreadState_SetAsyncExc(thread_id,ctypes.py_object(SystemExit))</code></p>
<h4 id="线程进程队列性能" tabindex="-1">线程进程队列性能 <a class="header-anchor" href="#线程进程队列性能" aria-label="Permalink to &quot;线程进程队列性能&quot;">&ZeroWidthSpace;</a></h4>
<table tabindex="0">
<thead>
<tr>
<th>线程/进程/线程队列/进程队列</th>
<th>10W数据进队列时间</th>
<th>10W数据出队列时间</th>
<th>100W数据进队列时间</th>
<th>100W数据出队列时间</th>
<th>结果分析</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>collections.deque</code></td>
<td>180ms</td>
<td>380ms</td>
<td>190ms</td>
<td>376ms</td>
<td>性能：高</td>
</tr>
<tr>
<td><code>multiprocessing.Queue</code></td>
<td>300ms</td>
<td>12s</td>
<td>1.92s</td>
<td>2m15s</td>
<td>性能：一般。</td>
</tr>
<tr>
<td>组合使用1：mq提供数据给collections.deque使用</td>
<td>300ms</td>
<td>11s</td>
<td>3.051s</td>
<td>2m26s</td>
<td>性能：一般。<br/>分析：结果跟直接使用进程队列相近，耗时主要发生在加锁释放锁上面</td>
</tr>
<tr>
<td>组合使用2：一个进程作为生产者生产3个<code>multiprocessing.Queue</code><br/>三个线程消费进程队列数据，存储到<code>collections.deque</code></td>
<td>mq=300ms dq=50/s</td>
<td>mq=50/s dq=50/s</td>
<td>mq=3.0s dq=50/s</td>
<td>mq=dq=50/s</td>
<td>性能：差。<br/>分析：在线程中消费进程队列中的数据，可能会因为锁的抢占带来性能问题。<br/> 100W条数据mq入=6s,<br/> MQ抢占时段：mq出=dq入=dq出 = 50条/s， <br/>MQ非抢占时段:mq出=dq入=dq出 = 100W/50s。</td>
</tr>
</tbody>
</table>
<p>综合分析<sup class="footnote-ref"><a href="#fn1" id="fnref1">[1]</a></sup></p>
<ul>
<li>MQ在数据量比较大的时候，抢占队列会导致出队列速度降低。</li>
<li>不推荐组合使用，建议使用进程multiprocessQ或都使用线程+collect.deque比较好。</li>
</ul>
<h3 id="多进程" tabindex="-1">多进程 <a class="header-anchor" href="#多进程" aria-label="Permalink to &quot;多进程&quot;">&ZeroWidthSpace;</a></h3>
<p>可充分利用CPU,多进程切换更加耗时，所以时间不是简单除，能开的线程数比进程多很多，多线程稳定性比多进程好</p>
<div class="warning custom-block"><p class="custom-block-title">[⚠️Warning]</p>
<p>在windows和macos下多进程编程必须放到<code>if __name__ == &quot;__main__&quot;:</code>否则会报<code>BrokenProcessPool</code><br>
linux不会</p>
</div>
<p>fork的时候，会额外创建一个子进程，子进程会把父进程的所有数据都复制一份，数据会完全隔离，会从fork之后的代码依次运行。<br>
父进程结束之后，子进程未结束，子进程会继续执行打印，但实际上你已经可以动了。
<code>from concurrent.futures import ProcessPoolExecutor</code>接口形状和<code>ThreadPoolExecutor</code>一模一样。</p>
<h4 id="multiprocessing" tabindex="-1">multiprocessing <a class="header-anchor" href="#multiprocessing" aria-label="Permalink to &quot;multiprocessing&quot;">&ZeroWidthSpace;</a></h4>
<p><a href="https://docs.python.org/zh-cn/3.7/library/multiprocessing.html" target="_blank" rel="noreferrer">文档</a><br>
比ProcessPoolExecutor更加底层，一般用上面那个，这个用的少<br>
默认进程池的进程数是和CPU的数量相等的</p>
<p><code>apply_async</code> 是在一个池工作进程中<strong>异步</strong>地执行函数，然后返回结果<br>
<code>apply</code>是在一个池工作进程中执行函数，然后返回结果。<br>
<code>multiprocessing.cpu_count()</code>获得<br>
<code>pool.close()</code>关闭进程池不再接收新任务<br>
<code>pool.join()</code>等待池中的任务全都完成，join之前必须close<br>
<code>imap</code>和<code>imap_unordered</code>顾名思义，和上面那个一样<br>
单个的task start之后会有PID，可以通过<code>pid</code>属性查看<br>
<code>daemon</code>属性等价于多进程的setDaemon</p>
<details class="details custom-block"><summary>Click to see more</summary>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> multiprocessing  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> time  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> multiprocessing </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Lock  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> task</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(times):  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'Process </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">% s</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">tart'</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">%</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">times)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    time.sleep(times)  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'Process </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">% e</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">nd'</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">%</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">times)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "我完成了--</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%s</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">%</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">times  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">if</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __name__</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> ==</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> '__main__'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    t1</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">multiprocessing.Process(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">target</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">task,</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">args</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,))  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    t1.start() </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 单个的</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"multiprocess。。。"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    # 申请一个worker数量和cup核数相等的池  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    pool</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">multiprocessing.Pool(multiprocessing.cpu_count())  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    results</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[]  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> [</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">] :  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        result</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">pool.apply_async(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">func</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">task,</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">args</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(i,)) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 线程池中提交任务  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        results.append(result)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    pool.close()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    pool.join() </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 阻塞等待完成  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> r </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> results:  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(r.get())</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br></div></div><p>运行结果</p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>multiprocess。。。</span></span>
<span class="line"><span>Process 3tart</span></span>
<span class="line"><span>Process 1tart</span></span>
<span class="line"><span>Process 2tart</span></span>
<span class="line"><span>Process 3tart</span></span>
<span class="line"><span>Process  1.000000e+00nd</span></span>
<span class="line"><span>Process  2.000000e+00nd</span></span>
<span class="line"><span>Process  3.000000e+00nd</span></span>
<span class="line"><span>Process  3.000000e+00nd</span></span>
<span class="line"><span>我完成了--1</span></span>
<span class="line"><span>我完成了--2</span></span>
<span class="line"><span>我完成了--3</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br></div></div></details>
<h3 id="进程通信" tabindex="-1">进程通信 <a class="header-anchor" href="#进程通信" aria-label="Permalink to &quot;进程通信&quot;">&ZeroWidthSpace;</a></h3>
<div class="warning custom-block"><p class="custom-block-title">[❓Question]</p>
<p>为啥不能多进程调起多线程？这样不快吗<br>
暂时的答案，没必要，主进程可以开多线程负责io，子进程负责计算就可以了，太复杂了不利于开发</p>
</div>
<p><mark>多线程的锁和队列共享等在多进程都是不能用的</mark>，但是在multiprocessing中有替代品</p>
<ul>
<li>Queue和多线程中的一样，但是在multiprocessing中进程池是不适用的
<ul>
<li>在进程池中使用<code>Manager().Queue()</code>替代,后面俩方法适用于JoinableQueue和Manager的Queu</li>
<li><code>q.task_done()</code>：消费者使用此方法发出信号，表示q.get()的当前返回项目已经被处理</li>
<li><code>q.join()</code>：生产者调用此方法进行阻塞，直到队列中所有的项目均task_down处理</li>
</ul>
</li>
<li>全局去变量是不适用的，数据是隔离的</li>
<li>Pipe管道进行通信，简化版的Queue
<ul>
<li>一次定义，返回两个端<code>receive_pipe,send_pipe=Pipe()</code></li>
<li>只能适用于两个进程，使用send和recv通信</li>
<li>性能比Queue高</li>
</ul>
</li>
<li>共享内存操作，<code>Manager</code>
<ul>
<li>会把变量放到共享内存中去，常见的几个都有比如<code>dict()</code></li>
<li>不都是进程安全的，注意同步问题</li>
<li>单个<code>Manager</code>可以通过网络由不同计算机上的进程共享，但它们比使用共享内存慢。</li>
<li>生成器是无法被序列化的<code>TypeError: cannot pickle 'generator' object</code></li>
</ul>
</li>
</ul>
<details class="details custom-block"><summary>两个进程的Pipe和Queue测试</summary>
<p>个进程的Pipe和Queue测试</p>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> time  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> multiprocessing  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> multiprocessing </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Pipe,Queue  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> fun1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(arg1,q,p):  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"1 begin"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, arg1)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    time.sleep(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"1 end...."</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    temp</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">q.get()  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"队列中拿了"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,temp)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    p.send(temp)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> fun2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(arg2,q,p):  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    q.put(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"199"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"2 begin"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, arg2)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    time.sleep(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">4</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"2 end...."</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"管道拿回来"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,p.recv())  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">if</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __name__</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> ==</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> '__main__'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    q</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Queue(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">maxsize</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">10</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    recv_p,send_p</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Pipe()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    t1 </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> multiprocessing.Process(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">target</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">fun1, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">args</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"我是线程1"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,q,send_p))  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    t2 </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> multiprocessing.Process(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">target</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">fun2, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">args</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"我是线程2"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,q,recv_p))  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    t1.start()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    t2.start()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    t1.join()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    t2.join()</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br></div></div><p>运行结果</p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>1 begin 我是线程1</span></span>
<span class="line"><span>2 begin 我是线程2</span></span>
<span class="line"><span>1 end....</span></span>
<span class="line"><span>队列中拿了 199</span></span>
<span class="line"><span>2 end....</span></span>
<span class="line"><span>管道拿回来 199</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br></div></div></details>
<details class="details custom-block"><summary>Manager进程池通信+继承Process类</summary>
<p>anager进程池通信+继承Process类</p>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># -*-coding:utf-8-*-  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> multiprocessing  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> random  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> multiprocessing </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Manager  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> time  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 使用线程安全队列的生产消费者模型  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Productor</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">multiprocessing</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Process</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">):  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __init__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self, name,q,d):  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"初始化</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%s</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">进程:"</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> %</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> name)  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.q</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">q </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 实验队列  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.d</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">d </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 实验dict  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        super</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">().</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">__init__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">name</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">name)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> run</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self):  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        while</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> True</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            time.sleep(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0.5</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 假设每个生产者每0.5秒生产一个  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            value </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> random.randint(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1024</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">            self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.q.put(value)  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">            print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%s</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> Product : </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%d</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> %</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.name,value))  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> value</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">%</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">100</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">==</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 100的倍数就放入字典  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">                self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.d[</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">str</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(random.randint(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">4096</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">))]</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">value  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Consumer</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">multiprocessing</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Process</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">):  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __init__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self, name,q,d):  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"初始化</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%s</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">进程:"</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> %</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> name)  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.q</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">q </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 实验队列  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.d</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">d</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 实验dict  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        super</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">().</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">__init__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">name</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">name)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> run</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self):  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        while</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> True</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            time.sleep(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0.2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            temp </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.q.get()  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">            print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%s</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> Comsume : </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%d</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> %</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.name,temp))  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> temp</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">%</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">100</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">==</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 100的背书打印字典  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">                print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.d)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">if</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __name__</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> ==</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> '__main__'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    d</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Manager().dict()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    q </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Manager().Queue(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">maxsize</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">100</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 就一个参数，定义一个长度100的先进先出队列  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    pool</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[] </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 自制假进程池，我还没找到怎么用类同时用线程池  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> range</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">):  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        pool.append(Consumer(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">name</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"消费者</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%d</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> %</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> i,</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">q</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">q,</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">d</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">d))  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> range</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">5</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">):  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        pool.append(Productor(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">name</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"生产者</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%d</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> %</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> i,</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">q</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">q,</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">d</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">d))  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> pool:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        i.start()  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> pool:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        i.join()</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br></div></div><p>运行结果</p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>初始化消费者1进程:</span></span>
<span class="line"><span>初始化消费者2进程:</span></span>
<span class="line"><span>初始化生产者1进程:</span></span>
<span class="line"><span>初始化生产者2进程:</span></span>
<span class="line"><span>初始化生产者3进程:</span></span>
<span class="line"><span>初始化生产者4进程:</span></span>
<span class="line"><span>...</span></span>
<span class="line"><span>生产者2 Product : 227</span></span>
<span class="line"><span>消费者1 Comsume : 699</span></span>
<span class="line"><span>消费者1 Comsume : 522</span></span>
<span class="line"><span>消费者2 Comsume : 100</span></span>
<span class="line"><span>{'3112': 100}</span></span>
<span class="line"><span>生产者4 Product : 872</span></span>
<span class="line"><span>生产者3 Product : 982</span></span>
<span class="line"><span>消费者2 Comsume : 872</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br></div></div></details>
<p>#TODO 细化多线程多进程的东西
多线程线程池的函数</p>
<ul>
<li><a href="https://blog.csdn.net/panguangyuu/article/details/105335900" target="_blank" rel="noreferrer">Python concurrent.futures 的 as_completed 函数解释_潘广宇的博客-CSDN博客</a></li>
<li><a href="https://blog.csdn.net/u012183105/article/details/88909955" target="_blank" rel="noreferrer">Python多线程使用concurrent.futures.as_completed方法下的一个坑_Grady.Lo的博客-CSDN博客</a></li>
</ul>
<h3 id="进程本地socket通信" tabindex="-1">进程本地socket通信 <a class="header-anchor" href="#进程本地socket通信" aria-label="Permalink to &quot;进程本地socket通信&quot;">&ZeroWidthSpace;</a></h3>
<p>#TODO 进程本地socket通信
可算完了</p>
<hr>
<h2 id="协程和异步" tabindex="-1">协程和异步 <a class="header-anchor" href="#协程和异步" aria-label="Permalink to &quot;协程和异步&quot;">&ZeroWidthSpace;</a></h2>
<h3 id="io多路复用和c10k" tabindex="-1">IO多路复用和C10K <a class="header-anchor" href="#io多路复用和c10k" aria-label="Permalink to &quot;IO多路复用和C10K&quot;">&ZeroWidthSpace;</a></h3>
<div class="tip custom-block"><p class="custom-block-title">[💡Tip]</p>
<p>这一章是讲解比较底层机制的，应用的时候能查到即可，不用熟练掌握</p>
</div>
<p>并发是一个时刻内只有一个程序运行在一个CPU上，并行是在一个时刻内多个程序运行在多个CPU上，最多和CPU核数一样<br>
消息通信机制同步异步是是否等待IO操作<br>
阻塞和非阻塞是指当前线程是否会被挂起<br>
C10K问题，1999年提出来的的技术挑战，使用1Ghz 2GB内存 1gbps下为1万个用户提供FTP服务<br>
C10M问题，如何利用 8 核心 CPU,64G 内存，在 10gbps 的网络上保持 1000 万并发连接</p>
<h4 id="unix下的五种io模型" tabindex="-1">Unix下的五种IO模型 <a class="header-anchor" href="#unix下的五种io模型" aria-label="Permalink to &quot;Unix下的五种IO模型&quot;">&ZeroWidthSpace;</a></h4>
<ul>
<li>阻塞式 I/O</li>
<li>非阻塞式 I/O</li>
<li>I/O复用</li>
</ul>
<blockquote>
<p>select 目前几乎在所有的平台上支特，其良好跨平台支持也是它的一个优点。select 的一个缺点在于单个进程能够监视的文件描述符的数量存在最大限制，在 Liux 上一般为 1024，可以通过修改宏定义甚至重新编译内核的方式提升这一限制，但是这样也会造成效率的降低。
select,pol,epoll都是IO多路复用的机制。I/O多路复用就是通过一种机制，一个进程可以监视多个描述符，一旦某个描述符就绪（一般是读就绪或者写就绪），能够通知程序进行相应的读写操作。但 select, poll，epoll本质上都是同步I/O,因为他们都需要在读写事件就绪后自己负责进行读写 也就是说这个读写过程是阻塞的
而异步IO则无需自己负责进行读写，异步I/O的实现会负责把数据从内核拷贝到用户空间。</p>
<p>Select 函数监视的文件描述符分 3 类，分别是 writefds、readfds、和 exceptfds。。调用后 selecti 函数会阻塞，直到有描述副就绪（有数据可读、可写、或者有 except），或者超时（timeout 指定等待时间，如果立即返回设为 null 即可），函数返回。当 selecti 函数返回后，可以通过遍历 fdset，来找到就绪的描述符。</p>
<p>不同与 select 使用三个位图来表示三个 fdset 的方式，pol 使用一个 pollfd 的指针实现。
pollfd 结构包含了要监视的 eventi和发生的 event，不再使用 select“参数-值”传递的方式。同时，po 川 fd 并没有最大数量限制（但是数量过大后性能也是会下降）。和 selecti 函数一样，poll 返回后，需要轮询 oollfd 来获取就绪的描述符。
从上面看，select 和 pol 都需要在返回后，通过遍历文件描述符来获取已经就绪的 socket。事实上，同时连接的大量客户端在一时刻可能只有很少的处于就绪状态，因此随着监视的描述符数量的增长，其效率也会线性下降</p>
<p>epoll 是在 2.6 内核中提出的，是之前的 select 和 poll 的增强版本。相对于 select 和 poll 来说，epoll 更加灵活，没有描述符限制。epollf 使用一个文件描述符管理多个描述符，将用户关系的文件描述符的事件存放到内核的一个事件表中，这样在用户空间和内核空间的 copy 只需一次,使用红黑树实现，效率高</p>
</blockquote>
<ul>
<li>信号驱动式 I/O</li>
<li>异步I/O(POSIX的aio_系列函数）
#TODO 这里以后等着链接到详解Linux IO多路复用的地方</li>
</ul>
<details class="details custom-block"><summary>使用非阻塞IO进行socket</summary>
<p>用非阻塞IO进行socket</p>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> socket  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> urllib.parse </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> urlparse  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"""非阻塞IO"""</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> get_url</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(url):  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    #通过socket请求html  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    url </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> urlparse(url)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    host </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> url.netloc  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    path </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> url.path  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> path </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">==</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> ""</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        path </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "/"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    #建立socket连接  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    client </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> socket.socket(socket.</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">AF_INET</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, socket.</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">SOCK_STREAM</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    client.setblocking(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">False</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 设置为非阻塞  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    while</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> True</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        try</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            client.connect((host, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">80</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 阻塞不会消耗cpu，阻塞回报错，其实已经发出去了  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        except</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> BlockingIOError</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> as</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> e :  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            pass</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        except</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> OSError</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> as</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> e:  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            break</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    while</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> True</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        try</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            client.send(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"GET </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">{}</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> HTTP/1.1</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">\r\n</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">Host:</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">{}\r\n</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">Connection:close</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">\r\n\r\n</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.format(path, host).encode(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"utf8"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">))  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            break</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        except</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> OSError</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> as</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> e :  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            pass</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    data </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> b</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">""</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    while</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> True</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        try</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            d </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> client.recv(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1024</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        except</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> BlockingIOError</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> as</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> e :  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            continue</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> d:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            data </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> d  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        else</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            break</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    data </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> data.decode(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"utf8"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    html_data </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> data.split(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">\r\n\r\n</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x3C;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">br</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">/></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(html_data)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    client.close()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">if</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __name__</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> ==</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "__main__"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> url </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> range</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">20</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">):  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        url </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "http://www.baidu.com/"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        get_url(url)</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br><span class="line-number">50</span><br><span class="line-number">51</span><br></div></div><p>运行结果</p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>&#x3C;!DOCTYPE html>&#x3C;html>&#x3C;head>&#x3C;meta http-...</span></span>
<span class="line"><span>&#x3C;!DOCTYPE html>&#x3C;html>&#x3C;head>&#x3C;meta http-...</span></span>
<span class="line"><span>&#x3C;!DOCTYPE html>&#x3C;html>&#x3C;head>&#x3C;meta http-...</span></span>
<span class="line"><span>&#x3C;!DOCTYPE html>&#x3C;html>&#x3C;head>&#x3C;meta http-...</span></span>
<span class="line"><span>...</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br></div></div></details>
<h4 id="selector" tabindex="-1">selector <a class="header-anchor" href="#selector" aria-label="Permalink to &quot;selector&quot;">&ZeroWidthSpace;</a></h4>
<p>python中直接使用select不多，都是用selector内部它也是select实现的，DefaultSelector会根据平台自动选择三种非阻塞IO模式<br>
<a href="https://learnku.com/docs/pymotw/selectors-io-multiplexing-abstractions/3428" target="_blank" rel="noreferrer">12.4. selectors — I/O 多路复用抽象层 | 网络模块 |《Python 3 标准库实例教程》| Python 技术论坛</a><br>
#TODO 这个Selector我是真没看懂咋回事</p>
<details class="details custom-block"><summary>教程给的代码，以后再改吧</summary>
<p>程给的代码，以后再改吧</p>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#1. epoll并不代表一定比select好  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 在并发高的情况下，连接活跃度不是很高， epoll比select  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 并发性不高，同时连接很活跃， select比epoll好  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#通过非阻塞io实现http请求  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># select + 回调 + 事件循环  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#  并发性高  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 使用单线程  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> socket  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> urllib.parse </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> urlparse  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> selectors </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> DefaultSelector, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">EVENT_READ</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">EVENT_WRITE</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">selector </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> DefaultSelector()  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#使用select完成http请求  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">urls </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> []  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">stop </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> False</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Fetcher</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> connected</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self, key):  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        selector.unregister(key.fd)  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.client.send(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"GET </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">{}</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> HTTP/1.1</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">\r\n</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">Host:</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">{}\r\n</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">Connection:close</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">\r\n\r\n</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.format(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.path, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.host).encode(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"utf8"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">))  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        selector.register(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.client.fileno(), </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">EVENT_READ</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.readable)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> readable</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self, key):  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        d </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.client.recv(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1024</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> d:  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">            self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.data </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> d  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        else</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            selector.unregister(key.fd)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            data </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.data.decode(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"utf8"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            html_data </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> data.split(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">\r\n\r\n</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x3C;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">br</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">/></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">            print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(html_data)  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">            self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.client.close()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            urls.remove(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.spider_url)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            if</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> not</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> urls:  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">                global</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> stop  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">                stop </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> True</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> get_url</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self, url):  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.spider_url </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> url  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        url </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> urlparse(url)  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.host </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> url.netloc  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.path </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> url.path  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.data </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> b</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">""</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        if</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.path </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">==</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> ""</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">            self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.path </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "/"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        # 建立socket连接  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.client </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> socket.socket(socket.</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">AF_INET</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, socket.</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">SOCK_STREAM</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.client.setblocking(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">False</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        try</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">            self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.client.connect((</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.host, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">80</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">))  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 阻塞不会消耗cpu  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        except</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> BlockingIOError</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> as</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> e:  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            pass</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        #注册  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        selector.register(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.client.fileno(), </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">EVENT_WRITE</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.connected)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> loop</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">():  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    #事件循环，不停的请求socket的状态并调用对应的回调函数  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    #1. select本身是不支持register模式  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    #2. socket状态变化以后的回调是由程序员完成的  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    while</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> not</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> stop:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        ready </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> selector.select()  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> key, mask </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> ready:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            call_back </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> key.data  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            call_back(key)  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    #回调+事件循环+select(poll\epoll)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">if</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __name__</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> ==</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "__main__"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    fetcher </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Fetcher()  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> time  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    start_time </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> time.time()  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> url </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> range</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">20</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">):  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        url </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "http://shop.projectsedu.com/goods/</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">{}</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">/"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.format(url)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        urls.append(url)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        fetcher </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Fetcher()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        fetcher.get_url(url)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    loop()  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(time.time()</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">start_time)</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br><span class="line-number">50</span><br><span class="line-number">51</span><br><span class="line-number">52</span><br><span class="line-number">53</span><br><span class="line-number">54</span><br><span class="line-number">55</span><br><span class="line-number">56</span><br><span class="line-number">57</span><br><span class="line-number">58</span><br><span class="line-number">59</span><br><span class="line-number">60</span><br><span class="line-number">61</span><br><span class="line-number">62</span><br><span class="line-number">63</span><br><span class="line-number">64</span><br><span class="line-number">65</span><br><span class="line-number">66</span><br><span class="line-number">67</span><br><span class="line-number">68</span><br><span class="line-number">69</span><br><span class="line-number">70</span><br><span class="line-number">71</span><br><span class="line-number">72</span><br><span class="line-number">73</span><br><span class="line-number">74</span><br><span class="line-number">75</span><br><span class="line-number">76</span><br><span class="line-number">77</span><br><span class="line-number">78</span><br><span class="line-number">79</span><br><span class="line-number">80</span><br><span class="line-number">81</span><br><span class="line-number">82</span><br><span class="line-number">83</span><br><span class="line-number">84</span><br><span class="line-number">85</span><br></div></div><p>运行结果</p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span></span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div></details>
<h5 id="回调的缺陷" tabindex="-1">回调的缺陷 <a class="header-anchor" href="#回调的缺陷" aria-label="Permalink to &quot;回调的缺陷&quot;">&ZeroWidthSpace;</a></h5>
<ol>
<li>编程过程四分五裂，维护麻烦</li>
<li>出现错误的时候调试困难</li>
<li>异常处理和边界条件处理麻烦</li>
<li>有数据需要多次处理很麻烦</li>
<li>管理共享变量困难</li>
</ol>
<h4 id="example-4用selector-socket实现群聊" tabindex="-1">example-4用selector+socket实现群聊 <a class="header-anchor" href="#example-4用selector-socket实现群聊" aria-label="Permalink to &quot;example-4用selector+socket实现群聊&quot;">&ZeroWidthSpace;</a></h4>
<p>#TODO 这个selector+socket比较难，以后在搞</p>
<h3 id="原生协程" tabindex="-1">原生协程 <a class="header-anchor" href="#原生协程" aria-label="Permalink to &quot;原生协程&quot;">&ZeroWidthSpace;</a></h3>
<ol>
<li>回调模式编码复杂度高</li>
<li>同步编程的并发性不高</li>
<li>多线程编程需要线程间同步，Lock还会影响性能</li>
</ol>
<p>理想调度:</p>
<ol>
<li>采用同步的方式去编写异步的代码</li>
<li>使用单线程去切换任务：
<ol>
<li>线程是由操作系统切换的，单线程切换意味着我们需要程序员自己去调度任务和函数</li>
<li>不在需要锁，并发性高，如果单线程内切换函数，性能远高于线程切换，并发性更高</li>
</ol>
</li>
</ol>
<p>这就需要我们要暂停函数并且合适的时候恢复<br>
Coroutine<a href="https://zh.wikipedia.org/wiki/%E5%8D%8F%E7%A8%8B" target="_blank" rel="noreferrer">协程</a>就是有多个入口的函数，可以暂停的函数，可以向暂停的地方传入值</p>
<p>3.5以后直接引入了async await定义原生协程，调用和激活的时候要<code>send(None)</code>next不能用<br>
引入协程关键字避免代码混乱，将协程和生成器区分开<br>
async里面是<mark>不能定义yield</mark>的，使用<code>async def fun()</code>将一个函数定义为协程，即一个<code>Awaitable</code>对象,函数体内使用await交出控制权。<br>
await后面声明一个<code>Awaitable</code>对象(实现<code>__await__()</code>)，@types.coroutine装饰器也是包装实现这个魔法函数<br>
可以将await解读为yield from<br>
这俩东西比不比yield性能高，但是编码维护顺畅很多，一般用这俩就行</p>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">async</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> B</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">():  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "back!"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">async</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> A</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">():  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    b </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> await</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> B()  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> b  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">coro</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">A()  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(coro.send(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">None</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">))</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#----结果----</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Traceback (most recent call last):</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  File </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"/Users/jack/code/py/AdvancedPython/asyncio_prac/await-async.py"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, line </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">9</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> &#x3C;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">module</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">></span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(coro.send(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">None</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">))</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">StopIteration</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: back!</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br></div></div><div class="warning custom-block"><p class="custom-block-title">[⚠️Warning]</p>
<p>协程是单线程的，异步代码中不要使用阻塞操作，应该把控制权交出去？<br>
<strong>使用多线程扔给其他线程阻塞着，密集计算就扔给多进程</strong>
协程必须搭配事件循环使用，单独用没意义，asyncio提供了合适的接口和事件循环<br>
<a href="https://hatboy.github.io/2019/02/16/Python%E5%BC%82%E6%AD%A5%E7%BC%96%E7%A8%8B%E8%AF%A6%E8%A7%A3/" target="_blank" rel="noreferrer">异步io详解</a> 这个人写的太厉害了，甚至令人惊叹<br>
<a href="https://www.cnblogs.com/ssyfj/p/9222342.html" target="_blank" rel="noreferrer">这个</a>也行</p>
</div>
<h3 id="asyncio并发" tabindex="-1">asyncio并发 <a class="header-anchor" href="#asyncio并发" aria-label="Permalink to &quot;asyncio并发&quot;">&ZeroWidthSpace;</a></h3>
<h4 id="基本用法和嵌套" tabindex="-1">基本用法和嵌套 <a class="header-anchor" href="#基本用法和嵌套" aria-label="Permalink to &quot;基本用法和嵌套&quot;">&ZeroWidthSpace;</a></h4>
<p>提供了不同系统的事件循环，传输协议抽象，实现了异步的Future类，必须使用将产生阻塞IO的调用时，有接口可以把这个事件转移到线程池<br>
twisted，gevent都是利用这个实现的<br>
一个线程里面只有一个eventloop，没有就会自己获得</p>
<p>协程的使用流程是，定义协程函数-&gt;构建协程对象-&gt;提交到协程池-&gt;loop-&gt;拿到结果</p>
<p>Future其本质上是一个容器，用于接受异步执行的结果，用到的并不多可以加深理解</p>
<blockquote>
<p>Furture 对象内部封装了一个 <code>_state</code>，这个 <code>_state</code> 维护着四种状态：<strong>Pending</strong>、<strong>Running</strong>、<strong>Done</strong>，<strong>Cancelled</strong>，如果变成 <code>Done</code> 完成，就不再等待，而是往后执行，这四种状态的存在其实类似与进程的 运行态、就绪态、阻塞态，事件循环凭借着四种状态对 Future协程对象 进行调度。</p>
</blockquote>
<p>Task 核心作用是<strong>在事件循环中添加多个并发任务</strong>；</p>
<blockquote>
<p>Python 3.7 以后的版本支持 <code>asyncio.create_task()</code>，在此之前的写法为 <code>loop.create_task()</code>，开发过程中需要注意代码写法对不同版本 python 的兼容性。</p>
</blockquote>
<details class="details custom-block"><summary>asyncio的基本用法</summary>
<p>syncio的基本用法</p>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># -*-coding:utf-8-*-  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> asyncio  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> random  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> time  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> functools </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> partial  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">async</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> func1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(arg1):  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"start...fun1"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    s</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=await</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> func2(arg1) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 协程是可以套起来的  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(s)  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"end...fun1"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> s  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">async</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> func2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(arg1):  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"start...fun2"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    x</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">random.randint(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">5</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    await</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> asyncio.sleep(x) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 随机睡，注意返回顺序  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(arg1)  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"end...fun2"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "sleep</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%s</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> s"</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">%</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">x  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> callback</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(arg1,future</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">None</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">):</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 传了一个Future(task)对象，它必须是最后一个参数  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(arg1) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 其他的arg使用functools.partial包装成函数引用  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"callback"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">if</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __name__</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">==</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"__main__"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    start_time</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">time.time()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    loop</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">asyncio.get_event_loop()  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    # -----使用future对象-----  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    # futures=[asyncio.ensure_future(func1("i am arg")) for i in range(0,4)] # 整10个协程,注意接口形状  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    # loop.run_until_complete(asyncio.wait(futures)) # 提交到协程池  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    # for i in futures:  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    #     print(i.result()) # 获得future对象的结果  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    # -----使用task对象-----  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    tasklist</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[]  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> range</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">4</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">):  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        temp</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">loop.create_task(func1(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"i am arg"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">))  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        temp.add_done_callback(partial(callback,</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"this is arg1"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># callback要传入引用  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        tasklist.append(temp) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># task对象和Future一模一样，task是子类  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    loop.run_until_complete(asyncio.wait(tasklist)) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 不要一个一个运行，使用wait一起运行，也可以提交单个  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> tasklist:  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'result:'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,i.result())  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    end_time</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">time.time()  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(end_time</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">start_time)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    # asyncio.wiat return_when可以设置loop什么时候进行下一步，点进定义可以看  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    # asyncio.gather 更加高层，可以分组控制，传入协程列表的时候要加*才行，有什么函数自己看  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    group1 </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> [func1(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"http://projectsedu.com"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> range</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)]  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    group2 </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> [func1(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"http://www.imooc.com"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> range</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)]  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    group1 </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> asyncio.gather(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">group1)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    group2 </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> asyncio.gather(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">group2)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    group2.cancel()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    loop.run_until_complete(asyncio.wait(futures))</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br><span class="line-number">50</span><br><span class="line-number">51</span><br><span class="line-number">52</span><br><span class="line-number">53</span><br><span class="line-number">54</span><br></div></div><p>运行结果</p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>start...fun1</span></span>
<span class="line"><span>start...fun2</span></span>
<span class="line"><span>start...fun1</span></span>
<span class="line"><span>start...fun2</span></span>
<span class="line"><span>start...fun1</span></span>
<span class="line"><span>start...fun2</span></span>
<span class="line"><span>start...fun1</span></span>
<span class="line"><span>start...fun2</span></span>
<span class="line"><span>i am arg</span></span>
<span class="line"><span>end...fun2</span></span>
<span class="line"><span>sleep2 s</span></span>
<span class="line"><span>end...fun1</span></span>
<span class="line"><span>this is arg1</span></span>
<span class="line"><span>callback</span></span>
<span class="line"><span>i am arg</span></span>
<span class="line"><span>end...fun2</span></span>
<span class="line"><span>sleep3 s</span></span>
<span class="line"><span>end...fun1</span></span>
<span class="line"><span>i am arg</span></span>
<span class="line"><span>end...fun2</span></span>
<span class="line"><span>sleep3 s</span></span>
<span class="line"><span>end...fun1</span></span>
<span class="line"><span>this is arg1</span></span>
<span class="line"><span>callback</span></span>
<span class="line"><span>this is arg1</span></span>
<span class="line"><span>callback</span></span>
<span class="line"><span>i am arg</span></span>
<span class="line"><span>end...fun2</span></span>
<span class="line"><span>sleep5 s</span></span>
<span class="line"><span>end...fun1</span></span>
<span class="line"><span>this is arg1</span></span>
<span class="line"><span>callback</span></span>
<span class="line"><span>result: sleep3 s</span></span>
<span class="line"><span>result: sleep5 s</span></span>
<span class="line"><span>result: sleep2 s</span></span>
<span class="line"><span>result: sleep3 s</span></span>
<span class="line"><span>5.001136779785156</span></span>
<span class="line"><span>start...fun1</span></span>
<span class="line"><span>start...fun2</span></span>
<span class="line"><span>start...fun1</span></span>
<span class="line"><span>start...fun2</span></span>
<span class="line"><span>Traceback (most recent call last):</span></span>
<span class="line"><span>  File "/Users/jack/code/py/AdvancedPython/asyncio_prac/asyncio-2.py", line 54, in &#x3C;module></span></span>
<span class="line"><span>    loop.run_until_complete(asyncio.gather(group1, group2)) # group2已经cancle掉了，所以会报错</span></span>
<span class="line"><span>  File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/asyncio/base_events.py", line 616, in run_until_complete</span></span>
<span class="line"><span>    return future.result()</span></span>
<span class="line"><span>asyncio.exceptions.CancelledError</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br></div></div></details>
<p>loop 阶段有两个方法，一个是<code>run_until_complete</code>,一个是<code>run_forever</code>，前者在后者的基础上中添加了一个callback让loop停止，loop对象会被放到future中（这一点很反直觉），所以任意一个future任务都可以停止掉loop<br>
比如协程写数据库的时候有一个future出错未进行的future都停掉<br>
<code>asyncio.all_tasks(loop)</code>注意新版的获取所有任务需要传入loop</p>
<details class="details custom-block"><summary>取消task</summary>
<p>消task</p>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># -*-coding:utf-8-*-  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> asyncio  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> random  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> time  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> functools </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> partial  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">async</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> func1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(arg1):  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"start...fun1"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    s</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=await</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> asyncio.sleep(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># func2(arg1) # 协程是可以套起来的  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(s)  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"end...fun1"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> s  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">async</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> func2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(arg1):  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"start...fun2"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    x</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">random.randint(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">10</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    await</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> asyncio.sleep(x) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 随机睡，注意返回顺序  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(arg1)  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"end...fun2"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "sleep</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%s</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> s"</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">%</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">x  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> callback</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(arg1,future</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">None</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">):</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 传了一个Future(task)对象，它必须是最后一个参数  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(arg1) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 其他的arg使用functools.partial包装成函数引用  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"callback"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">if</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __name__</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">==</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"__main__"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    start_time</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">time.time()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    #loop=asyncio.get_event_loop()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    loop </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> asyncio.new_event_loop()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    asyncio.set_event_loop(loop)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    tasklist</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[]  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> range</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">4</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">):  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        temp</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">loop.create_task(func1(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"i am arg"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">))  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        temp.add_done_callback(partial(callback,</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"this is arg1"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># callback要传入引用  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        tasklist.append(temp) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># task对象和Future一模一样，future是子类  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    #loop.run_until_complete(asyncio.wait(tasklist))  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    try</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        loop.run_until_complete(asyncio.wait(tasklist)) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 不要一个一个运行，使用wait一起运行，也可以提交单个  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    except</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> KeyboardInterrupt</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> as</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> e:  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(loop.is_running())  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        all_tasks</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">asyncio.all_tasks(loop) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 获取所有的task,注意传入loop  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> task </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> all_tasks:  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">            print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"cancel task"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            task.cancel() </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 取消任务  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        loop.stop() </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 暂停loop  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        loop.run_forever() </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 别忘了loop run forever  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    finally</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        loop.close() </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 最后正常关闭,close会关闭队列执行器等一系列东西  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> tasklist:  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'result:'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,i.result())  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    end_time</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">time.time()  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(end_time</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">start_time)</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br><span class="line-number">50</span><br><span class="line-number">51</span><br><span class="line-number">52</span><br><span class="line-number">53</span><br></div></div><p>运行结果</p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>start...fun1</span></span>
<span class="line"><span>start...fun1</span></span>
<span class="line"><span>start...fun1</span></span>
<span class="line"><span>start...fun1</span></span>
<span class="line"><span>Traceback (most recent call last):</span></span>
<span class="line"><span>  File "/Users/jack/code/py/AdvancedPython/asyncio_prac/asyncio-3.py", line 50, in &#x3C;module></span></span>
<span class="line"><span>    print('result:',i.result())</span></span>
<span class="line"><span>asyncio.exceptions.CancelledError</span></span>
<span class="line"><span>False</span></span>
<span class="line"><span>cancel task</span></span>
<span class="line"><span>cancel task</span></span>
<span class="line"><span>cancel task</span></span>
<span class="line"><span>cancel task</span></span>
<span class="line"><span>cancel task</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br></div></div></details>
<p>嵌套协程代码在上面，返回顺序是这样的，可以看到第子协程的返回值是什么时候到达上一级的<br>
<img src="./static/Python语言进阶_images_12.png" alt=""></p>
<ul>
<li>使用<code>loop.call_soon(func, arg)</code>是等待loop下一个循环到来的时候立即执行
<ul>
<li><code>loop.call_soon_threadsafe(func, arg)</code>是线程安全方法</li>
<li>call_soon比call_later快,因为call_later是loop开始后几秒调用，soon是立刻调用</li>
</ul>
</li>
<li>使用<code>loop.call_later(time,func, arg)</code>是等待loop开始后几秒开始运行</li>
<li>使用<code>loop.call_at(now+2, callback, 2, loop)</code>，在系统指定时间运行
<ul>
<li>需要使用<code>now=asyncio.time()</code>获得时钟时间，使用now作为基准延后几秒运行</li>
</ul>
</li>
<li><code>async for i in l</code>可以将for 异步化
<ul>
<li>一个对象必须实现<code>__aiter__</code>方法，该方法返回一个异步迭代器（asynchronous iterator）对象</li>
<li>一个异步迭代器对象必须实现<code>__anext__</code>方法，该方法返回一个awaitable类型的值。</li>
<li>为了停止迭代，<code>__anext__</code>必须抛出一个<code>StopAsyncIteration</code>异常。</li>
</ul>
</li>
<li>异步上下文管理器<code>async with</code>
<ul>
<li><code>__aenter__</code> 和<code>__aexit__</code>。这两个方法都要返回一个 awaitable类型的值。
上面这俩可以看PEP 479</li>
</ul>
</li>
</ul>
<div class="warning custom-block"><p class="custom-block-title">[❓Question]</p>
<p>其实还是不太明白，at的机制是什么时候调用，是安排在时间插值的任务之前之后还是指定时间的下次loop?<br>
但是好像不太影响</p>
</div>
<p>其实asyncio可以做tcp和udp，但是这俩最好直接gevent和twisted，async的话真碰到需求了再去查<br>
所以就先不写了，直接看aiohtt，进阶的话再说<br>
<a href="https://cloud.ooowl.fun/api/v3/file/source/1112/13-7%20future%20%E5%92%8C%20task.mp4?sign=YrHo6p-Pti28cdytaPH_zb-XEW37FpRhktB0UnYJ4fc%3D%3A0" target="_blank" rel="noreferrer">task是Future</a>线程和协程之间的桥梁</p>
<h3 id="协程同步" tabindex="-1">协程同步 <a class="header-anchor" href="#协程同步" aria-label="Permalink to &quot;协程同步&quot;">&ZeroWidthSpace;</a></h3>
<p><a href="https://segmentfault.com/a/1190000041568839" target="_blank" rel="noreferrer">并发异步编程之争：协程(asyncio)到底需不需要加锁？(线程/协程安全/挂起/主动切换)Python3 - SegmentFault 思否</a>
简单来说协程保证最终一致性，中间状态还是混乱的</p>
<p>锁和多线程里面一样，有Lock Condition Semaphore Event，提供Queue和PriorityQueue<br>
锁实现的是<code>__aenter__</code> <code>__aexit__</code>锁住之后就是同步的了，使用锁可以<code>async with</code>和<code>async lock.acquire</code><br>
Queue实际上最大的作用就是max_size，如果不介意的话直接用普通变量就可以</p>
<h3 id="aiohttp和aiomysql" tabindex="-1">aiohttp和aiomysql <a class="header-anchor" href="#aiohttp和aiomysql" aria-label="Permalink to &quot;aiohttp和aiomysql&quot;">&ZeroWidthSpace;</a></h3>
<p>aiohttp可以用来写高并发爬虫，其实也不用那么高并发 ，但是真的好炫酷<br>
即可以当server又可以client</p>
<h3 id="example-5aiohttp实现高并发爬虫" tabindex="-1">example-5aiohttp实现高并发爬虫 <a class="header-anchor" href="#example-5aiohttp实现高并发爬虫" aria-label="Permalink to &quot;example-5aiohttp实现高并发爬虫&quot;">&ZeroWidthSpace;</a></h3>
<ul>
<li>使用aiohttp编写非阻塞爬虫</li>
<li>使用信号量机制限制爬取频率</li>
<li>把example-1元类实现ORM修改为aiomysql异步的ORM并使用
<ul>
<li>只需要修改save函数的保存部分，甚至可以封装一下</li>
</ul>
</li>
<li>调试
<img src="./static/Python语言进阶_images_13.png" alt="500|"></li>
</ul>
<details class="details custom-block"><summary>简略版异步高并发爬虫</summary>
<p>略版异步高并发爬虫</p>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># -*-coding:utf-8-*-  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> time  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> asyncio </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Queue  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> aiohttp  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> asyncio  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> aiofiles  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> aiomysql  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> pyquery </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> PyQuery  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">unCrawledQ </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Queue(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">maxsize</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">100</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 待爬队列  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Crawled </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> set</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 已经爬完的队列，set去重  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">RelatedQ </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Queue(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">maxsize</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">100</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">htmlContentQ </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Queue(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">maxsize</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">100</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 未清洗队列  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">resultQ </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Queue(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">maxsize</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">100</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 待插入sql队列  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">sem </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> asyncio.Semaphore(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 信号量控制获取内容的并发为3  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">semR </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> asyncio.Semaphore(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 信号量控制获取相关的并发为3 # 如何共用信号不锁住?  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">_running </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> True</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  # 控制整个程序的起停  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">async</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Spider</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">():  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 获取内容  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    while</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> _running:  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        await</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> sem.acquire()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        urlid </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> await</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> unCrawledQ.get()  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 获得一个没有爬过的  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        async</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> with</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> aiohttp.ClientSession() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">as</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> session:  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 如何共用session?  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            url </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> f</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'https://segmentfault.com/a/</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">{</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">urlid</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">}</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            async</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> with</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> session.get(url) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">as</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> response:  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">                print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Status:"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, response.status, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"url:"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, url)  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 输出信息  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">                html </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> await</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> response.text()  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 获取列表  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">                await</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> htmlContentQ.put(html)  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 把内容添加到内容队列  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">                Crawled.add(urlid)  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 添加id到已爬取列表  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">                await</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> RelatedQ.put(urlid)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        sem.release()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">async</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Related</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">():  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 解析这个文章关联的url  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    while</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> _running:  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        await</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> semR.acquire()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        urlid </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> await</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> RelatedQ.get()  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 从带关联队列获取一个id  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        async</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> with</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> aiohttp.ClientSession() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">as</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> session:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            url </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> f</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'https://segmentfault.com/gateway/article/</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">{</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">urlid</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">}</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">/related'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            async</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> with</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> session.get(url) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">as</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> response:  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">                print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Status:"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, response.status, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"related:"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, urlid)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">                data </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> await</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> response.json()  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 从借口获取json  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">                for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> data:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">                    urlid </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> i[</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"id"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">                    if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> urlid </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">not</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> in</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Crawled:  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 没爬过  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">                        await</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> unCrawledQ.put(urlid)  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 添加到队列  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">                        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"add:"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, urlid)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        semR.release()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">async</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Extart_Header</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">():  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    while</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> _running:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        item </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> await</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> htmlContentQ.get()  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 拿出一个html内容  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        pq </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> PyQuery(item)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        await</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Insert(pq(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"h1"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"a"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">).text())  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        time.sleep(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">async</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Insert</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(result):  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 异步插入mysql  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    async</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> with</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> aiofiles.open(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"2.txt"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"a"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">encoding</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"utf8"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">as</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> f:  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        await</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> f.write(result)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    pool </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> await</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> aiomysql.create_pool(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">host</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"127.0.0.1"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 插一次建立一次connection，合适吗?  </span></span>
<span class="line"><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">                                      port</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">3306</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">user</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"root"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,  </span></span>
<span class="line"><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">                                      password</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"1118"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,  </span></span>
<span class="line"><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">                                      db</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"aiosql"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,  </span></span>
<span class="line"><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">                                      loop</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">""</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,  </span></span>
<span class="line"><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">                                      charset</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"utf8"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,  </span></span>
<span class="line"><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">                                      autocommit</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">True</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    async</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> with</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> pool.acquire() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">as</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> conn:  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        async</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> with</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> conn.cursor() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">as</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> cur:  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            await</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> cur.execute(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"INSERT INTO tittle VALUE </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">{}</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.format(result))  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">async</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> init</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">():  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    await</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> unCrawledQ.put(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"1190000041885333"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">if</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __name__</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> ==</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> '__main__'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    # session获取完后不要关闭，可以当作参数到处传，避免重复请求session连接  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    group1 </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> [Spider() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> range</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">4</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)]  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    group2 </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> [Related() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> range</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)]  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    group1.append(init())  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 初始化协程，只运行一次  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    group3 </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> [Extart_Header() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> range</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)]  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    group1 </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> asyncio.gather(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">group1)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    group2 </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> asyncio.gather(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">group2)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    group3 </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> asyncio.gather(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">group3)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    loop </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> asyncio.get_event_loop()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    loop.run_until_complete(asyncio.gather(group1, group2, group3))  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    loop.run_forever()</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br><span class="line-number">50</span><br><span class="line-number">51</span><br><span class="line-number">52</span><br><span class="line-number">53</span><br><span class="line-number">54</span><br><span class="line-number">55</span><br><span class="line-number">56</span><br><span class="line-number">57</span><br><span class="line-number">58</span><br><span class="line-number">59</span><br><span class="line-number">60</span><br><span class="line-number">61</span><br><span class="line-number">62</span><br><span class="line-number">63</span><br><span class="line-number">64</span><br><span class="line-number">65</span><br><span class="line-number">66</span><br><span class="line-number">67</span><br><span class="line-number">68</span><br><span class="line-number">69</span><br><span class="line-number">70</span><br><span class="line-number">71</span><br><span class="line-number">72</span><br><span class="line-number">73</span><br><span class="line-number">74</span><br><span class="line-number">75</span><br><span class="line-number">76</span><br><span class="line-number">77</span><br><span class="line-number">78</span><br><span class="line-number">79</span><br><span class="line-number">80</span><br><span class="line-number">81</span><br><span class="line-number">82</span><br><span class="line-number">83</span><br><span class="line-number">84</span><br><span class="line-number">85</span><br><span class="line-number">86</span><br><span class="line-number">87</span><br><span class="line-number">88</span><br><span class="line-number">89</span><br><span class="line-number">90</span><br><span class="line-number">91</span><br><span class="line-number">92</span><br><span class="line-number">93</span><br><span class="line-number">94</span><br></div></div><p>运行结果</p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>Status: 200 url: https://segmentfault.com/a/1190000041885333</span></span>
<span class="line"><span>Status: 200 related: 1190000041885333</span></span>
<span class="line"><span>add: 1190000041787331</span></span>
<span class="line"><span>add: 1190000023009604</span></span>
<span class="line"><span>add: 1190000022525379</span></span>
<span class="line"><span>add: 1190000017462391</span></span>
<span class="line"><span>add: 1190000039678637</span></span>
<span class="line"><span>add: 1190000007791891</span></span>
<span class="line"><span>add: 1190000003484673</span></span>
<span class="line"><span>Status: 200 url: https://segmentfault.com/a/1190000041787331</span></span>
<span class="line"><span>Status: 200 url: https://segmentfault.com/a/1190000023009604</span></span>
<span class="line"><span>Status: 200 url: https://segmentfault.com/a/1190000022525379</span></span>
<span class="line"><span>Status: 200 related: 1190000022525379</span></span>
<span class="line"><span>Status: 200 related: 1190000041787331</span></span>
<span class="line"><span>add: 1190000022513280</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br></div></div></details>
<div class="info custom-block"><p class="custom-block-title">[📝Note]</p>
<p>有好几个问题，还有试图共用一个session的时候，会锁住<br>
这个多线程的难度不相上下，有无多线程和协程的排查技巧？</p>
</div>
<h3 id="异步进阶" tabindex="-1">异步进阶 <a class="header-anchor" href="#异步进阶" aria-label="Permalink to &quot;异步进阶&quot;">&ZeroWidthSpace;</a></h3>
<p>异步编程是个大话题了，以后再说，这里讨论的已经够多了<br>
<a href="./深入python.html">深入python-&gt;异步编程</a>
#TODO  异步编程，asyncio asynchttp gevent twisted
结合多进程和多线程</p>
<hr>
<h2 id="日志和测试" tabindex="-1">日志和测试 <a class="header-anchor" href="#日志和测试" aria-label="Permalink to &quot;日志和测试&quot;">&ZeroWidthSpace;</a></h2>
<h3 id="原生日志" tabindex="-1">原生日志 <a class="header-anchor" href="#原生日志" aria-label="Permalink to &quot;原生日志&quot;">&ZeroWidthSpace;</a></h3>
<p>先上<a href="https://docs.python.org/zh-cn/3.9/howto/logging.html#logging-flow" target="_blank" rel="noreferrer">文档</a></p>
<table tabindex="0">
<thead>
<tr>
<th>级别</th>
<th>何时使用 (调用时的函数名即为级别名的小写)</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>DEBUG</code> 10</td>
<td>细节信息，仅当诊断问题时适用。</td>
</tr>
<tr>
<td><code>INFO</code> 20</td>
<td>确认程序按预期运行。</td>
</tr>
<tr>
<td><code>WARNING</code>(default)30</td>
<td>表明有已经或即将发生的意外（例如：磁盘空间不足）。程序仍按预期进行。</td>
</tr>
<tr>
<td><code>ERROR</code> 40</td>
<td>由于严重的问题，程序的某些功能已经不能正常执行</td>
</tr>
<tr>
<td><code>CRITICAL</code> 50</td>
<td>严重的错误，表明程序已不能继续执行</td>
</tr>
<tr>
<td><code>NOTSET</code> 0</td>
<td></td>
</tr>
</tbody>
</table>
<p><img src="./static/Python语言进阶_images_14.png" alt="python log模块的工作过程"></p>
<ul>
<li>先行配置根记录器basicConfig()会做以下两件事：
<ol>
<li>添加默认的处理器(handler)</li>
<li>添加默认的格式化器（formatter）</li>
</ol>
</li>
</ul>
<p>默认<code>filemode='a'</code>, <code>level=logging.WARNING</code>,命令行运行的时候可以<code>--log=INFO</code>指定,直接使用
logger-&gt;handler-&gt;formatter,分别都有可以定义的方法<br>
你可以将任意对象作为消息传递将调用其 <code>__ str__()</code> 方法</p>
<p>注意这几个handler的使用</p>
<ul>
<li><a href="https://docs.python.org/zh-cn/3.9/library/logging.handlers.html#logging.handlers.RotatingFileHandler" title="logging.handlers.RotatingFileHandler" target="_blank" rel="noreferrer"><code>RotatingFileHandler</code></a> 实例将消息发送到硬盘文件，支持最大日志文件大小和日志文件轮换</li>
<li><a href="https://docs.python.org/zh-cn/3.9/library/logging.handlers.html#logging.handlers.TimedRotatingFileHandler" title="logging.handlers.TimedRotatingFileHandler" target="_blank" rel="noreferrer"><code>TimedRotatingFileHandler</code></a> 实例将消息发送到硬盘文件，以特定的时间间隔轮换日志文件。</li>
<li><a href="https://docs.python.org/zh-cn/3.9/library/logging.handlers.html#logging.handlers.SMTPHandler" title="logging.handlers.SMTPHandler" target="_blank" rel="noreferrer"><code>SMTPHandler</code></a> 实例将消息发送到指定的电子邮件地址。</li>
<li><a href="https://docs.python.org/zh-cn/3.9/library/logging.handlers.html#logging.handlers.HTTPHandler" title="logging.handlers.HTTPHandler" target="_blank" rel="noreferrer"><code>HTTPHandler</code></a> 实例使用 <code>GET</code> 或 <code>POST</code> 方法将消息发送到 HTTP 服务器。</li>
</ul>
<h4 id="按进程记录日志" tabindex="-1">按进程记录日志 <a class="header-anchor" href="#按进程记录日志" aria-label="Permalink to &quot;按进程记录日志&quot;">&ZeroWidthSpace;</a></h4>
<p>在写文件模式下，logging模块是不支持多进程的
Python默认采用Fork方式创建新进程，在Fork新进程的时候会连同 <strong>锁</strong> 也一同复制到新进程。</p>
<ol>
<li>当主进程里有两个线程T1/T2，以及一个锁Lock1。</li>
<li>线程T2获取了锁Lock1，此时线程T1创建了一个新进程P2，此时Lock1被一同frok给了P2。</li>
<li>P2执行时尝试等待Lock1解锁。由于线程T2不会被复制到P2，没有人给P2线程的Lock1解锁，导致P2死锁。</li>
</ol>
<p>解决方案:</p>
<ul>
<li>一种方案是让所有进程都用一个 <code>SocketHandler</code> 处理日志，然后用一个单独的进程实现套接字服务</li>
<li>可以利用 <code>Queue</code> 和 <a href="https://docs.python.org/zh-cn/3.9/library/logging.handlers.html#logging.handlers.QueueHandler" title="logging.handlers.QueueHandler" target="_blank" rel="noreferrer"><code>QueueHandler</code></a> 将所有的日志事件发送给自己的多进程应用中的某个进程</li>
</ul>
<div class="danger custom-block"><p class="custom-block-title">[🚨Danger]</p>
<p>Python的logging模块在写文件时会加锁，由于锁被复制导致进程死锁。<br>
由于创建新进程时锁会被复制，混用多进程和多线程时的加锁操作应当格外小心。</p>
</div>
<h4 id="按天记录日志" tabindex="-1">按天记录日志 <a class="header-anchor" href="#按天记录日志" aria-label="Permalink to &quot;按天记录日志&quot;">&ZeroWidthSpace;</a></h4>
<p>按天记录的时候，进程会在12.00的时候把日志文件重命名，如果有重名的，就会删掉。<br>
在多进程模式下，每个进程是独立的，一个进程可能会把另一个进程的删了<br>
<a href="https://www.xluke.info/article/python-logging-multiprocess-safe" target="_blank" rel="noreferrer">探讨python logging多线程和多进程的安全问题 | Luke's blog</a><br/>
<a href="https://www.bilibili.com/video/BV1PP4y187Wr?spm_id_from=333.337.search-card.all.click" target="_blank" rel="noreferrer">你不知道的logging日志处理_哔哩哔哩_bilibili</a><br/>
<a href="https://zhuanlan.zhihu.com/p/361058730" target="_blank" rel="noreferrer">Python面试官：聊聊多进程场景下Logging模块？ - 知乎</a></p>
<h3 id="loguru" tabindex="-1">loguru <a class="header-anchor" href="#loguru" aria-label="Permalink to &quot;loguru&quot;">&ZeroWidthSpace;</a></h3>
<p>loguru 是对logging的封装，logging属实难用，配置多又不安全，现在用得最多的就是第三方loguru，下面我会总结出我多用的场景<br>
#TODO 多线程多进程协程 锁的性能影响 分文件 日志格式 压缩 大小分片时间分片，滚动删除，cache exceptinon</p>
<ul>
<li><a href="https://blog.csdn.net/lhbo_bo/article/details/119359836" target="_blank" rel="noreferrer">python日志记录loguru模块_写代码ing的博客-CSDN博客</a></li>
<li><a href="https://blog.csdn.net/brightgreat/article/details/123437605" target="_blank" rel="noreferrer">python loguru优雅的输出日志信息_darling331的博客-CSDN博客</a></li>
</ul>
<h3 id="测试" tabindex="-1">测试 <a class="header-anchor" href="#测试" aria-label="Permalink to &quot;测试&quot;">&ZeroWidthSpace;</a></h3>
<h4 id="单元测试" tabindex="-1">单元测试 <a class="header-anchor" href="#单元测试" aria-label="Permalink to &quot;单元测试&quot;">&ZeroWidthSpace;</a></h4>
<p>使用unittest包，对某个文件<code>file.py</code>里的类进行测试的时候，新建<code>file_test.py</code>,在测试文件里引入原文件中需要的类，继承<code>unittest.TestCase</code>类创建测试类</p>
<p>以<code>test</code>开头的方法就是测试方法，不以<code>test</code>开头的方法不被认为是测试方法，测试的时候不会被执行。<br>
对每一类测试都需要编写一个<code>test_xxx()</code>方法。由于<code>unittest.TestCase</code>提供了很多内置的条件判断，我们只需要调用这些方法就可以断言输出是否是我们所期望的。</p>
<p>最常用的断言就是<code>self.assertEqual(abs(-1),1)</code><br>
另一种重要的断言就是期待抛出指定类型的Error<code>with self.assertRaises(KeyError):</code><br>
最后调用<code>unittest.main()</code>运行即可</p>
<p>可以在单元测试中编写两个特殊的<code>setUp()</code>和<code>tearDown()</code>方法。这两个方法会分别在每调用一个测试方法的前后分别被执行，可以用来管理资源连接和释放，<strong>每个测试方法都会调用的钩子</strong></p>
<details class="details custom-block"><summary>Click to see more</summary>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> logging  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> unittest  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> mydict </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Dict  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> MyTestCase</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">unittest</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">TestCase</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">):  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> setUp</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self):  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.f</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">open</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"a.txt"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"a"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">encoding</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"utf8"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'setUp...'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> tearDown</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self):  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.f.write(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"xxx"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'tearDown...'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.f.close()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> test_something</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self):  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        logging.debug(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"TESTING..."</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># add assertion here  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> test_init</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self):  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        d </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Dict(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">a</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">b</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'test'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.assertEqual(d.a, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.assertEqual(d.b, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'test'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.assertTrue(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">isinstance</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(d, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">dict</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">))  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> test_key</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self):  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        d </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Dict()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        d[</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'key'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">] </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 'value'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.assertEqual(d.key, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'value'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> test_attr</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self):  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        d </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Dict()  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        d.key </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 'value'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.assertTrue(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'key'</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> in</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> d)  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.assertEqual(d[</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'key'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">], </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'value'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> test_keyerror</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self):  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        d </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Dict()  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        with</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.assertRaises(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">KeyError</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">):  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            value </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> d[</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'empty'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> test_attrerror</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(self):  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        d </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Dict()  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        with</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> self</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.assertRaises(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">AttributeError</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">):  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            value </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> d.empty  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">if</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __name__</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> ==</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> '__main__'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    unittest.main()</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br></div></div><p>运行结果</p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>Launching pytest with arguments /Users/jack/code/py/AdvancedPython/tests/mydict_test.py --no-header --no-summary -q in /Users/jack/code/py/AdvancedPython/tests</span></span>
<span class="line"><span></span></span>
<span class="line"><span>============================= test session starts ==============================</span></span>
<span class="line"><span>collecting ... collected 6 items</span></span>
<span class="line"><span></span></span>
<span class="line"><span>mydict_test.py::MyTestCase::test_attr PASSED                             [ 16%]setUp...</span></span>
<span class="line"><span>...</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br></div></div></details>
<h4 id="文档测试" tabindex="-1">文档测试 <a class="header-anchor" href="#文档测试" aria-label="Permalink to &quot;文档测试&quot;">&ZeroWidthSpace;</a></h4>
<p>内置的文档测试模块可以直接提取注释中的代码并执行测试，代码的执行是使用python<strong>命令行</strong>执行，看一眼就明白了<br>
当模块正常导入时，doctest不会被执行。只有在<strong>命令行</strong>直接运行时，才执行doctest</p>
<details class="details custom-block"><summary>Click to see more</summary>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># -*-coding:utf-8-*-  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># SettingCode here  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">__author__ </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "a_little_rubbish"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">__date__ </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "2022/5/30 10:25"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># import your model here  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> doctest  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># your class&#x26;function here  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> fact</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(n):  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    '''  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    Calculate 1*2*...*n # 这里仍然可以写注释</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">     </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    >>> </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">fact(1)  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    1    </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    >>> </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">fact(10)  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    3628800    </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    >>> </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">fact(-1)  </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    Traceback (most recent call last):        </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    ...    </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    ValueError    </span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    '''</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> n </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x3C;</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        raise</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> ValueError</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> n </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">==</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> n </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> fact(n </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">if</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> __name__</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> ==</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "__main__"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"START"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    doctest.testmod() </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 不使用测试模式运行的时候需要指定</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br></div></div><p>运行结果</p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>passed</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div></details>
<h3 id="类型注解" tabindex="-1">类型注解 <a class="header-anchor" href="#类型注解" aria-label="Permalink to &quot;类型注解&quot;">&ZeroWidthSpace;</a></h3>
<h4 id="基本类型注解" tabindex="-1">基本类型注解 <a class="header-anchor" href="#基本类型注解" aria-label="Permalink to &quot;基本类型注解&quot;">&ZeroWidthSpace;</a></h4>
<p>当我们想要说明类型的时候，可以使用类型注解，但是类型注解不是类型检查并不能阻止调用者传入不应该传入的参数。</p>
<ul>
<li>变量类型：在变量名后加一个冒号，冒号后写变量的数据类型，如 int、dict 等</li>
<li>函数返回类型：方法参数中如变量类型，在参数括号后加一个箭头，箭头后返回值的类型
<ul>
<li>函数注解的信息，保存在 <code>__annotations__</code> 属性中可以来调用</li>
</ul>
</li>
<li>格式要求（PEP 8，非强制）：变量名和冒号无空格，冒号和后边类型间加一个空格，箭头左右均有一个空格</li>
</ul>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 定义一个变量  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">x: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">int</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">x: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">int</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> |</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> float</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 2</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 表示 or Python 3.10 开始支持  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">x </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 3  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 定义一个除法函数  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> div</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(a: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">int</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, b: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">int</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) -> </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">float</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> a</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">/</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">b  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 查看类型注解信息  </span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(div.</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">__annotations__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#----结果----</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'a'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">int</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'b'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">int</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'return'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">float</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br></div></div><h4 id="复杂结构注解和使用泛型" tabindex="-1">复杂结构注解和使用泛型 <a class="header-anchor" href="#复杂结构注解和使用泛型" aria-label="Permalink to &quot;复杂结构注解和使用泛型&quot;">&ZeroWidthSpace;</a></h4>
<p>可以使用嵌套的类型注解</p>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> typing </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Union, List, Tuple, Dict</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">config: Dict[</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">str</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, Union[List[</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">str</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">], Tuple[</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">bool</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">str</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]]]</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> { </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 嵌套的类型注解</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">            'width'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: [</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'100%'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'Width of img'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">],</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">            'height'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: [</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'auto'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'Height of img'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">],</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">            'fluid'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: (</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">True</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'外层包含一个div'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        }</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br></div></div><p>python的泛型是PEP443用<code>from functools import singledispatch</code> 实现的，在函数前加注解</p>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> functools </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> singledispatch</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">@singledispatch</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> age</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(obj):</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'请传入合法类型的参数！'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">@age.register</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">int</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> _</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(age):</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'我已经</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">{}</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">岁了。'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.format(age))</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">@age.register</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">str</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> _</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(age):</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'I am </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">{}</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> years old.'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.format(age))</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#----结果----</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">age(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">23</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># int</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">age(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'twenty three'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># str</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">age([</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'23'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">])  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># list</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br></div></div><p>复杂类型写注解很麻烦，尤其是涉及到泛型，对于python这种强类型来说不是很常见，用到再<a href="https://www.gairuo.com/p/python-type-annotations" target="_blank" rel="noreferrer">看</a></p>
<div class="tip custom-block"><p class="custom-block-title">[📄Abstract]</p>
<p>不要在python里面写java，这一点也不pythonic✋<br>
<strong>泛型程序设计</strong>（generic programming）是<a href="https://zh.wikipedia.org/wiki/%E7%A8%8B%E5%BA%8F%E8%AE%BE%E8%AE%A1%E8%AF%AD%E8%A8%80" title="程序设计语言" target="_blank" rel="noreferrer">程序设计语言</a>的一种风格或<a href="https://zh.wikipedia.org/wiki/%E7%BC%96%E7%A8%8B%E8%8C%83%E5%9E%8B" title="编程范型" target="_blank" rel="noreferrer">范式</a>。泛型允许程序员在<a href="https://zh.wikipedia.org/wiki/%E5%BC%B7%E9%A1%9E%E5%9E%8B%E7%A8%8B%E5%BC%8F%E8%AA%9E%E8%A8%80" title="强类型编程语言" target="_blank" rel="noreferrer">强类型程序设计语言</a>中编写代码时使用一些以后才指定的<a href="https://zh.wikipedia.org/wiki/%E7%B1%BB%E5%9E%8B" title="类型" target="_blank" rel="noreferrer">类型</a>，在<a href="https://zh.wikipedia.org/wiki/%E5%AE%9E%E4%BE%8B" title="实例" target="_blank" rel="noreferrer">实例化</a>时作为参数指明这些类型。<br>
各种程序设计语言和其编译器、运行环境对泛型的支持均不一样。</p>
<ul>
<li><a href="https://zh.wikipedia.org/wiki/Ada" title="Ada" target="_blank" rel="noreferrer">Ada</a>、<a href="https://zh.wikipedia.org/wiki/Delphi" title="Delphi" target="_blank" rel="noreferrer">Delphi</a>、<a href="https://zh.wikipedia.org/wiki/Eiffel" title="Eiffel" target="_blank" rel="noreferrer">Eiffel</a>、<a href="https://zh.wikipedia.org/wiki/Java" title="Java" target="_blank" rel="noreferrer">Java</a>、<a href="https://zh.wikipedia.org/wiki/C%E2%99%AF" title="C♯" target="_blank" rel="noreferrer">C#</a>、<a href="https://zh.wikipedia.org/wiki/F" title="F" target="_blank" rel="noreferrer">F#</a>、<a href="https://zh.wikipedia.org/wiki/Swift_(%E7%A8%8B%E5%BC%8F%E8%AA%9E%E8%A8%80)" title="Swift (编程语言)" target="_blank" rel="noreferrer">Swift</a> 和 <a href="https://zh.wikipedia.org/wiki/Visual_Basic_.NET" title="Visual Basic .NET" target="_blank" rel="noreferrer">Visual Basic .NET</a> 称之为泛型（generics）；</li>
<li><a href="https://zh.wikipedia.org/wiki/ML%E8%AF%AD%E8%A8%80" title="ML语言" target="_blank" rel="noreferrer">ML</a>、<a href="https://zh.wikipedia.org/wiki/Scala" title="Scala" target="_blank" rel="noreferrer">Scala</a> 和 <a href="https://zh.wikipedia.org/wiki/Haskell" title="Haskell" target="_blank" rel="noreferrer">Haskell</a> 称之为<a href="https://zh.wikipedia.org/wiki/%E5%8F%82%E6%95%B0%E5%A4%9A%E6%80%81" title="参数多态" target="_blank" rel="noreferrer">参数多态</a>（parametric polymorphism）；</li>
<li><a href="https://zh.wikipedia.org/wiki/C%2B%2B" title="C++" target="_blank" rel="noreferrer">C++</a> 和 <a href="https://zh.wikipedia.org/wiki/D%E8%AA%9E%E8%A8%80" title="D语言" target="_blank" rel="noreferrer">D</a>称之为<a href="https://zh.wikipedia.org/wiki/%E6%A8%A1%E6%9D%BF_(C%2B%2B)" title="模板 (C++)" target="_blank" rel="noreferrer">模板</a>。</li>
</ul>
</div>
<hr class="footnotes-sep">
<section class="footnotes">
<ol class="footnotes-list">
<li id="fn1" class="footnote-item"><p><a href="https://juejin.cn/post/7152352643430481928" target="_blank" rel="noreferrer">collections.deque和multiprocessing.Queue组合使用带来的性能问题 - 掘金</a> <a href="#fnref1" class="footnote-backref">↩︎</a></p>
</li>
</ol>
</section>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Python快速复习]]></title>
            <link>http://ooowl.fun/blogs/Python/%E8%AF%AD%E6%B3%95%E5%92%8C%E5%BA%93/Python%E5%BF%AB%E9%80%9F%E5%A4%8D%E4%B9%A0.html</link>
            <guid isPermaLink="false">http://ooowl.fun/blogs/Python/%E8%AF%AD%E6%B3%95%E5%92%8C%E5%BA%93/Python%E5%BF%AB%E9%80%9F%E5%A4%8D%E4%B9%A0.html</guid>
            <pubDate>Mon, 16 May 2022 15:57:35 GMT</pubDate>
            <content:encoded><![CDATA[<h1 id="python快速复习" tabindex="-1">Python快速复习 <a class="header-anchor" href="#python快速复习" aria-label="Permalink to &quot;Python快速复习&quot;">&ZeroWidthSpace;</a></h1><p class="article-meta">创建于 2022年5月16日 23:57:35 · 约1,845字</p>
<p>很零碎，很基础，不容易想起来的知识点。<br>
配合廖学峰和python文档快速熟悉知识</p>
<h2 id="一些资料" tabindex="-1">一些资料 <a class="header-anchor" href="#一些资料" aria-label="Permalink to &quot;一些资料&quot;">&ZeroWidthSpace;</a></h2>
<ul>
<li><a href="https://docs.python.org/zh-cn/3/library/index.html" target="_blank" rel="noreferrer">官方文档#第三方包</a></li>
<li><a href="https://docs.python.org/3/library/functions.html" target="_blank" rel="noreferrer">内置函数Built-in Functions</a></li>
<li><a href="https://pypi.org/" target="_blank" rel="noreferrer">第三方包查询pypi</a></li>
<li><a href="https://www.lfd.uci.edu/~gohlke/pythonlibs/" target="_blank" rel="noreferrer">windows WHL站</a></li>
</ul>
<p><a href="https://docs.python.org/zh-cn/3/library/functions.html" target="_blank" rel="noreferrer">内置函数 — Python 3.12.6 文档</a> 重点关注下列几个速速复习：</p>
<ul>
<li><code>bool()</code>传进去的东西返回是True还是False，可以在传入的对象中定义<code>__bool__</code></li>
<li><code>complex</code> 转化为复数<code>1.23+4.5j</code></li>
<li><code>商,余数=divmod(a,b)</code>同时计算</li>
<li><code>pow</code>和<code>**</code>一样</li>
<li><code>bytes(b&quot;aster&quot;)</code>创建一个bytes对象，本质是一个0-255之间的<strong>不可更改</strong>的数组，可以decode为str和encode，使用bytearray来创建<strong>可更改</strong>的</li>
<li><code>chr(65)=='A'</code>逆函数<code>ord('A')==65</code></li>
<li><code>bin,oct,hex</code>二进制八进制十六进制，使用<code>int('0b101010',2)</code>使用int转换2进制为十进制</li>
<li><code>ascii()</code>转换为ascii兼容的字符，<code>repr()</code>转换回来</li>
<li><code>reversed()</code>把一个序列倒过来</li>
<li><code>all()</code>保证每个都为True,<code>any()</code>任意一个为True。但是<code>all([]) is True</code>，<code>all([]) is False</code></li>
<li><code>object()</code>创建后在命名空间中从没有使用过的哨兵</li>
<li><code>isinstance</code>，<code>issubclass</code>是否是实例或子类，注意<strong>在py中bool是整数</strong></li>
<li><code>@property</code>允许把函数作为类的属性去调用</li>
<li><code>eval('a=1')</code>尝试直接把字符串转成代码运行，<code>exec</code>可以运行大量的传入的字符串代码，可以用<code>compile</code>编译成固定的，然后多次运行</li>
<li><code>global var</code>声明的var是全局的，<code>globals()</code>获得全局变量字典，<code>local()</code>获得当前空间的但不能修改</li>
</ul>
<h2 id="环境管理相关" tabindex="-1">环境管理相关 <a class="header-anchor" href="#环境管理相关" aria-label="Permalink to &quot;环境管理相关&quot;">&ZeroWidthSpace;</a></h2>
<h3 id="环境常用" tabindex="-1">环境常用 <a class="header-anchor" href="#环境常用" aria-label="Permalink to &quot;环境常用&quot;">&ZeroWidthSpace;</a></h3>
<p>三个常用的就够了，venv和virtualenv，conda<br>
venv的创建就是<code>python -m venv /path/to/new/virtual/environment</code> 此时进入创建的目录bin文件夹，activate就可以激活了。<br>
venv创建的环境python版本和外部的大版本相同，只是把环境独立了出来，python解释器是指向那个的软连接,venv只隔离包<br>
windows上激活就是运行脚本，linux激活就是source activate</p>
<p>virtualenv和conda都是解释器级别的隔离，但是这俩是不兼容的有一个会不起效，会直接创建新的解释器，可以指定python的版本<br>
virtualenv需要安装<code>pip install virtualenv</code>,</p>
<h3 id="pip包常用" tabindex="-1">pip包常用 <a class="header-anchor" href="#pip包常用" aria-label="Permalink to &quot;pip包常用&quot;">&ZeroWidthSpace;</a></h3>
<h2 id="数字和字符串" tabindex="-1">数字和字符串 <a class="header-anchor" href="#数字和字符串" aria-label="Permalink to &quot;数字和字符串&quot;">&ZeroWidthSpace;</a></h2>
<ul>
<li>Python允许在数字中间以<code>_</code>分隔，因此，写成<code>10_000_000_000</code>和<code>10000000000</code>是完全一样的。十六进制数也可以写成<code>0xa1b2_c3d4</code>。浮点数运算可能会有四舍五入的误差</li>
<li><code>str</code>通过<code>encode()</code>方法可以编码为指定的<code>bytes</code> <code>'ABC'.encode('ascii')</code>
<ul>
<li>反过来，如果我们从网络或磁盘上读取了字节流，那么读到的数据就是<code>bytes</code>。要把<code>bytes</code>变为<code>str</code>，就需要用<code>decode()</code>,参数<code>errors='ignore'</code>忽略错误的字节</li>
<li><code>len()</code>函数计算的是<code>str</code>的字符数，如果换成<code>bytes</code>，<code>len()</code>函数就计算字节数</li>
</ul>
</li>
<li>对于单个字符的编码，Python提供了<code>ord()</code>函数获取字符的整数表示，<code>chr()</code>函数把编码转换为对应的字符</li>
<li><code>'Age: %s. Gender: %s' % (25, True)</code>如果你不太确定应该用什么，<code>%s</code>永远起作用，它会把任何数据类型转换为字符串,双<code>%%</code>可以打印正常%</li>
<li><code>'Hello, {name}, 成绩提升了 {score:.1f}%'.format(name='小明', score=17.125)</code></li>
<li>通过dict提供的<code>get()</code>方法，如果key不存在，可以返回<code>None</code>，或者自己指定的value，<code>d.get(&quot;key&quot;,value)</code></li>
<li>int的base参数可以指定进制</li>
</ul>
<h2 id="函数" tabindex="-1">函数 <a class="header-anchor" href="#函数" aria-label="Permalink to &quot;函数&quot;">&ZeroWidthSpace;</a></h2>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> add_end</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(L</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[]):</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    L.append(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'END'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> L</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br></div></div><p>Python函数在定义的时候，默认参数<code>L</code>的值就被计算出来了，即<code>[]</code>，因为默认参数<code>L</code>也是一个变量，它指向对象<code>[]</code>，每次调用该函数，如果改变了<code>L</code>的内容，则下次调用时，默认参数的内容就变了，不再是函数定义时的<code>[]</code>了</p>
<div class="warning custom-block"><p class="custom-block-title">[⚠️Warning]</p>
<p>定义默认参数要牢记一点：默认参数必须指向不变对象！</p>
</div>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> person</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(name, age, </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, city, job):</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(name, age, city, job)</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br></div></div><p>和关键字参数<code>**kw</code>不同，命名关键字参数需要一个特殊分隔符<code>*</code>，<code>*</code>后面的参数被视为命名关键字参数。<br>
如果函数定义中已经有了一个可变参数，后面跟着的命名关键字参数就不再需要一个特殊分隔符<code>*</code>了<br>
命名关键字参数必须传入参数名，这和位置参数不同。如果没有传入参数名，调用将报错：</p>
<h3 id="尾递归优化" tabindex="-1">尾递归优化 <a class="header-anchor" href="#尾递归优化" aria-label="Permalink to &quot;尾递归优化&quot;">&ZeroWidthSpace;</a></h3>
<p>解决递归调用栈溢出的方法是通过<strong>尾递归</strong>优化，事实上尾递归和循环的效果是一样的，所以，把循环看成是一种特殊的尾递归函数也是可以的。<br>
尾递归是指，在函数返回的时候，调用自身本身，并且，return语句不能包含表达式。这样，编译器或者解释器就可以把尾递归做优化，使递归本身无论调用多少次，都只占用一个栈帧，不会出现栈溢出的情况。</p>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> fact</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(n):</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> fact_iter(n, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> fact_iter</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(num, product):</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> num </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">==</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> product</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> fact_iter(num </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, num </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> product)</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br></div></div><p>尾递归调用时，如果做了优化，栈不会增长，因此，无论多少次调用也不会导致栈溢出。<br>
遗憾的是，大多数编程语言没有针对尾递归做优化，Python解释器也没有做优化，所以，即使把上面的<code>fact(n)</code>函数改成尾递归方式，也会导致栈溢出。</p>
<p><code>functools.partial</code>的作用就是，把一个函数的某些参数给固定住（也就是设置默认值），返回一个新的函数，调用这个新函数会更简单，<code>int2 = functools.partial(int, base=2)</code></p>
<h2 id="特性" tabindex="-1">特性 <a class="header-anchor" href="#特性" aria-label="Permalink to &quot;特性&quot;">&ZeroWidthSpace;</a></h2>
<h3 id="列表生成式" tabindex="-1">列表生成式 <a class="header-anchor" href="#列表生成式" aria-label="Permalink to &quot;列表生成式&quot;">&ZeroWidthSpace;</a></h3>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 以下代码正常输出偶数：</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[x </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> x </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> range</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">11</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> x </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">%</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 2</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> ==</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">4</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">6</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">8</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">10</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 以下代码奇负偶正：</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[x </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> x </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">%</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 2</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> ==</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 0</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> else</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> -</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">x </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> x </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> range</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">11</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)]</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">4</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">5</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">6</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">7</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">8</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">9</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">10</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br></div></div><p>如果使用<code>()</code>那就是生成器了，生成器使用<code>next()</code>获取下一个值抛出<code>StopIteration</code>的错误停止，generator也是可迭代对象<br>
在函数中使用<code>yield</code>阻塞函数执行并return值使用next回复执行，使用时需要创建对象，类似于类的使用<br>
可以使用<code>isinstance()</code>判断一个对象是否是<code>Iterable</code>或<code>Iterator</code> 对象<code>from collections.abc import Iterable,Iterator</code>
生成器都是<code>Iterator</code>对象，但<code>list</code>、<code>dict</code>、<code>str</code>虽然是<code>Iterable</code>，却不是<code>Iterator</code>,把<code>Iterable</code>变成<code>Iterator</code>可以使用<code>iter()</code>函数</p>
<ul>
<li>凡是可作用于<code>for</code>循环的对象都是<code>Iterable</code>类型；</li>
<li>凡是可作用于<code>next()</code>函数的对象都是<code>Iterator</code>类型，它们表示一个惰性计算的序列</li>
<li><code>for</code>循环本质上就是通过不断调用<code>next()</code>函数实现的</li>
</ul>
<h3 id="排序" tabindex="-1">排序 <a class="header-anchor" href="#排序" aria-label="Permalink to &quot;排序&quot;">&ZeroWidthSpace;</a></h3>
<p><code>sorted()</code>函数也是一个高阶函数，它还可以接收一个<code>key</code>函数来实现自定义的排序，例如按绝对值大小排序<br>
<code>sorted([36, 5, -12, 9, -21], key=abs)</code></p>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 自定义字段排序</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">sorted</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(obj, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">key</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=lambda</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> x: x[</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'a'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">])</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 多字段优先级排序</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">sorted</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(obj, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">key</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=lambda</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> x: (x[</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'a'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">], x[</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'b'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]))</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 有个第三方包</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">sorted</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(obj, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">key</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">operator.itemgetter(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'a'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">))</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 自定义排序函数，实际上是重载了比较函数</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> functools </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> cmp_to_key</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">sorted</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(obj, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">key</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">cmp_to_key(func))</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br></div></div><h3 id="装饰器格式" tabindex="-1">装饰器格式 <a class="header-anchor" href="#装饰器格式" aria-label="Permalink to &quot;装饰器格式&quot;">&ZeroWidthSpace;</a></h3>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(func):</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> wrapper</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">args, </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">**</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">kw):</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'call </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%s</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">():'</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> %</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> func.</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">__name__</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 功能代码</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> func(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">args, </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">**</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">kw)</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> wrapper</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br></div></div><div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>assert x >= 0 : "x must >= 0";</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p>这样，断言失败的时候，<code>AssertionError</code>会带上消息<code>x must &gt;= 0</code>，更加便于调试。</p>
<h2 id="oop" tabindex="-1">OOP <a class="header-anchor" href="#oop" aria-label="Permalink to &quot;OOP&quot;">&ZeroWidthSpace;</a></h2>
<p><code>_</code>可以访问但不建议
<code>__</code>私有变量（private）不能直接访问<code>__name</code>是因为Python解释器对外把<code>__name</code>变量改成了<code>_ClassName__name</code>
<code>__xxx__</code>是特殊变量</p>
<p>和普通的函数相比，在类中定义的函数只有一点不同，就是第一个参数永远是实例变量<code>self</code>，并且，调用时，不用传递该参数<br>
对于静态语言（例如Java）来说，如果需要传入<code>Animal</code>类型，则传入的对象必须是<code>Animal</code>类型或者它的子类，否则，将无法调用<code>run()</code>方法。<br>
对于Python这样的动态语言来说，则不一定需要传入<code>Animal</code>类型。我们只需要保证传入的对象有一个<code>run()</code>方法就可以了</p>
<div class="info custom-block"><p class="custom-block-title">[📝Note]</p>
<p>就这样吧，剩下的详细放在进阶里</p>
</div>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[第零章 计算机概论]]></title>
            <link>http://ooowl.fun/blogs/Book/%E9%B8%9F%E5%93%A5%E7%9A%84linux%E7%A7%81%E6%88%BF%E8%8F%9C/%E7%AC%AC%E9%9B%B6%E7%AB%A0-%E8%AE%A1%E7%AE%97%E6%9C%BA%E6%A6%82%E8%AE%BA.html</link>
            <guid isPermaLink="false">http://ooowl.fun/blogs/Book/%E9%B8%9F%E5%93%A5%E7%9A%84linux%E7%A7%81%E6%88%BF%E8%8F%9C/%E7%AC%AC%E9%9B%B6%E7%AB%A0-%E8%AE%A1%E7%AE%97%E6%9C%BA%E6%A6%82%E8%AE%BA.html</guid>
            <pubDate>Sun, 15 May 2022 09:39:01 GMT</pubDate>
            <content:encoded><![CDATA[<h1 id="第零章-计算机概论" tabindex="-1">第零章 计算机概论 <a class="header-anchor" href="#第零章-计算机概论" aria-label="Permalink to &quot;第零章 计算机概论&quot;">&ZeroWidthSpace;</a></h1><p class="article-meta">创建于 2022年5月15日 17:39:01 · 约27字</p>
<p>数据结构-&gt;王道组成原理-&gt;王道操作系统-&gt;网络自顶向下-&gt;鸟哥私房菜</p>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[彩蛋收集]]></title>
            <link>http://ooowl.fun/blogs/%E4%BB%A3%E7%A0%81%E4%B9%8B%E5%A4%96/%E5%BD%A9%E8%9B%8B%E6%94%B6%E9%9B%86.html</link>
            <guid isPermaLink="false">http://ooowl.fun/blogs/%E4%BB%A3%E7%A0%81%E4%B9%8B%E5%A4%96/%E5%BD%A9%E8%9B%8B%E6%94%B6%E9%9B%86.html</guid>
            <pubDate>Sun, 08 May 2022 16:13:55 GMT</pubDate>
            <content:encoded><![CDATA[<h1 id="彩蛋收集" tabindex="-1">彩蛋收集 <a class="header-anchor" href="#彩蛋收集" aria-label="Permalink to &quot;彩蛋收集&quot;">&ZeroWidthSpace;</a></h1><p class="article-meta">创建于 2022年5月9日 00:13:55 · 约764字</p>
<p>只记我遇到的和知道的</p>
<h2 id="python" tabindex="-1">Python <a class="header-anchor" href="#python" aria-label="Permalink to &quot;Python&quot;">&ZeroWidthSpace;</a></h2>
<p>python 好几个，有些版本是没有的</p>
<ul>
<li><code>import this</code> 会有python之禅</li>
<li><code>import antigravity</code> 会有一个小漫画</li>
<li><code>import __hello__</code> 返回Hello World...</li>
<li><code>from __future__ import braces</code> 返回 SyntaxError: not a chance
<ul>
<li>'braces' 库也是一个具有浓厚程序员风格的玩笑，它在其文档中提到，当在编写 Python 代码时使用这个库可提供使用 C++ 花括号的功能。但当你尝试使用它的时候，你将会看到社区对此的看法</li>
</ul>
</li>
<li><code>from __future__ import barry_as_FLUFL</code> April Fool，主要作用就是让 <code>!=</code> 失效，只能用 <code>&lt;&gt;</code>py2中的老写法判断不等于。
<ul>
<li>Barry Warsaw 提出的，与他的退休有关。他是一位著名的 Python 开发者，在他宣布正式退休的时候，就诞生了下面这个彩蛋</li>
</ul>
</li>
</ul>
<h2 id="apt" tabindex="-1">APT <a class="header-anchor" href="#apt" aria-label="Permalink to &quot;APT&quot;">&ZeroWidthSpace;</a></h2>
<p><code>This APT has Super Cow Powers.</code>本ATP具有超级牛力<br>
<code>apt moo</code> 加更多的moo ，最后会循环显示<br>
<code>apt-build moo</code><br>
<code>aptitude moo </code><br>
<code>aptitude</code>和<code>apt</code>一直在后面加参数-v -vv 最后会有循环彩蛋</p>
<h2 id="java" tabindex="-1">Java <a class="header-anchor" href="#java" aria-label="Permalink to &quot;Java&quot;">&ZeroWidthSpace;</a></h2>
<p>经常在java图标进程icon解包上见到的上黑下白红鼻子。<strong>Duke</strong>是<strong>Java 的官方吉祥物</strong>，最初在<strong>1995年由 Sun Microsystems</strong>（Java 的创造者之一）设计用来宣传 Java 技术。
<a href="https://wiki.openjdk.org/display/duke/Main" target="_blank" rel="noreferrer">Java 吉祥物—Duke</a></p>
<h2 id="百万随机数" tabindex="-1">百万随机数 <a class="header-anchor" href="#百万随机数" aria-label="Permalink to &quot;百万随机数&quot;">&ZeroWidthSpace;</a></h2>
<p>A Million Random Digits with 100,000 Normal Deviates 0th Edition<br>
创建随机数表的工作从1947年开始，随机数通过对电子<a href="https://zh.wikipedia.org/wiki/%E8%BD%AE%E7%9B%98" title="轮盘" target="_blank" rel="noreferrer">轮盘</a>生成结果的再随机化得到。一个随机频率脉冲源平均每秒产生十万个脉冲，使用每秒一次的恒定频率脉冲对其进行<a href="https://zh.wikipedia.org/wiki/%E9%87%87%E6%A0%B7" title="采样" target="_blank" rel="noreferrer">采样</a>。脉冲标准化电路将信号输入五位二进制计数器，输出相当于转动一个32格轮盘的结果。二—十进制转换器将32位中的20位转换为十进制（剩余12位被丢弃），最后保留得到的两位数的第二位。将最终数据输入<a href="https://zh.wikipedia.org/wiki/IBM" title="IBM" target="_blank" rel="noreferrer">IBM</a><br/><a href="https://zh.wikipedia.org/wiki/%E6%89%93%E5%AD%94%E5%8D%A1" title="打孔卡" target="_blank" rel="noreferrer">打孔卡</a>机中<br>
这个列表对于提供随机数是一个重要的突破，因为在此之前从未有这样巨大且精制的列表。除了书籍形式，也可以订购列表的打孔卡版。这个随机数表主要应用于<a href="https://zh.wikipedia.org/wiki/%E7%BB%9F%E8%AE%A1%E5%AD%A6" title="统计学" target="_blank" rel="noreferrer">统计学</a>和<a href="https://zh.wikipedia.org/wiki/%E7%A7%91%E5%AD%A6%E5%AE%9E%E9%AA%8C" title="科学实验" target="_blank" rel="noreferrer">科学实验</a>的<a href="https://zh.wikipedia.org/wiki/%E5%AF%A6%E9%A9%97%E8%A8%AD%E8%A8%88" title="实验设计" target="_blank" rel="noreferrer">设计</a>中，尤其是使用<a href="https://zh.wikipedia.org/wiki/%E8%92%99%E7%89%B9%E5%8D%A1%E6%B4%9B%E6%96%B9%E6%B3%95" title="蒙特卡洛方法" target="_blank" rel="noreferrer">蒙特卡洛方法</a>的实验；在<a href="https://zh.wikipedia.org/wiki/%E5%AF%86%E7%A0%81%E5%AD%A6" title="密码学" target="_blank" rel="noreferrer">密码学</a>中，譬如设计<a href="https://zh.wikipedia.org/w/index.php?title=%E5%93%88%E5%A4%AB%E6%8B%89%E5%AF%86%E7%A0%81&amp;action=edit&amp;redlink=1" title="哈夫拉密码（页面不存在）" target="_blank" rel="noreferrer">哈夫拉密码</a>（Khafre cipher）时，随机数被用作“空袖数”（Nothing up my sleeve number）。这本书是从1920年代到1950年代制作的一系列随机数表的最后成员之一，随着高速计算机的发展，生成<a href="https://zh.wikipedia.org/wiki/%E4%BC%AA%E9%9A%8F%E6%9C%BA%E6%95%B0" title="伪随机数" target="_blank" rel="noreferrer">伪随机数</a>比查阅随机数表更为快速。<br>
2001年，这本书重新发行（<a href="https://zh.wikipedia.org/wiki/Special:%E7%BD%91%E7%BB%9C%E4%B9%A6%E6%BA%90/0833030477" target="_blank" rel="noreferrer">ISBN 0-8330-3047-7</a>），<a href="https://zh.wikipedia.org/wiki/%E5%85%B0%E5%BE%B7%E5%85%AC%E5%8F%B8" title="兰德公司" target="_blank" rel="noreferrer">兰德公司</a>执行副总裁迈克尔·里奇撰写了新的<a href="https://zh.wikipedia.org/wiki/%E5%89%8D%E8%A8%80" title="前言" target="_blank" rel="noreferrer">前言</a>。在<a href="https://zh.wikipedia.org/wiki/%E4%BA%9A%E9%A9%AC%E9%80%8A%E5%85%AC%E5%8F%B8" title="亚马逊公司" target="_blank" rel="noreferrer">亚马逊</a>的相应页面上，这本书收到了很多有趣的用户评价<br>
淘宝有个原版书店，1500块！！！抢钱啊，Amazon原价也才70刀，买来收藏-</p>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[part 2 常用命令]]></title>
            <link>http://ooowl.fun/blogs/Web%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/%E6%B5%8B%E8%AF%95%E8%BF%90%E7%BB%B4/linux%E7%AE%80%E5%8D%95%E9%80%9F%E9%80%9A/part-2-%E5%B8%B8%E7%94%A8%E5%91%BD%E4%BB%A4.html</link>
            <guid isPermaLink="false">http://ooowl.fun/blogs/Web%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/%E6%B5%8B%E8%AF%95%E8%BF%90%E7%BB%B4/linux%E7%AE%80%E5%8D%95%E9%80%9F%E9%80%9A/part-2-%E5%B8%B8%E7%94%A8%E5%91%BD%E4%BB%A4.html</guid>
            <pubDate>Fri, 29 Apr 2022 14:12:54 GMT</pubDate>
            <description><![CDATA[unix最开始的Bourne shell 多用户拉垮-&gt;linux造Bourne Again shell=BASH-&gt;Debian觉得太重就改了改有了dash。 其他的还有一些魔改版]]></description>
            <content:encoded><![CDATA[<h1 id="part-2-常用命令" tabindex="-1">part 2 常用命令 <a class="header-anchor" href="#part-2-常用命令" aria-label="Permalink to &quot;part 2 常用命令&quot;">&ZeroWidthSpace;</a></h1><p class="article-meta">创建于 2022年4月29日 22:12:54 · 约2,688字</p>
<h2 id="命令行历史" tabindex="-1">命令行历史 <a class="header-anchor" href="#命令行历史" aria-label="Permalink to &quot;命令行历史&quot;">&ZeroWidthSpace;</a></h2>
<p>unix最开始的Bourne shell 多用户拉垮-&gt;linux造Bourne Again shell=BASH-&gt;Debian觉得太重就改了改有了dash。<br>
其他的还有一些魔改版</p>
<blockquote>
<p>sh 遵循POSIX规范：“当某行代码出错时，不继续往下解释”。bash 就算出错，也会继续向下执行。sh是bash的一种特殊的模式，sh就是开启了POSIX标准的bash， /bin/sh 相当于 /bin/bash --posix，在Linux系统上/bin/sh往往是指向/bin/bash的符号链接</p>
</blockquote>
<blockquote>
<p>POSIX表示可移植操作系统接口（Portable Operating System Interface of UNIX，缩写为 POSIX ）。POSIX标准意在期望获得源代码级别的软件可移植性。换句话说，为一个POSIX兼容的操作系统编写的程序，应该可以在任何其它的POSIX操作系统上编译执行。</p>
</blockquote>
<h2 id="基础命令" tabindex="-1">基础命令 <a class="header-anchor" href="#基础命令" aria-label="Permalink to &quot;基础命令&quot;">&ZeroWidthSpace;</a></h2>
<p>内嵌命令，直接写在bash源码里面的，对应的就是外部命令<br>
man 查看命令用法，内嵌命令用man -f xx列出可用的手册，就可以man 1p cd查看对应手册的解释<br>
help 可以查看内置命令的参数用法，外置命令用ls --help<br>
--version可以查看命令版本<br>
type xx 查看是不是内嵌<br>
ls -al | grep “xx”  -h 人类能读懂的方式展示大小<br>
<strong>ctrl+l</strong>=clear清屏，reset=test相当于重设一次bash<br>
history查看命令输入过的历史，+数字可以查看最后几条，-c 清空，前面的数组是编号 !+编号 可以重复打出指定命令。<strong>他不是读取.bash_history</strong><br>
nmap 192.168.0.1 -p 80 # 查看端口是否开放
<a href="https://github.com/onceupon/Bash-Oneliner" target="_blank" rel="noreferrer">bash-oneliner</a>可以复习</p>
<h2 id="文件管理类" tabindex="-1">文件管理类 <a class="header-anchor" href="#文件管理类" aria-label="Permalink to &quot;文件管理类&quot;">&ZeroWidthSpace;</a></h2>
<p>cd -回到上次的目录<br>
ll is an alias for ls -lh<br>
pwd 当前目录，-P 无视链接
rmdir -p 是递归删除文件夹，若底层目录删除完后父目录为空则递归删除父目录<br>
/cp使用cp的原生命令，会强制覆盖不提示。alias查看是别名的命令。</p>
<ul>
<li>cat -n 显示行号</li>
<li>more 翻页完就会自动退出空格下翻b往回翻enter下一行</li>
<li>less 按需加载，=显示更多信息</li>
<li>head/tail -n 数字 默认输出头尾10/数字行</li>
<li>tail -f 可以实时追踪文件变化，ctrl+s/q可以暂停/继续
<ul>
<li>如果被覆写会出截断错误</li>
<li>vim的修改是无法显示的，每一个文件都有 索引节点号index，底层存储方式是inode，vim会保存修改文件的index，ls -i可以查看</li>
</ul>
</li>
</ul>
<p>echo -e &quot;string&quot; 字符串支持转义</p>
<p>输出重定向</p>
<ul>
<li>&gt; 覆盖重定向写</li>
<li>&gt;&gt;追加重定向写</li>
</ul>
<p>软链接实际上是独立的文件有独立的文件符号和inode但是data指向了source，所以链接数指的是硬连接
在进入文件夹的软链接 系统不会自动回到source -P才可以</p>
<div class="danger custom-block"><p class="custom-block-title">[🚨Danger] 软链接的删除</p>
<p>链接的删除
软链接删除不会影响原文件，但是删除软链接下的所有文件，<strong>rm -rf softlink/</strong> 会删除原文件夹下的所有文件。</p>
</div>
<p>原文件删除软链接就进不去了</p>
<p>如果不加s <code>ln source destnation</code>创建硬链接指向同一个inode，a,b-&gt;inode-&gt;disk data，删除硬连接符a或b不会影响原文件，最后一个链接被删除时，inode和data都会删除</p>
<h2 id="获取时间" tabindex="-1">获取时间 <a class="header-anchor" href="#获取时间" aria-label="Permalink to &quot;获取时间&quot;">&ZeroWidthSpace;</a></h2>
<p>时间的格式只有一种是最好的即<a href="https://www.iso.org/iso-8601-date-and-time-format.html" target="_blank" rel="noreferrer">ISO 8601</a>规范日期时间的写法<br>
YYYY-MM-DD hh:mm:ss<br>
暂时少整理，时间和时间戳是个好知识点</p>
<p>date <strong>+</strong> 解析串，串如果有空格的话用双引号<br>
&quot;+%Y-%m-%d %H:%M:%S&quot;<br>
小写y是后两位年份，小写是timestamp<br>
date -d &quot;1 days ago&quot;,年月日时分秒都可以，正的是以前负的是以后的时间<br>
date -s 设置系统时间。<br>
ntpdate 命令已经被timedatectl替代了<br>
cal -n -m 2003-5-1 获得离2003-5-1最近仨月的星期一在最前的日历</p>
<h2 id="用户管理" tabindex="-1">用户管理 <a class="header-anchor" href="#用户管理" aria-label="Permalink to &quot;用户管理&quot;">&ZeroWidthSpace;</a></h2>
<h3 id="添加删除" tabindex="-1">添加删除 <a class="header-anchor" href="#添加删除" aria-label="Permalink to &quot;添加删除&quot;">&ZeroWidthSpace;</a></h3>
<p>useradd -d /home/d1 d2 创建d2但是home文件夹是d1。不能用已有的文件夹</p>
<p>id d2 获得用户的系统id，id是依次累加的，在/etc/passwd文件内存放所有用户，一大堆系统用户是默认创建的服务使用的，顺着uid找就可以看创建的用户</p>
<p><strong>su切换用户时会进程套娃</strong>，注意！<br>
删除用户不会删除home，加-r 就会</p>
<h3 id="用户权限" tabindex="-1">用户权限 <a class="header-anchor" href="#用户权限" aria-label="Permalink to &quot;用户权限&quot;">&ZeroWidthSpace;</a></h3>
<p>/etc/sudoers文件管权限<br>
/etc/group文件管用户组</p>
<p>groupadd/del 增加删除<br>
<strong>usermod -g group user 把user变更为group，-G是追加</strong></p>
<p>文件文件类型<br>
网络通信，本质上就是对网卡或网络虚拟设备进行 I/O 操作
后四种是伪文件不占空间</p>
<p><img src="./static/part-2-常用命令_images_1.png" alt=""></p>
<p><strong>chmod {ugoa}{+-=}{rwx} file</strong><br>
<strong>chmod 777 file</strong> (7=r1w1x1 二进制的7)<br>
-R 递归</p>
<p>如果创建者已经销号了，文件可以被root更改所属user和group<br>
<strong>chown user file</strong><br>
<strong>chgrp group file</strong></p>
<h2 id="磁盘管理" tabindex="-1">磁盘管理 <a class="header-anchor" href="#磁盘管理" aria-label="Permalink to &quot;磁盘管理&quot;">&ZeroWidthSpace;</a></h2>
<h3 id="查找压缩" tabindex="-1">查找压缩 <a class="header-anchor" href="#查找压缩" aria-label="Permalink to &quot;查找压缩&quot;">&ZeroWidthSpace;</a></h3>
<p><a href="https://www.cnblogs.com/jiftle/p/9707518.html" target="_blank" rel="noreferrer">详解find参数</a><br>
find path -name/-user/-size(b,c,w,k,M,G)</p>
<p>查找 path 下 文件名/所属用户/大小(block 512Byte,char 1Byte,word 位长,MB,GB)</p>
<p>类型 -type <strong>f</strong> 普通文件 <strong>l</strong> 符号连接 <strong>d</strong> 目录 <strong>c</strong> 字符设备 <strong>b</strong> 块设备 <strong>s</strong> 套接字 <strong>p</strong> Fifo</p>
<p>locate 命令<br>
每天定时更新，系统所有文件的索引，使用前最好updatedb<br>
locate xx 会直接返回所有含有xx的文件和目录</p>
<p>whereis 是返回所有找得到的文件，where找到的是立即执行的</p>
<p>grep -n 可以显示行号，管道就可以把一个输出传输到另一个输出</p>
<p>wc 行数为、单词数、字节数</p>
<p>gzip gunzip 只能压缩文件，不保留压缩文件<br>
zip 和unzip  dest source -r可以压缩目录，-d可以指定解压存放，不删除文件<br>
tar -c 产生打包文件 -v 显示详细信息 -f 指定文件名，-z 同时打包压缩 -x 解压tar -C 指定解压路径<br>
无脑版压缩解压</p>
<ul>
<li>tar -cvzf file1 file2</li>
<li>tar -xvzf file -C path</li>
</ul>
<h3 id="存储相关" tabindex="-1">存储相关 <a class="header-anchor" href="#存储相关" aria-label="Permalink to &quot;存储相关&quot;">&ZeroWidthSpace;</a></h3>
<p>du 目录文件 disk usage 查看占用空间<br>
-h 人性化 -a 输出包括子目录的文件，-s 只显示总和 -c 显示总和 --d n 最大输出n层子目录</p>
<p>df 查看空间使用量 disk free<br>
tmpfs是swap和内存文件系统，也会展示<br>
devtmpfs是内核启动的时候挂载点</p>
<p>free -hs 2 隔两秒看次内存<br>
lsblk 列出块设备 -f 带文件系统类型和<strong>UUID</strong><br>
硬盘的类型去看鸟哥的书</p>
<p>挂载，先用lsblk查看块设备，找到dev里对应的名字一样的设备文件，最后mount,硬盘不支持热插拔
mount dev point<br>
umount point or dev<br>
在/etc/fstab文件中配置自动挂载<br>
UUID=设备的UUID或dev者设备名 /boot挂载点   xfs文件系统     defaults        0 kdump给系统备份的选项 0文件系统检查优先级，系统默认使用fsck来检查系统文件，0不检查1最高</p>
<p>fdisk -l 查看分区情况,fdisk /dev/sdb 对设备进行分区操作</p>
<p>mkfs -t 文件系统类型 dev</p>
<h2 id="进程管理" tabindex="-1">进程管理 <a class="header-anchor" href="#进程管理" aria-label="Permalink to &quot;进程管理&quot;">&ZeroWidthSpace;</a></h2>
<p>进程可分为前台和后台运行进程(守护进程)，后缀类似于systemd-daemon的意思<br>
process status=ps<br>
不加参数就是只显示和本控制台和本用户当前的的进程</p>
<div class="info custom-block"><p class="custom-block-title">[📝Note] 参数风格</p>
<p>数风格
加 - 是unix 风格<br>
不加是BSD风格</p>
</div>
<p>a列出带有终端所有用户的进程 x列出当前用户所有进程，包括没终端的 u 显示更多信息<br>
常用的就aux<br>
ps -ef 还会显示父进程的id<br>
pstree -p pid -u 所属user 显示进程树，用户变化才会标示</p>
<div class="tip custom-block"><p class="custom-block-title">[💡Tip] 特殊pid</p>
<p>殊pid
<strong>Linux</strong> 中有<strong>pid 0</strong>, pid <strong>1</strong> 和pid 2 三个特殊的进程。<br>
<strong>pid 0</strong>，即“swapper” 进程，是pid <strong>1</strong> 和pid 2 的父进程。<br>
<strong>pid 1</strong>，即“init” 进程，所有用户空间的进程均派生自该进程。<br>
<strong>pid 2</strong>，即“kthreadd” 进程，是内核空间所有进程的父进程。</p>
</div>
<p>ssh权限分离，sudo的时候是有个root的ssh代替操作,pts为打开顺序</p>
<p>ssh被kill之后，新用户登不上，但是先前建立的链接父进程会变1保持连接<br>
1-sshd-remotelogin-bash<br>
killall 支持通配符<br>
kill -l查看信号，-9是强制</p>
<p>top -d 刷新间隔 -i 不现实闲置僵尸进程(实时占用着的才显示) -p 监控指定PID</p>
<table tabindex="0">
<thead>
<tr>
<th style="text-align:left">%Cpu(s):&nbsp;</th>
<th style="text-align:left">&nbsp;0.0 us,</th>
<th style="text-align:left">&nbsp; 0.1 sy,&nbsp;</th>
<th style="text-align:left">&nbsp;0.0 ni,</th>
<th style="text-align:left">&nbsp;99.8 id,</th>
<th style="text-align:left">&nbsp; 0.0 wa,</th>
<th style="text-align:left">&nbsp; 0.1 hi,</th>
<th style="text-align:left">&nbsp; 0.0 si,</th>
<th style="text-align:left">&nbsp; 0.0 st</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:left">cup时间(占用比例</td>
<td style="text-align:left">默<br>认更改优先<br>级的user进程</td>
<td style="text-align:left">system系统进程</td>
<td style="text-align:left">nice 指定友<br>善值的进程<br>，越友善优先级越低</td>
<td style="text-align:left">idel 空闲中的时间</td>
<td style="text-align:left">wait等待IO的占用</td>
<td style="text-align:left">hardware interrupt</td>
<td style="text-align:left">software interrupt</td>
<td style="text-align:left">stole<br>n被虚拟化<br>设备偷走的时间</td>
</tr>
<tr>
<td style="text-align:left">PR</td>
<td style="text-align:left">NI</td>
<td style="text-align:left">VIRT</td>
<td style="text-align:left">RES</td>
<td style="text-align:left">SHR</td>
<td style="text-align:left">time+</td>
<td style="text-align:left"></td>
<td style="text-align:left"></td>
<td style="text-align:left"></td>
</tr>
<tr>
<td style="text-align:left">priority优先级</td>
<td style="text-align:left">nice值</td>
<td style="text-align:left">虚拟内存占用大小</td>
<td style="text-align:left">real实际内存占用</td>
<td style="text-align:left">share共享内存大小</td>
<td style="text-align:left">总共占用的CUP时间，+表示精确</td>
<td style="text-align:left"></td>
<td style="text-align:left"></td>
<td style="text-align:left"></td>
</tr>
</tbody>
</table>
<p>shift +p 按照CUP占用分<br>
shift +n 按照PID大小<br>
空格立即刷新<br>
s 设置刷新时间间隔<br>
c 显示命令完全模式<br>
命令 k 9终止</p>
<p>3、查 看磁盘 IO 读写情况：iotop -o（直接查看输出比较高的磁盘读写程序）
4、查看端口占用情况：netstat -tunlp | grep 端口号</p>
<h2 id="网络相关" tabindex="-1">网络相关 <a class="header-anchor" href="#网络相关" aria-label="Permalink to &quot;网络相关&quot;">&ZeroWidthSpace;</a></h2>
<p>netstat，详细的网络状态</p>
<ul>
<li>-a 显示 所有websocket</li>
<li>-n 强制全用ip</li>
<li>-l 列出正在监听的服务状态</li>
<li>-p 显示那个进程在调用</li>
</ul>
<h3 id="定时任务" tabindex="-1">定时任务 <a class="header-anchor" href="#定时任务" aria-label="Permalink to &quot;定时任务&quot;">&ZeroWidthSpace;</a></h3>
<p>crontab依赖于crond<br>
crontab -e 编辑cron文件 -l 查看当前用户的定时任务 -r 清除当前用户的定时任务<br>
任务格式<code>* * * * * 任务文件位置 参数</code> <strong>几分 几小时 几号 几月 星期几</strong>执行</p>
<table tabindex="0">
<thead>
<tr>
<th>特殊符号</th>
<th>含义</th>
</tr>
</thead>
<tbody>
<tr>
<td>*</td>
<td>代表任何时间。 比如第一个“*”就代表一小时中每分钟 都执行一次的意思。</td>
</tr>
<tr>
<td>，</td>
<td>代表不连续的时间。 比如“0 8,12,16 * * * 命令”， 就代表 在每天的 8 点 0 分，12 点 0 分，16 点 0 分都执行一次命令</td>
</tr>
<tr>
<td>-</td>
<td>代表连续的时间范围。比如“0 5 * * 1-6 命令”，代表在 周一到周六的凌晨 5 点 0 分执行命令</td>
</tr>
<tr>
<td>*/n</td>
<td>代表每隔多久执行一次。比如“ * /10 * * * * 命令”，代 表每隔 10 分钟就执行一遍命令</td>
</tr>
</tbody>
</table>
<h2 id="包管理" tabindex="-1">包管理 <a class="header-anchor" href="#包管理" aria-label="Permalink to &quot;包管理&quot;">&ZeroWidthSpace;</a></h2>
<h3 id="rpm" tabindex="-1">RPM <a class="header-anchor" href="#rpm" aria-label="Permalink to &quot;RPM&quot;">&ZeroWidthSpace;</a></h3>
<p>RedhatPackageManager<br>
命名规范: 软件名.版本名.平台.rpm<br>
rpm -a 所有的 -q[i] 查询 [查看软件信息]，-e 卸载 --nodeps 不考虑依赖直接卸载，安装也有这个参数，可能会导致依赖本软件的软件无法运行<br>
rpm -ivh  rpm 安装，显示信息和进度条</p>
<div class="info custom-block"><p class="custom-block-title">[📝Note]</p>
<p>rpm不会自动解决依赖，而且还需要完整的rpm才能安<br>
所以有了yum(Yellow dog Updater, Modified)自动完成解决依赖找源之类的</p>
</div>
<h3 id="yum" tabindex="-1">yum <a class="header-anchor" href="#yum" aria-label="Permalink to &quot;yum&quot;">&ZeroWidthSpace;</a></h3>
<p><strong>yum</strong> -y <strong>update</strong>：升级所有包同时也升级软件和系统内核<br>
<strong>yum</strong> -y <strong>upgrade</strong>：只升级所有包，不升级软件和系统内核<br>
yum search Software 搜索软件<br>
yum check-update 检查是否有可用的更新 rpm 软件包<br>
yum remove Software 删除指定的 rpm 软件包<br>
yum list Software 显示可用的软件包信息<br>
yum clean (all)清理 yum 过期的缓存<br>
yum deplist 显示 yum 软件包的所有依赖关系（看不太懂）</p>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[part 3 shell脚本]]></title>
            <link>http://ooowl.fun/blogs/Web%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/%E6%B5%8B%E8%AF%95%E8%BF%90%E7%BB%B4/linux%E7%AE%80%E5%8D%95%E9%80%9F%E9%80%9A/part-3-shell%E8%84%9A%E6%9C%AC.html</link>
            <guid isPermaLink="false">http://ooowl.fun/blogs/Web%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/%E6%B5%8B%E8%AF%95%E8%BF%90%E7%BB%B4/linux%E7%AE%80%E5%8D%95%E9%80%9F%E9%80%9A/part-3-shell%E8%84%9A%E6%9C%AC.html</guid>
            <pubDate>Fri, 29 Apr 2022 14:12:45 GMT</pubDate>
            <description><![CDATA[cat /etc/shells 查看系统支持哪些shell $SHELL当前用的啥]]></description>
            <content:encoded><![CDATA[<h1 id="part-3-shell脚本" tabindex="-1">part 3 shell脚本 <a class="header-anchor" href="#part-3-shell脚本" aria-label="Permalink to &quot;part 3 shell脚本&quot;">&ZeroWidthSpace;</a></h1><p class="article-meta">创建于 2022年4月29日 22:12:45 · 约2,051字</p>
<h2 id="shell" tabindex="-1">shell <a class="header-anchor" href="#shell" aria-label="Permalink to &quot;shell&quot;">&ZeroWidthSpace;</a></h2>
<p><code>cat /etc/shells</code> 查看系统支持哪些shell <code>$SHELL</code>当前用的啥</p>
<div class="danger custom-block"><p class="custom-block-title">[🚨Danger] 指定解析器</p>
<p>定解析器
<strong>#!/bin/bash</strong><br>
每个脚本开头都使用&quot;#!&quot;，#!实际上是一个2字节魔法数字，这是指定一个文件类型的特殊标记，在这种情况下，指的就是一个可执行的脚本。在#!之后，接一个路径名，这个路径名指定了一个解释脚本命令的程序，这个程序可以是shell，程序语言或者任意一个通用程序。</p>
</div>
<p>使用bash a.sh的时候就不用+x<br>
<strong>source</strong> or <strong>.</strong>  a.sh也可以执行，<em><strong>在当前shell中一条一条执行，其他的都是开启一个子shell进程执行，可能会获取不到环境变量，子 shell 中设置的 当前变量，父 shell 是不可见的</strong></em><br>
直接bash命令相当于直接进入了子shell操作</p>
<h2 id="变量" tabindex="-1">变量 <a class="header-anchor" href="#变量" aria-label="Permalink to &quot;变量&quot;">&ZeroWidthSpace;</a></h2>
<div class="danger custom-block"><p class="custom-block-title">[🚨Danger]</p>
<p><strong>赋值的时候等号两边一定要空格，否则会被当成一体的字符串！！！
尤其是循环判断</strong>
变量类型会自动判断，小心！</p>
</div>
<h3 id="全局和局部环境变量" tabindex="-1">全局和局部环境变量 <a class="header-anchor" href="#全局和局部环境变量" aria-label="Permalink to &quot;全局和局部环境变量&quot;">&ZeroWidthSpace;</a></h3>
<p>使用env和printenv命令获取所有系统定义的变量<br>
printenv可以不加$符，printenv HOME=echo $HOME<br>
set 可以看到定义的所有变量和函数，自定义的也能看到</p>
<h3 id="系统环境变量和用户定义环境变量" tabindex="-1">系统环境变量和用户定义环境变量 <a class="header-anchor" href="#系统环境变量和用户定义环境变量" aria-label="Permalink to &quot;系统环境变量和用户定义环境变量&quot;">&ZeroWidthSpace;</a></h3>
<p>在命令行里 定义变量，<code>a = 2</code>,<code>echo $a</code> 弱类型，定义字符串用双引号括起来，双引号会自动识别变量表示符<em><strong>单引号不会读取为变量表示符</strong></em><br>
但是定义的是<strong>局部变量</strong>，使用<code>export variable = 2</code>设为<strong>全局变量</strong></p>
<div class="warning custom-block"><p class="custom-block-title">[⚠️Warning]</p>
<p>在子shell里面修改全局变量只会在子范围里面生效，上级不会生效，<strong>export也没用</strong><br>
export只在本次会话中生效</p>
</div>
<p><em><strong>约定俗成系统变量大写，自定义变量小写</strong></em></p>
<p>默认等号后面都是字符串，如果要做数值运算，应该使用<code>a = $((1+5))</code> or <code>a = $[5+1]</code></p>
<h3 id="只读变量" tabindex="-1">只读变量 <a class="header-anchor" href="#只读变量" aria-label="Permalink to &quot;只读变量&quot;">&ZeroWidthSpace;</a></h3>
<p>静态常量 <code>readonly a = 5</code> <code>unset variable</code>，从环境中删除variable<br>
bin和sbin目录下都是系统的定义的可执行，查看$PATH就可以，路径添加到 $ PATH 的格式为 <code> PATH=$PATH:&lt;PATH1&gt;:&lt;PATH2&gt;</code><br>
或者编辑变量文件在最后直接export</p>
<blockquote>
<p>可以设置环境变量有4个 优先级从高到底</p>
</blockquote>
<p>#TODO 环境变量和优先级
<a href="https://einverne.github.io/post/2017/03/bashrc-profile.html" target="_blank" rel="noreferrer">理解 bashrc profile 优先级及区别 | Verne in GitHub</a><br>
<a href="https://zhuanlan.zhihu.com/p/405174594" target="_blank" rel="noreferrer">Linux文件 profile、bashrc、bash_profile区别 - 知乎</a><br>
<a href="https://wido.me/sunteya/understand-bashrc-and-profile" target="_blank" rel="noreferrer">理解 bashrc 和 profile - { wido.me }</a></p>
<ol>
<li><strong>/etc/profile</strong>:在登录时,操作系统定制用户环境时使用的第一个文件,此文件为系统的每个用户设置环境信息,当用户第一次登录时,该文件被执行。</li>
<li><strong>/etc/environment</strong>:在登录时操作系统使用的第二个文件,系统在读取你自己的profile前,设置环境文件的环境变量。</li>
<li><strong>~/.bash_profile</strong>:在登录时用到的第三个文件是.profile文件,每个用户都可使用该文件输入专用于自己使用的shell信息,当用户登录时,该 文件仅仅执行一次!默认情况下,他设置一些环境变游戏量,执行用户的.bashrc文件。/etc/bashrc:为 每一个运行bash shell的用户执行此文件.当bash shell被打开时,该文件被读取.</li>
<li><strong>~/.bashrc</strong>:激活shell时使用该文件</li>
</ol>
<h3 id="接收变量" tabindex="-1">接收变量 <a class="header-anchor" href="#接收变量" aria-label="Permalink to &quot;接收变量&quot;">&ZeroWidthSpace;</a></h3>
<ul>
<li>$$ Shell本身的PID（ProcessID）</li>
<li>$! Shell最后运行的后台Process的PID</li>
<li>$0 表示脚本本身的名称,带路径</li>
<li>$1 就是第一个参数，$2就是第二个以此类推</li>
<li>$# 获取接收的参数个数</li>
<li>$* 获取所有参数视为一个字符串&quot;在被双引号括起来时&quot;</li>
<li>$@ 把参数作为数组</li>
<li>$? 上次执行脚本的返回码 (0-255)，<strong>这个直接在命令行执行完脚本后使用</strong>，在脚本中用会返回上一个命令(也是脚本)而不是本次的</li>
</ul>
<p>basename 命令路径可以获取最后一个/分割的内容，如果跟着第二个参数suffix就会去掉后缀<br>
dirname 返回的是该文件的路径，也是简单的字符串分割</p>
<h2 id="表达式" tabindex="-1">表达式 <a class="header-anchor" href="#表达式" aria-label="Permalink to &quot;表达式&quot;">&ZeroWidthSpace;</a></h2>
<h3 id="运算符" tabindex="-1">运算符 <a class="header-anchor" href="#运算符" aria-label="Permalink to &quot;运算符&quot;">&ZeroWidthSpace;</a></h3>
<p>shell默认是不会解析基本数学表达式的，需要使用<code>expr 1 + 2</code>命令，注意<strong>必须要有空格</strong>，乘号使用*<br>
命令替换使用两个反引号，把结果赋给变量。</p>
<p>为了解决麻烦，使用<code>$((表达式))</code>或<code>$[表达式]</code>，在for和if中可以<code>((expression))</code>但是不提倡</p>
<h3 id="判断" tabindex="-1">判断 <a class="header-anchor" href="#判断" aria-label="Permalink to &quot;判断&quot;">&ZeroWidthSpace;</a></h3>
<h4 id="if" tabindex="-1">if <a class="header-anchor" href="#if" aria-label="Permalink to &quot;if&quot;">&ZeroWidthSpace;</a></h4>
<p>test 命令检查某条件是否成立，可进行数值、字符和文件的测试，使用echo $?查看返回码0代表正常运行就是一样(好怪)<br>
可以简写成<code>[ condition ]</code> 方括号一定要有空格，条件<strong>非空为True 1，空为False 0</strong></p>
<p>字符串就=,!=，数值判断不能用符号,[4 -ne 5]～4≠5</p>
<table tabindex="0">
<thead>
<tr>
<th style="text-align:left">-eq</th>
<th style="text-align:left">等于（equal）=</th>
<th style="text-align:left">-ne</th>
<th style="text-align:left">不等于（not equal）≠</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:left">-lt</td>
<td style="text-align:left">小于（less than）&lt;</td>
<td style="text-align:left">-le</td>
<td style="text-align:left">小于等于（less equal）&lt;=</td>
</tr>
<tr>
<td style="text-align:left">-gt</td>
<td style="text-align:left">大于（greater than）&gt;</td>
<td style="text-align:left">-ge</td>
<td style="text-align:left">大于等于（greater equal）&gt;=</td>
</tr>
</tbody>
</table>
<p>判断文件是否有权限<br>
-r 读 -w 写 -x 执行</p>
<p>判断文件类型<br>
-e 文件存在（existence） -f 存在且是文件（file） -d 存在且是目录（directory）</p>
<p>&amp;&amp; 与 || 或 ! 非<br>
<code>[ ] &amp;&amp; echo OK || echo notOK</code> 整成三元运算符<br>
在一个[]里进行与或判断的话，形式如下<code>[ condition1 -a/-o condition2 ]</code> and -a ; or  -o<br>
一般多个条件是<code>[ cond1 ] &amp;&amp; [ cond2 ]</code><br>
if 命令格式有点不一样</p>
<div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> [ expression ];</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">then</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    process</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">fi</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 完全体</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> [ expression ]</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">then</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    process</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">elif</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> [ con ]</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">then</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    process</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">else</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    process</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">fi</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br></div></div><p><code>;</code>作用是在一行里把两个命令隔开</p>
<div class="tip custom-block"><p class="custom-block-title">[💡Tip] if 使用时候的小技巧</p>
<p>f 使用时候的小技巧
在判断字符串后面拼接一个字符，即使不输入也不会报错<br>
<code>if [ &quot;$1&quot;x=&quot;condition&quot;x ];then</code></p>
</div>
<h4 id="case" tabindex="-1">case <a class="header-anchor" href="#case" aria-label="Permalink to &quot;case&quot;">&ZeroWidthSpace;</a></h4>
<div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">case</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> $variable </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#DBEDFF">value1</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">)</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    process</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;;</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#DBEDFF">value2</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">)</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    process</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*)</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    default</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">esac</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br></div></div><p>就是switch case，语法真的奇怪</p>
<h3 id="循环" tabindex="-1">循环 <a class="header-anchor" href="#循环" aria-label="Permalink to &quot;循环&quot;">&ZeroWidthSpace;</a></h3>
<h4 id="for" tabindex="-1">for <a class="header-anchor" href="#for" aria-label="Permalink to &quot;for&quot;">&ZeroWidthSpace;</a></h4>
<p><strong>注意变量自加的写法</strong></p>
<div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 普通for</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> ((init;condition;variables</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">change))</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">do</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    process</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">done</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 增强for</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "a","b","c"</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">do</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    echo</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> $i</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">done</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 一个递加到指定数的for操作，注意变量的使用和数学表达式</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">((i</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;i</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x3C;=</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">$1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;i</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">++</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">))</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">do</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    sum</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">$</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">[</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> $sum </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">+</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> $i </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">]</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">done</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">echo</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> $sum</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br></div></div><h4 id="while" tabindex="-1">while <a class="header-anchor" href="#while" aria-label="Permalink to &quot;while&quot;">&ZeroWidthSpace;</a></h4>
<p>一般要在外面提前定义变量</p>
<div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">a</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">1</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">while</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> [ $a </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-le</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70"> $1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> ]</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">do</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 注释里为新写法</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    sum</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">$</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">[</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> $sum</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">+</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">$a </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">]</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # let sum+=a</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    a</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">$</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">[</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> $a </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">+</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> ]</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # let a=a+1</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">done</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br></div></div><h3 id="console-io" tabindex="-1">console IO <a class="header-anchor" href="#console-io" aria-label="Permalink to &quot;console IO&quot;">&ZeroWidthSpace;</a></h3>
<div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">read</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -t</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 10</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -p</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "输入你的名字"</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> name</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p>read 命令，只能在脚本文件里面使用，命令行里会出现-p: no coprocess</p>
<ul>
<li>-a 后跟一个变量，该变量会被认为是个数组，然后给其赋值，默认是以空格为分割符。</li>
<li>-d 后面跟一个标志符，其实只有其后的第一个字符有用，作为结束的标志。</li>
<li>-p 后面跟提示信息，即在输入前打印提示信息。</li>
<li>-e 在输入的时候可以使用命令补全功能。</li>
<li>-n 后跟一个数字，定义输入文本的长度，很实用。</li>
<li>-r 屏蔽\，如果没有该选项，则\作为一个转义字符，有的话 \就是个正常的字符了。</li>
<li>-s 安静模式，在输入字符时不再屏幕上显示，例如login时输入密码。</li>
<li>-t 后面跟秒数，定义输入字符的等待时间。</li>
<li>-u 后面跟fd，从文件描述符中读入，该文件描述符可以是exec新开启的。</li>
</ul>
<h2 id="函数" tabindex="-1">函数 <a class="header-anchor" href="#函数" aria-label="Permalink to &quot;函数&quot;">&ZeroWidthSpace;</a></h2>
<p>系统命令要使用命令替换，<code>$( expression ) </code> 实际上就是获得值赋予</p>
<p>自定义函数</p>
<div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">function</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> f</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">() # </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">function</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> 括号都能省略</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    variable</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">$</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">[</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70"> $1</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> +</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70"> $2</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> ]</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 注意参数的定义</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    Action</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> int</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 省略return返回值是上一个函数语句执行完的$?状态码范围必须0-255整数</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    # 如果要返回数据，要配合使用</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    echo</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> $variable</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">f</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> $a $b </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 注意参数的传入</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 返回值技巧</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">outer</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">$(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">f</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> $a $b) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 输出结果就会被赋到outer</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br></div></div><p>调用之前必先声明，严格顺序，因为他就是单纯逐行执行。</p>
<h2 id="文本处理" tabindex="-1">文本处理 <a class="header-anchor" href="#文本处理" aria-label="Permalink to &quot;文本处理&quot;">&ZeroWidthSpace;</a></h2>
<h3 id="正则表达式" tabindex="-1">正则表达式 <a class="header-anchor" href="#正则表达式" aria-label="Permalink to &quot;正则表达式&quot;">&ZeroWidthSpace;</a></h3>
<p>grep awk sed cut vim+/ 后面可以直接使用正则，但是什么情况下会使用还不知道，之后再补充吧</p>
<h3 id="命令" tabindex="-1">命令 <a class="header-anchor" href="#命令" aria-label="Permalink to &quot;命令&quot;">&ZeroWidthSpace;</a></h3>
<p><code>cut -d &quot;spliter&quot; -f column1,2-5 file </code> 以spliter为分割符取1，2到5列，-默认不填就是截到开头结尾
awk是gawk的软链接,是GNU的gawk的实现<br>
默认以空格分割<br>
<code>awk -F &quot;spliter&quot; '/regex pattern/ {action}'</code><br>
<code>awk -F &quot;:&quot; -v i=100 'BEGIN{print &quot;user, shell&quot;} {print $1+i&quot;,&quot;$7} END{print &quot;dahaige,/bin/zuishuai&quot;}' passwd</code><br>
以 : 为分割符，定义变量i = 100 开始前先打印一行&quot;user, shell&quot;，打印第一列+i 结束时打印&quot;dahaige,/bin/zuishuai&quot;</p>
<table tabindex="0">
<thead>
<tr>
<th style="text-align:left">内置变量</th>
<th style="text-align:left">含义</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:left">FILENAME</td>
<td style="text-align:left">文件名</td>
</tr>
<tr>
<td style="text-align:left">NR</td>
<td style="text-align:left">行号</td>
</tr>
<tr>
<td style="text-align:left">NF</td>
<td style="text-align:left">切割后列号</td>
</tr>
</tbody>
</table>
<p><code>awk -F &quot; &quot; '/^'&quot;$VALU&quot;'/ {print $2}'</code> 正则中使用外部变量</p>
<h2 id="发送消息" tabindex="-1">发送消息 <a class="header-anchor" href="#发送消息" aria-label="Permalink to &quot;发送消息&quot;">&ZeroWidthSpace;</a></h2>
<p><code>mesg，who -T </code>查看是否开启接收其他用户消息，<code>mesg n/y</code>关闭/打开消息<br>
<code>write user tty</code> 发送和接收方都会进入多行编辑模式。</p>
<h2 id="实例" tabindex="-1">实例 <a class="header-anchor" href="#实例" aria-label="Permalink to &quot;实例&quot;">&ZeroWidthSpace;</a></h2>
<h3 id="example-1-定时归档目录" tabindex="-1">example 1 - 定时归档目录 <a class="header-anchor" href="#example-1-定时归档目录" aria-label="Permalink to &quot;example 1 - 定时归档目录&quot;">&ZeroWidthSpace;</a></h3>
<p>要求:</p>
<ul>
<li>定时归档文件</li>
<li>用tar打包</li>
<li>附加日期</li>
<li>存储日志</li>
</ul>
<details class="details custom-block"><summary>Click to see more</summary>
<div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#!/bin/bash</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 判断参数是否为1</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> [ </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">$#</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> -ne</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> ]</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#!/bin/bash</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 判断参数是否为1</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> [ </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">$#</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> -ne</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> ]</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">then</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        echo</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "参数个数错误，目录应为1"</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        exit</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">fi</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 获取路径</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> [ </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-d</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70"> $1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  ]</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">then</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        echo</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> ""</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">else</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        echo</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "目录不存在"</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">fi</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">DATE</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">$( </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">date</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> +%y-%m-%d</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> )</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">DIRNAME</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">$( </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">basename</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70"> $1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> )</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">DIRPATH</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">$(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">cd</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> $(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">dirname</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70"> $1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">pwd</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> )</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">FILE</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">archive_</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">$DIRNAME_$DATE</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">echo</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "开始归档"</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">tar</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -czf</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> /home/jack/</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">$FILE $DIRPATH</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">/</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">$DIRNAME</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> [ </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">$?</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> -eq</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  ]</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">then</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        echo</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "压缩完成"</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">else</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        echo</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "压缩失败"</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">fi</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">exit</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br></div></div></details>
<h3 id="example-2-发送消息" tabindex="-1">example 2 - 发送消息 <a class="header-anchor" href="#example-2-发送消息" aria-label="Permalink to &quot;example 2 - 发送消息&quot;">&ZeroWidthSpace;</a></h3>
<p>使用Linux自带的mesg和write命令向其他用户发送消息</p>
<ul>
<li>command user message</li>
<li>检测用户是否在线</li>
<li>检测用户是否打开了消息</li>
<li>基本的判空特殊字符串处理等</li>
</ul>
<details class="details custom-block"><summary>Click to see more</summary>
<div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#!/bin/bash</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 获取用户列表注意列表的使用 l=(1 2 "3")</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">userlist</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">($(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">who</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -T</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> |</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> awk</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -F</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> " "</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> '{print $1}'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) )</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 检查参数</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> [ </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">$#</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> -eq</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> ] &#x26;&#x26; [[ </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">userlist</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">[</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">@</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">]}"</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =~</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70"> $1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> ]] &#x26;&#x26; [ </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">$2</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> !=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> ""</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> ];</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">then</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 判断元素是否在列表里以及判空</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        USER</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">$1</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        MSG</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">$2</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        TTY</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">$(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">who</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -T</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> |</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> awk</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -F</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> " "</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> '/^'"</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">$1</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"'/ {print $3}'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">else</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        echo</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "args number is unsuitable"</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">fi</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 检查用户是否在线</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> [ $(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">who</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -T</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> |</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> awk</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -F</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> " "</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">  '/^'"</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">$1</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"'/ {print $2}'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> ) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "+"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> ];</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">then</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # awk 正则表达式使用外部变量</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        echo</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> $MSG </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">|</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">write</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> $USER $TTY</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">else</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        echo</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "user is offline"</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">fi</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">exit</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br></div></div></details>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[part 1 linux的历史节点]]></title>
            <link>http://ooowl.fun/blogs/Web%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/%E6%B5%8B%E8%AF%95%E8%BF%90%E7%BB%B4/linux%E7%AE%80%E5%8D%95%E9%80%9F%E9%80%9A/README.html</link>
            <guid isPermaLink="false">http://ooowl.fun/blogs/Web%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/%E6%B5%8B%E8%AF%95%E8%BF%90%E7%BB%B4/linux%E7%AE%80%E5%8D%95%E9%80%9F%E9%80%9A/README.html</guid>
            <pubDate>Fri, 29 Apr 2022 14:10:10 GMT</pubDate>
            <description><![CDATA[[💡Tip]]]></description>
            <content:encoded><![CDATA[<h1 id="part-1-linux的历史节点" tabindex="-1">part 1 linux的历史节点 <a class="header-anchor" href="#part-1-linux的历史节点" aria-label="Permalink to &quot;part 1 linux的历史节点&quot;">&ZeroWidthSpace;</a></h1><p class="article-meta">创建于 2022年4月29日 22:10:10 · 约2,318字</p>
<div class="tip custom-block"><p class="custom-block-title">[💡Tip]</p>
<p>自己写来复习用，会的很多都没写上，看鸟哥记的笔记比较全。</p>
</div>
<!--more-->
<p>看的<a href="https://www.bilibili.com/video/BV1WY4y1H7d3" target="_blank" rel="noreferrer">尚硅谷的linux</a><br>
Linux图标企鹅名字叫tux(晚礼服)，系统是linus Torvalds开发<br>
<a href="https://linuxtools-rst.readthedocs.io/zh_CN/latest/index.html" target="_blank" rel="noreferrer">这本书也不错</a></p>
<h2 id="linux的开发事件节点" tabindex="-1">linux的开发事件节点 <a class="header-anchor" href="#linux的开发事件节点" aria-label="Permalink to &quot;linux的开发事件节点&quot;">&ZeroWidthSpace;</a></h2>
<h3 id="unix的过程" tabindex="-1">unix的过程 <a class="header-anchor" href="#unix的过程" aria-label="Permalink to &quot;unix的过程&quot;">&ZeroWidthSpace;</a></h3>
<p>最开始世界都是批处理操作系统，贝尔实验室+MIT+GE联合开发多用户分时OS: Multics，失败了-&gt;unix是贝尔实验室开发 <mark>Ken</mark> Thompson牵头和Dennis <mark>Ritchie</mark>吸取教训一块开发的</p>
<h3 id="c语言的过程" tabindex="-1">C语言的过程 <a class="header-anchor" href="#c语言的过程" aria-label="Permalink to &quot;C语言的过程&quot;">&ZeroWidthSpace;</a></h3>
<p>(全名: 肯尼斯·蓝·汤普森Kenneth Lane Thompson丹尼斯·里奇Dennis MacAlistair Ritchie)
unix 一开始用汇编，理念是保持高效和简洁，汇编复杂开发越来越难，当时流行的Fortran觉得不好用，所以K&amp;R(Ken&amp;Ritchie)就自己开发语言</p>
<p>当时有这么几种语言。</p>
<ul>
<li>最开始是 ALGOL 60语言也称A语言，A语言不能对硬件直接操作不适合写操作系统</li>
<li>剑桥大学将ALGOL 60语言发展成为CPL(Combined Programming Language)语言</li>
<li>剑桥大学的Matin Richards 对CPL语言进行了简化，于是产生了BCPL语言 (解释型语言，无法满足要求失败了)</li>
<li>Ken Thompson将BCPL进行了修改，命名为<a href="https://zh.wikipedia.org/wiki/B%E8%AA%9E%E8%A8%80" target="_blank" rel="noreferrer">B语言</a>意思是将CPL语言煮干，提炼出它的精华。</li>
<li>Dennis MacAlistair Ritchie再对B语言进行修改，取BCPL的第二个字母作语言名字，最终形成了C语言，并用C语言写了unix</li>
</ul>
<p>unix一开始小范围内是开源的，但是商业化开发时候选择付费。</p>
<ul>
<li>unix的变种:BSD,Solaris,IBM-AIX,HP-UX,主要用在单个大型服务器，对硬件依赖严重，在分布时代逐渐不行。</li>
<li>唯一比较强的是<a href="https://en.wikipedia.org/wiki/Berkeley_Software_Distribution" target="_blank" rel="noreferrer">BSD</a>-&gt;FreeBSD-&gt;darwin-&gt;macOS，FreeBSD因为版权问题发布比较晚,遵循BSD协议，对商业化更友好见  <a href="/blogs/代码之外/开源协议.html#^4fd49b">开源协议</a></li>
</ul>
<h3 id="linux的过程" tabindex="-1">linux的过程 <a class="header-anchor" href="#linux的过程" aria-label="Permalink to &quot;linux的过程&quot;">&ZeroWidthSpace;</a></h3>
<p>因为一般人用不起unix也没见过，为了方便研究荷兰教授Andrew Tanenbaum(大黑书计算机网络作者)写了不包含版权代码的类似unix的系统-&gt;minix开放源代码-&gt;linus觉得不好用，干脆重写-&gt;写了Linux</p>
<p>Linus发布后越来越多的人贡献代码，当时集中式的SVN比较多-&gt;分布式的gitkeeper05年对他们收费-&gt;为了管理就写了Git(只用了一星期)-&gt;08年Github上线。<br>
<a href="https://www.zhihu.com/question/22826568/answer/318102471" target="_blank" rel="noreferrer">知乎一老哥整理的历史</a></p>
<h2 id="gnu自由软件运动" tabindex="-1">GNU自由软件运动 <a class="header-anchor" href="#gnu自由软件运动" aria-label="Permalink to &quot;GNU自由软件运动&quot;">&ZeroWidthSpace;</a></h2>
<p>当时软件越来越多注册专利，Richard Stallman是<a href="https://zh.wikipedia.org/wiki/%E8%87%AA%E7%94%B1%E8%BD%AF%E4%BB%B6%E8%BF%90%E5%8A%A8" target="_blank" rel="noreferrer">自由软件运动</a>倡导者对此很气愤，1983年发起<a href="https://zh.wikipedia.org/wiki/GNU" target="_blank" rel="noreferrer">GUN</a>(<a href="https://www.gnu.org/home.en.html" target="_blank" rel="noreferrer">GNU's Not Unix.</a>) 起草了<a href="https://zh.wikipedia.org/wiki/GNU%E9%80%9A%E7%94%A8%E5%85%AC%E5%85%B1%E8%AE%B8%E5%8F%AF%E8%AF%81" target="_blank" rel="noreferrer">GPL</a>见<a href="/blogs/代码之外/开源协议.html#^b38a21">GPL协议</a>.<br>
作为操作系统，GNU的发展仍未完成，其中最大的问题是具有完备功能的内核尚未被开发成功，linus1991年开发后直接加入了GUN，由此大多使用Linux=(GNU/Linux)</p>
<h2 id="发行版" tabindex="-1">发行版 <a class="header-anchor" href="#发行版" aria-label="Permalink to &quot;发行版&quot;">&ZeroWidthSpace;</a></h2>
<p>hardware-&gt;kernel-&gt;shell-&gt;Application<br>
<strong>共同</strong>:所有的发行版都遵循GPL使用Linux内核版本格式约定基本一样（主版本号.次版本号.发行号.修正号）<br>
<strong>区别</strong>: 继承不同版本的内核，库、程序,使用不同的包管理器，软件侧重方向不同<br>
linux 发行版分类: <a href="https://www.cnblogs.com/kangfeng/articles/7990261.html" target="_blank" rel="noreferrer">Linux的发行版</a></p>
<ul>
<li>Debian
<ul>
<li>Linux Mint</li>
<li>Ubuntu</li>
</ul>
</li>
<li>Slackware
<ul>
<li>suse</li>
<li>OpenSUSE</li>
<li>SLES(SUSE Linux Enterprise Server(SLES)</li>
</ul>
</li>
<li>Redhat
<ul>
<li>RHEL(Red Hat Enterprise Linux)</li>
<li>Fedora 激进测试</li>
<li>Centos 稳定社区开源(已停止)</li>
</ul>
</li>
<li>其他
<ul>
<li>Gentoo 极致定制</li>
<li>Arch 极客激进</li>
</ul>
</li>
</ul>
<h2 id="posix" tabindex="-1">POSIX <a class="header-anchor" href="#posix" aria-label="Permalink to &quot;POSIX&quot;">&ZeroWidthSpace;</a></h2>
<p><a href="https://pubs.opengroup.org/onlinepubs/9699919799/" target="_blank" rel="noreferrer">The Open Group Base Specifications Issue 7, 2018 edition</a><br>
<a href="https://zh.wikipedia.org/wiki/%E5%8F%AF%E7%A7%BB%E6%A4%8D%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E6%8E%A5%E5%8F%A3" target="_blank" rel="noreferrer">POSIX规范wiki</a><br>
<a href="https://zhuanlan.zhihu.com/p/78080748" target="_blank" rel="noreferrer">stallman的采访</a><br/>
<a href="https://github.com/cisen/blog/issues/701" target="_blank" rel="noreferrer">热门博客的解释</a></p>
<hr>
<h2 id="文件夹功能" tabindex="-1">文件夹功能 <a class="header-anchor" href="#文件夹功能" aria-label="Permalink to &quot;文件夹功能&quot;">&ZeroWidthSpace;</a></h2>
<SiteMap>
<pre class="pre-1">
<span class="tree-symbols">/ </span>
<span class="tree-symbols">├──</span> bin -> usr/bin # 默认加入系统路径的可执行文件软链接的存放处
<span class="tree-symbols">├──</span> boot # 开机引导文件夹
<span class="tree-symbols">│   ├──</span> efi
<span class="tree-symbols">│   ├──</span> grub
<span class="tree-symbols">│   └──</span> grub2
<span class="tree-symbols">├──</span> dev # 设备管理目录，每个设备都会被对应成一个文件或文件夹
<span class="tree-symbols">├──</span> etc # 配置文件
<span class="tree-symbols">├──</span> home # 普通用户文件夹
<span class="tree-symbols">│   └──</span> ooowl # 每人一个
<span class="tree-symbols">├──</span> lib -> usr/lib # 存放库文件的目录
<span class="tree-symbols">├──</span> lib64 -> usr/lib64 # 存放库文件的目录
<span class="tree-symbols">├──</span> media # 挂在可移动媒体设备U盘光驱
<span class="tree-symbols">├──</span> mnt # 外部存储和硬盘挂载
<span class="tree-symbols">├──</span> opt # 可选目录，给第三方软件单独留的
<span class="tree-symbols">├──</span> proc # 进程虚拟目录存放正在运行的内存文件
<span class="tree-symbols">├──</span> root # root用户文件夹
<span class="tree-symbols">├──</span> run # 存放系统运行起来的实时信息，临时的文件系统，重启就刷新
<span class="tree-symbols">├──</span> sbin -> usr/sbin # 默认加入系统路径的系统级可执行文件软链接的存放处
<span class="tree-symbols">├──</span> srv # 系统服务相关的文件
<span class="tree-symbols">├──</span> sys # 系统硬件信息的相关文件，看意思知道大概
<span class="tree-symbols">│   ├──</span> block
<span class="tree-symbols">│   ├──</span> bus
<span class="tree-symbols">│   ├──</span> class
<span class="tree-symbols">│   ├──</span> dev
<span class="tree-symbols">│   ├──</span> devices
<span class="tree-symbols">│   ├──</span> firmware
<span class="tree-symbols">│   ├──</span> fs
<span class="tree-symbols">│   ├──</span> hypervisor
<span class="tree-symbols">│   ├──</span> kernel
<span class="tree-symbols">│   ├──</span> module
<span class="tree-symbols">│   └──</span> power
<span class="tree-symbols">├──</span> system-update -> /var/lib/PackageKit/prepared-update #
<span class="tree-symbols">├──</span> tmp # 系统和用户存放临时文件的目录
<span class="tree-symbols">├──</span> usr #
<span class="tree-symbols">│   ├──</span> bin
<span class="tree-symbols">│   ├──</span> etc
<span class="tree-symbols">│   ├──</span> games
<span class="tree-symbols">│   ├──</span> include
<span class="tree-symbols">│   ├──</span> lib
<span class="tree-symbols">│   ├──</span> lib64
<span class="tree-symbols">│   ├──</span> libexec
<span class="tree-symbols">│   ├──</span> local
<span class="tree-symbols">│   ├──</span> sbin
<span class="tree-symbols">│   ├──</span> share
<span class="tree-symbols">│   ├──</span> src
<span class="tree-symbols">│   └──</span> tmp -> ../var/tmp #  临时目录，不定时会被清理或者重启会丢失
<span class="tree-symbols">└──</span> var # 可变目录，一直变动的东西会存放在这里
<span class="tree-symbols">    ├──</span> backups
<span class="tree-symbols">    ├──</span> cache
<span class="tree-symbols">    ├──</span> lib
<span class="tree-symbols">    ├──</span> local
<span class="tree-symbols">    ├──</span> lock -> /run/lock
<span class="tree-symbols">    ├──</span> log
<span class="tree-symbols">    ├──</span> mail
<span class="tree-symbols">    ├──</span> opt
<span class="tree-symbols">    ├──</span> run -> /run
<span class="tree-symbols">    ├──</span> spool
<span class="tree-symbols">    └──</span> tmp
</pre>
</SiteMap>
<h2 id="vim操作" tabindex="-1">vim操作 <a class="header-anchor" href="#vim操作" aria-label="Permalink to &quot;vim操作&quot;">&ZeroWidthSpace;</a></h2>
<p><code>/</code>或者<code>:</code> 进入命令模式,编辑模式按i，普通模式可以进行选中复制粘贴之类的操作。<br>
整理常用</p>
<table tabindex="0">
<thead>
<tr>
<th style="text-align:left">键位</th>
<th style="text-align:left">操作</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:left">u</td>
<td style="text-align:left">undo/redo</td>
</tr>
<tr>
<td style="text-align:left">数字+yy</td>
<td style="text-align:left">复制n行</td>
</tr>
<tr>
<td style="text-align:left">数字+p</td>
<td style="text-align:left">粘贴几次</td>
</tr>
<tr>
<td style="text-align:left">X/x</td>
<td style="text-align:left">往前/后剪切一个字符</td>
</tr>
<tr>
<td style="text-align:left">d/y+$/^</td>
<td style="text-align:left">从光标处删除/复制到行尾 / 从行头删除/复制到 光标处</td>
</tr>
<tr>
<td style="text-align:left">数字+dd</td>
<td style="text-align:left">删除一行</td>
</tr>
<tr>
<td style="text-align:left">DW</td>
<td style="text-align:left">从光标到词尾删除一个词，即以空格符号分开的词，后方空格也会删掉</td>
</tr>
<tr>
<td style="text-align:left">r/R+字符</td>
<td style="text-align:left">替换掉当前处的字符/insert模式，会自动替换掉本行后面的字符</td>
</tr>
<tr>
<td style="text-align:left">$/^</td>
<td style="text-align:left">移动到行头/尾</td>
</tr>
<tr>
<td style="text-align:left">w/e</td>
<td style="text-align:left">移动到下一个词的头/尾</td>
</tr>
<tr>
<td style="text-align:left">b</td>
<td style="text-align:left">上一个词的头</td>
</tr>
<tr>
<td style="text-align:left">gg/GG</td>
<td style="text-align:left">文档的开头/结尾</td>
</tr>
<tr>
<td style="text-align:left">数字+H</td>
<td style="text-align:left">跳到某一行的行头，不加数字直接行头</td>
</tr>
</tbody>
</table>
<p>编辑模式可以i或者o相当于新开一行.<br>
命令模式
不用说的w,q,!</p>
<table tabindex="0">
<thead>
<tr>
<th style="text-align:left">命令</th>
<th style="text-align:left">效果</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:left">noh</td>
<td style="text-align:left">去掉高亮</td>
</tr>
<tr>
<td style="text-align:left">s/字符</td>
<td style="text-align:left">查找</td>
</tr>
<tr>
<td style="text-align:left">s/old/new</td>
<td style="text-align:left">替换当前第一个</td>
</tr>
<tr>
<td style="text-align:left">s/old/new/g</td>
<td style="text-align:left">替换当前行所有的</td>
</tr>
<tr>
<td style="text-align:left">%s/old/new</td>
<td style="text-align:left">替换每一行第一个</td>
</tr>
<tr>
<td style="text-align:left">%s/old/new/g</td>
<td style="text-align:left">替换文档中所有的</td>
</tr>
</tbody>
</table>
<table tabindex="0">
<thead>
<tr>
<th style="text-align:left">命令</th>
<th style="text-align:left">效果</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:left">set nu/nonu</td>
<td style="text-align:left">显示行号/关闭</td>
</tr>
<tr>
<td style="text-align:left">noh</td>
<td style="text-align:left">关闭高亮</td>
</tr>
<tr>
<td style="text-align:left">syantx on</td>
<td style="text-align:left">语法显示</td>
</tr>
</tbody>
</table>
<p>/+字符，查找之后高亮，按enter保持，n/N是下/上一个</p>
<h2 id="一些服务" tabindex="-1">一些服务 <a class="header-anchor" href="#一些服务" aria-label="Permalink to &quot;一些服务&quot;">&ZeroWidthSpace;</a></h2>
<p>hostname，返回主机名，hostnamectl set-hostname xxx 或者修改/etc/hostname可以改变，由hostnamectl提供服务</p>
<h3 id="service-和systemctl" tabindex="-1">service 和systemctl <a class="header-anchor" href="#service-和systemctl" aria-label="Permalink to &quot;service 和systemctl&quot;">&ZeroWidthSpace;</a></h3>
<p>service 服务 start/stop/restart/status 管理系统服务,存放在/etc/init.d目录下<br>
centOS6之后使用的是systemctl，service命令都会被重定向到systemctl。systemctl的服务都存放在/usr/lib/systemd/system里面，system的命令分两种，service是服务，target是一组服务的集合。</p>
<p>network服务和networkManager的服务之保留一个就行，这俩是负责网络管理的，貌似在rocky中已经没有了network服务了</p>
<p><a href="https://sysin.org/blog/rocky-linux-8-install/#Rocky-Linux-%E7%AE%80%E4%BB%8B" target="_blank" rel="noreferrer">setuptool</a> 已经没了，可以从这里面看看注意事项。那就跟着视频看看罢了,rocky有web界面管理</p>
<h3 id="运行级别" tabindex="-1">运行级别 <a class="header-anchor" href="#运行级别" aria-label="Permalink to &quot;运行级别&quot;">&ZeroWidthSpace;</a></h3>
<p>init进程是初始化的第一个进程，init会根据不同的级别运行不同的服务脚本<br>
开机-&gt;BIOS-&gt;/boot分区-&gt;启动init进程-&gt;运行级别-&gt;运行对应的服务<br>
一共有7种级别(runlevel)，常用3，5</p>
<ul>
<li>运行级别 0：系统停机状态，系统默认运行级别不能设为 0，否则不能正常启动</li>
<li>运行级别 1：单用户工作状态，root权限，用于系统维护，禁止远程登陆类似于安全模式</li>
<li>运行级别 2：多用户状态（没有 NFS网络文件系统），不支持网络</li>
<li>运行级别 3：完全的多用户状态（有 NFS），登陆后进入控制台命令行模式</li>
<li>运行级别 4：系您未使用，保留</li>
<li>运行级别 5：X11 控制台，登陆后进入图形 GUI模式</li>
<li>运行级别 6：系统正常关闭并重启，默认运行级别不能设为 6，否则不能正常启动</li>
</ul>
<p>CentOS7 的运行级别简化为:
multi-user.target = 级别 3（多用户有网，无图形界面）
graphical.target = 级别 5（多用户有网，有图形界面）</p>
<p>查看当前运行级别:
systemctl get-default
修改默认运行级别 systemctl set-default multi-user.target <strong>or</strong> graphical.target<br>
修改当前运行级别 init 0～6</p>
<p>chkconfig --list 老centos6查看级别运行的服务，用到在去查
systemctl list-unit-files 是7以后的命令。
static是静态服务，其他服务可以调起它
systemctl start/stop/status/disable/enable</p>
<div class="info custom-block"><p class="custom-block-title">[🧪Example]</p>
<p>systemctl status firewalld # 看防火墙的状态
systemctl enable firewalld # 防火墙开机自启</p>
</div>
<h3 id="开关机" tabindex="-1">开关机 <a class="header-anchor" href="#开关机" aria-label="Permalink to &quot;开关机&quot;">&ZeroWidthSpace;</a></h3>
<p>shutdown默认一分钟之后关机<br>
-c是取消，-r是重启 -H 等于halt命令是关机但是不断电，内存里的数据会保持
shutdown now立刻关机<br>
shutdown +数字 多少分钟之后关机;+00:00今天几点关机;-h 几小时后关机
::: note [💬Quote] man shutdown的一部分看看
an shutdown的一部分看看</p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span></span></span>
<span class="line"><span>OPTIONS</span></span>
<span class="line"><span>       The following options are understood:</span></span>
<span class="line"><span></span></span>
<span class="line"><span>       --help</span></span>
<span class="line"><span>           Print a short help text and exit.</span></span>
<span class="line"><span></span></span>
<span class="line"><span>       -H, --halt</span></span>
<span class="line"><span>           Halt the machine.</span></span>
<span class="line"><span></span></span>
<span class="line"><span>       -P, --poweroff</span></span>
<span class="line"><span>           Power-off the machine (the default).</span></span>
<span class="line"><span></span></span>
<span class="line"><span>       -r, --reboot</span></span>
<span class="line"><span>           Reboot the machine.</span></span>
<span class="line"><span></span></span>
<span class="line"><span>       -h</span></span>
<span class="line"><span>           Equivalent to --poweroff, unless --halt is specified.</span></span>
<span class="line"><span></span></span>
<span class="line"><span>       -k</span></span>
<span class="line"><span>           Do not halt, power-off, reboot, just write wall message.</span></span>
<span class="line"><span></span></span>
<span class="line"><span>       --no-wall</span></span>
<span class="line"><span>           Do not send wall message before halt, power-off, reboot.</span></span>
<span class="line"><span></span></span>
<span class="line"><span>       -c</span></span>
<span class="line"><span>           Cancel a pending shutdown. This may be used cancel the</span></span>
<span class="line"><span>           effect of an invocation of shutdown with a time argument</span></span>
<span class="line"><span>           that is not "+0" or "now".</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br></div></div><p>:::</p>
<p>linux会做预读和延迟写入，所以会用sync同步数据
实际上shutdown是一串命令的组合<br>
sync，poweroff，reboot，halt</p>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[常用库积累]]></title>
            <link>http://ooowl.fun/blogs/Book/C-primer-plus/%E5%B8%B8%E7%94%A8%E5%BA%93%E7%A7%AF%E7%B4%AF.html</link>
            <guid isPermaLink="false">http://ooowl.fun/blogs/Book/C-primer-plus/%E5%B8%B8%E7%94%A8%E5%BA%93%E7%A7%AF%E7%B4%AF.html</guid>
            <pubDate>Wed, 20 Apr 2022 09:21:46 GMT</pubDate>
            <content:encoded><![CDATA[<h1 id="常用库积累" tabindex="-1">常用库积累 <a class="header-anchor" href="#常用库积累" aria-label="Permalink to &quot;常用库积累&quot;">&ZeroWidthSpace;</a></h1><p class="article-meta">创建于 2022年4月20日 17:21:46 · 约10字</p>
<p><a href="marginnote3app://note/BED81EF1-0B75-4B20-9D09-B87CE18142EB">可移植类型:stdint.h和inttypes.h</a></p>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[C的编译器]]></title>
            <link>http://ooowl.fun/blogs/Book/C-primer-plus/%E7%AC%AC%E4%B8%89%E7%AB%A0-%E6%95%B0%E6%8D%AE%E5%92%8CC/C%E7%9A%84%E7%BC%96%E8%AF%91%E5%99%A8.html</link>
            <guid isPermaLink="false">http://ooowl.fun/blogs/Book/C-primer-plus/%E7%AC%AC%E4%B8%89%E7%AB%A0-%E6%95%B0%E6%8D%AE%E5%92%8CC/C%E7%9A%84%E7%BC%96%E8%AF%91%E5%99%A8.html</guid>
            <pubDate>Tue, 19 Apr 2022 04:22:52 GMT</pubDate>
            <content:encoded><![CDATA[<h1 id="c的编译器" tabindex="-1">C的编译器 <a class="header-anchor" href="#c的编译器" aria-label="Permalink to &quot;C的编译器&quot;">&ZeroWidthSpace;</a></h1><p class="article-meta">创建于 2022年4月19日 12:22:52 · 约0字</p>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[字符串常量存储]]></title>
            <link>http://ooowl.fun/blogs/Book/C-primer-plus/%E7%AC%AC%E4%B8%89%E7%AB%A0-%E6%95%B0%E6%8D%AE%E5%92%8CC/%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%B8%B8%E9%87%8F%E5%AD%98%E5%82%A8.html</link>
            <guid isPermaLink="false">http://ooowl.fun/blogs/Book/C-primer-plus/%E7%AC%AC%E4%B8%89%E7%AB%A0-%E6%95%B0%E6%8D%AE%E5%92%8CC/%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%B8%B8%E9%87%8F%E5%AD%98%E5%82%A8.html</guid>
            <pubDate>Mon, 18 Apr 2022 10:59:18 GMT</pubDate>
            <content:encoded><![CDATA[<h1 id="字符串常量存储" tabindex="-1">字符串常量存储 <a class="header-anchor" href="#字符串常量存储" aria-label="Permalink to &quot;字符串常量存储&quot;">&ZeroWidthSpace;</a></h1><p class="article-meta">创建于 2022年4月18日 18:59:18 · 约1,102字</p>
<h2 id="内存区域" tabindex="-1">内存区域 <a class="header-anchor" href="#内存区域" aria-label="Permalink to &quot;内存区域&quot;">&ZeroWidthSpace;</a></h2>
<p>局部变量、静态局部变量、全局变量、全局静态变量、字符串常量以及动态申请的内存区</p>
<ol>
<li>局部变量存储在栈中</li>
<li>全局变量、静态变量（全局和局部静态变量）存储在静态存储区</li>
<li>new申请的内存是在堆中</li>
<li>字符串常量也是存储在静态存储区</li>
</ol>
<ul>
<li><strong>栈</strong>中的变量内存会随着定义所在区间的结束自动释放；而对于堆，需要手动free，否则它就一直存在，直到程序结束；</li>
<li>对于<strong>静态存储区</strong>，其中的变量常量在程序运行期间会一直存在，不会释放，且变量常量在其中只有一份拷贝，不会出现相同的变量和常量的不同拷贝。</li>
<li>常量必须是<strong>确定的</strong>，不能运行时申请，在编译的时候就申请好了</li>
</ul>
<h2 id="字符串常量" tabindex="-1">字符串常量 <a class="header-anchor" href="#字符串常量" aria-label="Permalink to &quot;字符串常量&quot;">&ZeroWidthSpace;</a></h2>
<div class="language-cpp vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">cpp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">char</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> *</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">c</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"hello world"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p>书上说：<code>&quot;hello world&quot;</code>这个字符串被当作常量而且被放置在此程序的内存静态区。c为一个字符型指针，若为局部变量，则存储在栈内，该指针变量里面存了个地址，该地址为字符串中第一个字母h的地址。</p>
<p>当使用<code>printf()</code>输出时，格式化时选择<code>%s</code>，会输出<code>hello world</code>，这是<code>printf()</code>遇到结尾符号<code>'\0'</code>即停止显示打印。</p>
<p>字符串<code>&quot;hello world&quot;</code>是个常量，存储在一片连续的内存中，末尾有结尾符表示字符串的结束。<br>
那一般的<code>int i=1;</code><br>
所有的字符串常量都被放在静态内存区<br>
因为字符串常量很少需要修改，放在静态内存区会提高效率</p>
<div class="language-cpp vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">cpp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">char</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> str1[] </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "abcd"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">char</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> str2[] </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "abcd"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">const</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> char</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> str3[] </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "abcd"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">const</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> char</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> str4[] </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "abcd"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">const</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> char</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> *</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">str5 </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "abcd"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">const</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> char</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> *</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">str6 </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "abcd"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">char</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> *</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">str7 </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "abcd"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">char</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> *</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">str8 </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "abcd"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">cout </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x3C;&#x3C;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> ( str1 </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">==</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> str2 ) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x3C;&#x3C;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> endl;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">cout </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x3C;&#x3C;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> ( str3 </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">==</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> str4 ) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x3C;&#x3C;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> endl;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">cout </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x3C;&#x3C;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> ( str5 </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">==</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> str6 ) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x3C;&#x3C;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> endl;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">cout </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x3C;&#x3C;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> ( str7 </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">==</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> str8 ) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x3C;&#x3C;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> endl;</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br></div></div><p>结果是：<code>0 0 1 1</code><br>
str1,str2,str3,str4是数组变量，它们有各自的内存空间；字符数组作为局部变量被存储在栈区；<br>
而str5,str6,str7,str8是指针，它们指向相同的常量区域。<code>&quot;abcd&quot;</code>被存储在静态数据区，而且是全局的，</p>
<p>问题的引入：<br>
看看下面的程序的输出：</p>
<div class="language-cpp vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">cpp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">#include</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> &#x3C;stdio.h></span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">char</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> *</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">returnStr</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(){</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    char</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> *</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">p</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"hello world!"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> p;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">int</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> main</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(){</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    char</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> *</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">str</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">NULL</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//一定要初始化，好习惯</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    str</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">returnStr</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    printf</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%s\n</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, str);</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br></div></div><p>这个没有任何问题，因为<code>&quot;hello world!&quot;</code>是一个字符串常量，存放在静态数据区，把该字符串常量存放的静态数据区的首地址赋值给了指针，所以<code>returnStr</code>函数退出时，该该字符串常量所在内存不会被回收，故能够通过指针顺利无误的访问。<br>
但是，下面的就有问题：</p>
<div class="language-cpp vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">cpp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">#include</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> &#x3C;stdio.h></span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">char</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> *</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">returnStr</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(){</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    char</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> p[]</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"hello world!"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> p;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">int</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> main</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(){</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    char</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> *</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">str</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">NULL</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//一定要初始化，好习惯</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    str</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">returnStr</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    printf</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%s\n</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, str);</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br></div></div><p><code>&quot;hello world!&quot;</code>是一个字符串常量，存放在静态数据区，没错，<br>
但是<mark>把一个字符串常量赋值给了一个局部变量(char []型数组)，该局部变量存放在栈中</mark>，<br>
这样就有<mark>两块内容一样的内存</mark>，也就是说<code>char p[]=&quot;hello world!&quot;;</code>这条语句让<code>&quot;hello world!&quot;</code>这个字符串在内存中有两份拷贝，一份在动态分配的栈中，另一份在静态存储区。这是与前者最本质的区别，<br>
当<code>returnStr()</code>函数退出时，栈要清空，局部变量的内存也被清空了，<br>
所以这时的函数返回的是一个已被释放的内存地址，所以打印出来的是乱码。</p>
<p>如果函数的返回值非要是一个局部变量的地址，那么该局部变量一定要申明为static类型。如下：<br>
static 主要是为了限定范围用的。</p>
<div class="language-cpp vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">cpp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">#include</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> &#x3C;stdio.h></span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">char</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> *</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">returnStr</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(){</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    static</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> char</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> p[]</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"hello world!"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> p;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">int</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> main</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(){</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    char</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> *</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">str</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">NULL</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    str</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">returnStr</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    printf</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%s\n</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, str);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br></div></div><p>这个问题可以通过下面的一个例子来更好的说明：</p>
<div class="language-cpp vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">cpp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">#include</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> &#x3C;stdio.h></span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//返回的是局部变量的地址，该地址位于动态数据区，栈里</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">char</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> *</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">s1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(){</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    char*</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> p1 </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "qqq"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//为了测试‘char p[]="Hello world!"’中的字符串在静态存储区是否也有一份拷贝</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    char</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> p[]</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Hello world!"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    char*</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> p2 </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "w"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//为了测试‘char p[]="Hello world!"’中的字符串在静态存储区是否也有一份拷贝</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    printf</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"in s1 p=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%p\n</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, p);</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    printf</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"in s1 p1=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%p\n</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, p1);</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    printf</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"in s1: string's address: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%p\n</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x26;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Hello world!"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">));</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    printf</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"in s1 p2=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%p\n</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, p2);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> p;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//返回的是字符串常量的地址，该地址位于静态数据区</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">char</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> *</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">s2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(){</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    char</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> *</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">q</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Hello world!"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    printf</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"in s2 q=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%p\n</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, q);</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    printf</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"in s2: string's address: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%p\n</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x26;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Hello world!"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">));</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> q;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//返回的是静态局部变量的地址，该地址位于静态数据区</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">char</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> *</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">s3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(){</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    static</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> char</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> r[]</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Hello world!"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    printf</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"in s3 r=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%p\n</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, r);</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    printf</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"in s3: string's address: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%p\n</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x26;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Hello world!"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">));</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> r;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">int</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> main</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(){</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    char</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> *</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">t1, </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">t2, </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">t3;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    t1</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">s1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    t2</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">s2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    t3</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">s3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    printf</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"in main:"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    printf</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"p=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%p</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">, q=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%p</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">, r=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%p\n</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, t1, t2, t3);</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    printf</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%s\n</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, t1);</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    printf</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%s\n</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, t2);</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    printf</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%s\n</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, t3);</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br><span class="line-number">50</span><br><span class="line-number">51</span><br><span class="line-number">52</span><br><span class="line-number">53</span><br><span class="line-number">54</span><br></div></div><p>结果</p>
<div class="language-cpp vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">cpp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">in s1 p</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=0</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">013</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">FF0C</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">in s1 p1</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">00431084</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">in s1: string</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'s address: 00431074</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">in s1 p2=00431070</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">in s2 q=00431074</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">in s2: string'</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">s</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> address: </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">0</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0431074</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">in s3 r</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=0</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0434</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">DC0</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">in s3: string</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'s address: 00431074</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">in main:p=0013FF0C, q=00431074, r=00434DC0</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">$</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">Hello world!</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">Hello world!</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br></div></div><p>这个结果正好应证了上面解释，同时，还可是得出一个结论：<br>
字符串常量，之所以称之为常量，因为它可一看作是一个没有命名的字符串且为常量，存放在静态数据区。<br>
这里说的静态数据区，是相对于堆、栈等动态数据区而言的。<br>
静态数据区存放的是全局变量和静态变量，从这一点上来说，字符串常量又可以称之为一个无名的静态变量，<br>
因为<code>&quot;Hello world!&quot;</code>这个字符串在函数 s1和s2 中都引用了，但在内存中却只有一份拷贝，这与静态变量性质相当神似。</p>
<p>另外还有个实验：</p>
<div class="language-cpp vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">cpp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">#include</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> &#x3C;stdio.h></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">#include</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> &#x3C;stdlib.h></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">#include</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> &#x3C;math.h></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">int</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> main</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">() </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{ </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    char</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> *</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">b; </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    char</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> *</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">c; </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    char</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> a[]</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"hello world"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    b</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"hello world"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    c</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"hello world"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    printf</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%d</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%d</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%d</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%d\n</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,b,a,c,</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x26;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"hello world"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)); </span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br></div></div><p>实验结果为：</p>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>4282272,1244988,4282272,4282272</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p>对了，字符常量<code>'a'</code><br>
<code>sizeof('a')=1</code>，即字符‘a’在内存中占用一个字节Byte。</p>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[类型转换和缩减]]></title>
            <link>http://ooowl.fun/blogs/Book/C-primer-plus/%E7%AC%AC%E4%B8%89%E7%AB%A0-%E6%95%B0%E6%8D%AE%E5%92%8CC/%E7%B1%BB%E5%9E%8B%E8%BD%AC%E6%8D%A2%E5%92%8C%E7%BC%A9%E5%87%8F.html</link>
            <guid isPermaLink="false">http://ooowl.fun/blogs/Book/C-primer-plus/%E7%AC%AC%E4%B8%89%E7%AB%A0-%E6%95%B0%E6%8D%AE%E5%92%8CC/%E7%B1%BB%E5%9E%8B%E8%BD%AC%E6%8D%A2%E5%92%8C%E7%BC%A9%E5%87%8F.html</guid>
            <pubDate>Mon, 18 Apr 2022 10:51:30 GMT</pubDate>
            <description><![CDATA[要扩展的短数据类型为有符号数的 进行符号扩展，即短数据类型的符号位填充到长数据类型的高字节位（即比短数据类型多出的那一部分），保证扩展后的数值大小不变]]></description>
            <content:encoded><![CDATA[<h1 id="类型转换和缩减" tabindex="-1">类型转换和缩减 <a class="header-anchor" href="#类型转换和缩减" aria-label="Permalink to &quot;类型转换和缩减&quot;">&ZeroWidthSpace;</a></h1><p class="article-meta">创建于 2022年4月18日 18:51:30 · 约1,842字</p>
<h2 id="转换的三种情况" tabindex="-1">转换的三种情况 <a class="header-anchor" href="#转换的三种情况" aria-label="Permalink to &quot;转换的三种情况&quot;">&ZeroWidthSpace;</a></h2>
<h3 id="一、短数据类型扩展为长数据类型" tabindex="-1">一、短数据类型扩展为长数据类型 <a class="header-anchor" href="#一、短数据类型扩展为长数据类型" aria-label="Permalink to &quot;一、短数据类型扩展为长数据类型&quot;">&ZeroWidthSpace;</a></h3>
<ol>
<li>
<p>要扩展的短数据类型为有符号数的  进行符号扩展，即短数据类型的符号位填充到长数据类型的高字节位（即比短数据类型多出的那一部分），保证扩展后的数值大小不变</p>
<ul>
<li><code>char x=10001001b;   short y=x;  则y的值应为11111111 10001001b；</code></li>
<li><code>char x=00001001b;   short y=x;  则y的值应为00000000 00001001b；</code></li>
</ul>
</li>
<li>
<p>要扩展的短数据类型为无符号数的 进行零扩展，即用零来填充长数据类型的高字节位</p>
<ul>
<li><code>unsigned char x=10001001b;   short y=x;  则y的值应为00000000 10001001b；</code></li>
<li><code>unsigned char x=00001001b;   short y=x;  则y的值应为00000000 00001001b；</code></li>
</ul>
</li>
</ol>
<h3 id="二、长数据类型缩减为短数据类型" tabindex="-1">二、长数据类型缩减为短数据类型 <a class="header-anchor" href="#二、长数据类型缩减为短数据类型" aria-label="Permalink to &quot;二、长数据类型缩减为短数据类型&quot;">&ZeroWidthSpace;</a></h3>
<p>如果长数据类型的高字节全为1或全为0，则会直接截取低字节赋给短数据类型；</p>
<p>如果长数据类型的高字节不全为1或不全为0，则转会就会发生错误。</p>
<h3 id="三、同长度的数据类型中有符号数与无符号数的相互转化" tabindex="-1">三、同长度的数据类型中有符号数与无符号数的相互转化 <a class="header-anchor" href="#三、同长度的数据类型中有符号数与无符号数的相互转化" aria-label="Permalink to &quot;三、同长度的数据类型中有符号数与无符号数的相互转化&quot;">&ZeroWidthSpace;</a></h3>
<p>直接将内存中的数据赋给要转化的类型，数值大小则会发生变化。</p>
<p>短类型扩展为长类型时，但短类型与长类型分属有符号数与无符号数时，则先按规则一进行类型的扩展，再按本规则直接将内存中的数值原封不动的赋给对方。</p>
<h2 id="转换表" tabindex="-1">转换表 <a class="header-anchor" href="#转换表" aria-label="Permalink to &quot;转换表&quot;">&ZeroWidthSpace;</a></h2>
<table tabindex="0">
<thead>
<tr>
<th>有符号数的转换</th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td>从</td>
<td>到</td>
<td>方法</td>
</tr>
<tr>
<td>char</td>
<td>short</td>
<td>符号位扩展</td>
</tr>
<tr>
<td>char</td>
<td>long</td>
<td>符号位扩展</td>
</tr>
<tr>
<td>char</td>
<td>unsigned char</td>
<td>最高位失去符号位意义，变为数据位</td>
</tr>
<tr>
<td>char</td>
<td>unsigned short</td>
<td>符号位扩展到short;然后从short转到 unsigned short</td>
</tr>
<tr>
<td>char</td>
<td>unsigned long</td>
<td>符号位扩展到long; 然后从long 转到unsigned long</td>
</tr>
<tr>
<td>char</td>
<td>float</td>
<td>符号位扩展到long; 然后从long 转到float</td>
</tr>
<tr>
<td>char</td>
<td>double</td>
<td>符号位扩展到long; 然后从long 转到double</td>
</tr>
<tr>
<td>char</td>
<td>long double</td>
<td>符号位扩展到long; 然后从long 转到long double</td>
</tr>
<tr>
<td>short</td>
<td>char</td>
<td>保留低位字节</td>
</tr>
<tr>
<td>short</td>
<td>long</td>
<td>符号位扩展</td>
</tr>
<tr>
<td>short</td>
<td>unsigned char</td>
<td>保留低位字节</td>
</tr>
<tr>
<td>short</td>
<td>unsigned short</td>
<td>最高位失去符号位意义，变为数据位</td>
</tr>
<tr>
<td>short</td>
<td>unsigned long</td>
<td>符号位扩展到long; 然后从long转到unsigned double</td>
</tr>
<tr>
<td>short</td>
<td>float</td>
<td>符号位扩展到long; 然后从long 转到float</td>
</tr>
<tr>
<td>short</td>
<td>double</td>
<td>符号位扩展到long; 然后从long 转到double</td>
</tr>
<tr>
<td>short</td>
<td>long double</td>
<td>符号位扩展到long; 然后从long 转到double</td>
</tr>
<tr>
<td>long</td>
<td>char</td>
<td>保留低位字节</td>
</tr>
<tr>
<td>long</td>
<td>short</td>
<td>保留低位字节</td>
</tr>
<tr>
<td>long</td>
<td>unsigned char</td>
<td>保留低位字节</td>
</tr>
<tr>
<td>long</td>
<td>unsigned short</td>
<td>保留低位字节</td>
</tr>
<tr>
<td>long</td>
<td>unsigned long</td>
<td>最高位失去符号位意义，变为数据位</td>
</tr>
<tr>
<td>long</td>
<td>Float</td>
<td>使用单精度浮点数表示。可能丢失精度。</td>
</tr>
<tr>
<td>long</td>
<td>double</td>
<td>使用双精度浮点数表示。可能丢失精度。</td>
</tr>
<tr>
<td>long</td>
<td>long double</td>
<td>使用双精度浮点数表示。可能丢失精度。</td>
</tr>
</tbody>
</table>
<table tabindex="0">
<thead>
<tr>
<th>无符号数的转换</th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td>从</td>
<td>到</td>
<td>方法</td>
</tr>
<tr>
<td>unsigned char</td>
<td>char</td>
<td>最高位作为符号位</td>
</tr>
<tr>
<td>unsigned char</td>
<td>short</td>
<td>0扩展</td>
</tr>
<tr>
<td>unsigned char</td>
<td>long</td>
<td>0扩展</td>
</tr>
<tr>
<td>unsigned char</td>
<td>unsigned short</td>
<td>0扩展</td>
</tr>
<tr>
<td>unsigned char</td>
<td>unsigned long</td>
<td>0扩展</td>
</tr>
<tr>
<td>unsigned char</td>
<td>float</td>
<td>转换到long; 再从 long 转换到float</td>
</tr>
<tr>
<td>unsigned char</td>
<td>double</td>
<td>转换到long; 再从 long 转换到double</td>
</tr>
<tr>
<td>unsigned char</td>
<td>long double</td>
<td>转换到long; 再从 long 转换到double</td>
</tr>
<tr>
<td>unsigned short</td>
<td>char</td>
<td>保留低位字节</td>
</tr>
<tr>
<td>unsigned short</td>
<td>short</td>
<td>最高位作为符号位</td>
</tr>
<tr>
<td>unsigned short</td>
<td>long</td>
<td>0扩展</td>
</tr>
<tr>
<td>unsigned short</td>
<td>unsigned char</td>
<td>保留低位字节</td>
</tr>
<tr>
<td>unsigned short</td>
<td>unsigned long</td>
<td>0扩展</td>
</tr>
<tr>
<td>unsigned short</td>
<td>float</td>
<td>转换到long; 再从 long 转换到float</td>
</tr>
<tr>
<td>unsigned short</td>
<td>double</td>
<td>转换到long; 再从 long 转换到double</td>
</tr>
<tr>
<td>unsigned short</td>
<td>long double</td>
<td>转换到long; 再从 long 转换到double</td>
</tr>
<tr>
<td>unsigned long</td>
<td>char</td>
<td>保留低位字节</td>
</tr>
<tr>
<td>unsigned long</td>
<td>short</td>
<td>保留低位字节</td>
</tr>
<tr>
<td>unsigned long</td>
<td>long</td>
<td>最高位作为符号位</td>
</tr>
<tr>
<td>unsigned long</td>
<td>unsigned char</td>
<td>保留低位字节</td>
</tr>
<tr>
<td>unsigned long</td>
<td>unsigned short</td>
<td>保留低位字节</td>
</tr>
<tr>
<td>unsigned long</td>
<td>float</td>
<td>转换到long; 再从 long 转换到float</td>
</tr>
<tr>
<td>unsigned long</td>
<td>double</td>
<td>Convert directly to double</td>
</tr>
<tr>
<td>unsigned long</td>
<td>long double</td>
<td>转换到long; 再从 long 转换到double</td>
</tr>
</tbody>
</table>
<h2 id="深奥" tabindex="-1">深奥 <a class="header-anchor" href="#深奥" aria-label="Permalink to &quot;深奥&quot;">&ZeroWidthSpace;</a></h2>
<p>进制补码系统中，同一个负数在不同大小的表示法中的表示是不同的。你不能在一个包含16位数的表达式中随意地使用8位有符号数，转换是必需的。这种转换，以及其逆操作（将16位数转换为8位）就是符号扩展（sign extension）与缩减（contraction）操作。</p>
<p>个数从某个位数符号扩展到一个更大的位数很简单，只需要将符号位复制到新格式新增的高端各位即可</p>
<p>例如，为了将一个8位的数符号扩展到16位，只需将8位数的第7位复制到16位数的第8 .. 15位即可。而将一个16位数符号扩展到一个双字，只需要将第15位复制到双字的第16 .. 31位即可。</p>
<p>处理不同长度有符号数的时候，必须使用符号扩展。例如，在将一个字节量与一个字量相加的时候，在相加之前必须将字节量符号扩展到16位。其他运算可能又会需要符号扩展到32位。</p>
<p>处理无符号二进制数的时候，可以使用零扩展（zero extension）来将小位数的无符号数扩展到大位数的无符号数。零扩展非常简单——只需要用零来填充大位数操作数的高端各个字节即可。大多数高级语言编译器会自动处理符号扩展与零扩展、</p>
<p>语言（例如Ada）在从小数据类型转换到大数据类型时需要显式转换（explicit cast）。查一下所用语言的参考手册就知道这种显式转换是不是必需的了。要求提供显式转换的语言的优点在于编译器永远不会在程序员不知情的情况下做任何事情。如果你没有提供必要的转换，编译器会给出一个诊断消息，让你知道程序还需要改进。</p>
<p>符号扩展和零扩展，有一点需要明确的是，它们是需要付出代价的。将一个小整型赋值给一个大整型可能会比在同样大小的整型变量间传输数据需要更多的机器指令（执行时间更长）。因此，在一个数学表达式或者一条赋值语句中混合使用不同大小的变量要小心。</p>
<p>符号缩减，即将一个某位数转换为值相同但位数变小的数，比较麻烦。符号扩展永远不会失败，使用符号扩展，一个m位有符号数永远可以转换为一个n位数（这里n&gt;m）。不幸的是，在m&lt;n的情况下，一个n位数不是总能转换为m位数。例如，-448的16位十六进制表示是$FE40，而这个数的大小对于8位来说太大了，我们无法将其符号缩减到8位。</p>
<p>将一个数值正确地符号缩减，必须要检查需要丢弃的高端字节。首先，这些高端字节必须是全零或者$FF，如果它们包含其他值，我们就无法对这个数进行符号缩减。其次，最终结果的最高位必须与被丢弃的所有位一致。</p>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[零散知识点]]></title>
            <link>http://ooowl.fun/blogs/Book/C-primer-plus/%E7%AC%AC%E4%B8%89%E7%AB%A0-%E6%95%B0%E6%8D%AE%E5%92%8CC/%E9%9B%B6%E6%95%A3%E7%9F%A5%E8%AF%86%E7%82%B9.html</link>
            <guid isPermaLink="false">http://ooowl.fun/blogs/Book/C-primer-plus/%E7%AC%AC%E4%B8%89%E7%AB%A0-%E6%95%B0%E6%8D%AE%E5%92%8CC/%E9%9B%B6%E6%95%A3%E7%9F%A5%E8%AF%86%E7%82%B9.html</guid>
            <pubDate>Mon, 18 Apr 2022 05:49:13 GMT</pubDate>
            <description><![CDATA[最近在看深入理解计算机系统这本书，上面提到了在32位机器和64机器中int类型都占用4个字节。 后来，查了The C Programming language这本书，里面有一句话是这样的：Each compiler is free to choose appropriate sizes for its own hardware, subject only to the restriction that shorts and ints are at least 16bits, longs are at least 32bits, and short is no longer than int, which is no longer than long.]]></description>
            <content:encoded><![CDATA[<h1 id="零散知识点" tabindex="-1">零散知识点 <a class="header-anchor" href="#零散知识点" aria-label="Permalink to &quot;零散知识点&quot;">&ZeroWidthSpace;</a></h1><p class="article-meta">创建于 2022年4月18日 13:49:13 · 约1,864字</p>
<h2 id="int占几位" tabindex="-1">int占几位? <a class="header-anchor" href="#int占几位" aria-label="Permalink to &quot;int占几位?&quot;">&ZeroWidthSpace;</a></h2>
<p>最近在看深入理解计算机系统这本书，上面提到了在32位机器和64机器中int类型都占用4个字节。<br>
后来，查了The C Programming language这本书，里面有一句话是这样的：Each compiler is free to choose appropriate sizes for its own hardware, subject only to the restriction that shorts and ints are at least 16bits, longs are at least 32bits, and short is no longer than int, which is no longer than long.</p>
<p>意思大致是编译器可以根据自身硬件来选择合适的大小，但是需要满足约束：short和int型至少为16位，long型至少为32位，并且short型长度不能超过int型，而int型不能超过long型。</p>
<p>这即是说各个类型的变量长度是由编译器来决定的，而当前主流的编译器中一般是32位机器和64位机器中int型都是4个字节（例如，GCC）。<br>
下面列举在GCC编译器下32位机器和64位机器各个类型变量所占字节数：</p>
<table tabindex="0">
<thead>
<tr>
<th>C类型</th>
<th>32bit</th>
<th>64bit</th>
</tr>
</thead>
<tbody>
<tr>
<td>char</td>
<td>1</td>
<td>1</td>
</tr>
<tr>
<td>short int</td>
<td>2</td>
<td>2</td>
</tr>
<tr>
<td>int</td>
<td>4</td>
<td>4</td>
</tr>
<tr>
<td>long int</td>
<td>4</td>
<td>8</td>
</tr>
<tr>
<td>long long int</td>
<td>8</td>
<td>8</td>
</tr>
<tr>
<td>char*</td>
<td>4</td>
<td>8</td>
</tr>
<tr>
<td>float</td>
<td>4</td>
<td>4</td>
</tr>
<tr>
<td>double</td>
<td>8</td>
<td>8</td>
</tr>
<tr>
<td>需要说明一下的是指针类型存储的是所指向变量的地址，所以32位机器只需要32bit，而64位机器需要64bit。</td>
<td></td>
<td></td>
</tr>
<tr>
<td>经过询问，网上查找以及测试，发现 数据类型占内存的位数实际上<strong>与操作系统的位数和编译器（不同编译器支持的位数可能有所不同）都有关</strong> ，具体某种数据类型占字节数得编译器根据操作系统位数两者之间<strong>进行协调</strong>好后分配内存大小。</td>
<td></td>
<td></td>
</tr>
<tr>
<td><mark>在使用的时候如想知道具体占内存的位数通过sizeof(int)可以得到准确的答案</mark>。</td>
<td></td>
<td></td>
</tr>
<tr>
<td>稍微整理一下64位常用的，<a href="https://docs.microsoft.com/zh-cn/cpp/cpp/data-type-ranges?view=msvc-170" target="_blank" rel="noreferrer">微软这里</a>很全</td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
<table tabindex="0">
<thead>
<tr>
<th>数据类型</th>
<th>字节</th>
<th>取值范围</th>
</tr>
</thead>
<tbody>
<tr>
<td>char</td>
<td>1</td>
<td>-128～127</td>
</tr>
<tr>
<td>usigned char</td>
<td>1</td>
<td>0～255(2^9-1=255)</td>
</tr>
<tr>
<td>short</td>
<td>2</td>
<td>-32768～32767</td>
</tr>
<tr>
<td>usigned short</td>
<td>2</td>
<td>0～65535(2^17-1=65535)</td>
</tr>
<tr>
<td>int</td>
<td>4</td>
<td>-2147483648～2147483647</td>
</tr>
<tr>
<td>unsigned int</td>
<td>4</td>
<td>0~4294967295(2^33-1=4294967295)</td>
</tr>
<tr>
<td>long</td>
<td>4</td>
<td>-2147483648～2147483647</td>
</tr>
<tr>
<td>usigned long</td>
<td>4</td>
<td>0~4294967295</td>
</tr>
<tr>
<td>long long</td>
<td>8</td>
<td>-9223372036854775808～<br/>9223372036854775807</td>
</tr>
<tr>
<td>usigned long long</td>
<td>8</td>
<td>0～18,446,744,073,709,551,615</td>
</tr>
<tr>
<td>float</td>
<td>4</td>
<td>1.17549 *10^-38～ 3.40282*10^38</td>
</tr>
<tr>
<td>double</td>
<td>8</td>
<td>2.22507 *10^-308～1.79769*10^308</td>
</tr>
<tr>
<td>long double</td>
<td>12</td>
<td>2.22507 *10^-308～1.79769*10^308</td>
</tr>
</tbody>
</table>
<p>n位无符号数分配的时候 min全0=0~max全1=(2^n+1)-1<br>
n位有符号数分配的时候，min -全1=-(2^n-1)-1~max +全1=(2^n-1)<br>
考虑一下空间的分配，分三部分 先拿出一个符号位，n位这时候bit少了一位n-1 即 min -全1=-(2^n-1)~max +全1=(2^n-1)
注意此时0处正0仍然为0(0000)，没有负0(1000)，负0的空间实际上被分配给了负数，-全1时正好可以表示多一位-(2^n-1)+1<br>
但是这样负数的表示非常奇怪，往后移了一位<br>
计算机是用补码存储有符号数据的，其中正数的补码是该数的二进制形式，而负数的补码需要通过以下几步获得：</p>
<ol>
<li>先取绝对值的二进制形式，符号位置为1；</li>
<li>符号位不变，按位取反；</li>
<li>最后将获得值加1。</li>
</ol>
<p>这时候再回来看怎么分配的，-1 的补码是 11111111，这个数据正好对应着无符号数中的 65535，这样-1就占据了-0，-65535占据了-1的空间，-2开始就正常了。</p>
<h2 id="探究byte的定义" tabindex="-1">探究Byte的定义 <a class="header-anchor" href="#探究byte的定义" aria-label="Permalink to &quot;探究Byte的定义&quot;">&ZeroWidthSpace;</a></h2>
<p>再探究一下Byte的定义：能够编码一个字符的最小可寻址单元：</p>
<blockquote>
<p>Historically, the byte was the number of bits used to encode a single <a href="https://link.zhihu.com/?target=http%3A//en.wikipedia.org/wiki/Character_%28computing%29" target="_blank" rel="noreferrer">character</a> of text in a computer <a href="https://link.zhihu.com/?target=http%3A//en.wikipedia.org/wiki/Byte%23cite_note-Bemer1962-1" target="_blank" rel="noreferrer">1</a><br/><a href="https://link.zhihu.com/?target=http%3A//en.wikipedia.org/wiki/Byte%23cite_note-2" target="_blank" rel="noreferrer">2</a> and for this reason it is the smallest <a href="https://link.zhihu.com/?target=http%3A//en.wikipedia.org/wiki/Address_space" target="_blank" rel="noreferrer">addressable</a> unit of <a href="https://link.zhihu.com/?target=http%3A//en.wikipedia.org/wiki/Memory" target="_blank" rel="noreferrer">memory</a> in any <a href="https://link.zhihu.com/?target=http%3A//en.wikipedia.org/wiki/Computer_architecture" target="_blank" rel="noreferrer">computer architectures</a>.<br>
<a href="https://en.wikipedia.org/wiki/Byte" target="_blank" rel="noreferrer">https://en.wikipedia.org/wiki/Byte</a></p>
</blockquote>
<p>其实以前也有过4位，6位或7位为一byte的标准，IBM 701（36位字长，18位byte）、<a href="https://www.zhihu.com/search?q=IBM+702&amp;search_source=Entity&amp;hybrid_search_source=Entity&amp;hybrid_search_extra=%7B%22sourceType%22%3A%22answer%22%2C%22sourceId%22%3A27391534%7D" target="_blank" rel="noreferrer">IBM 702</a>（7位字长，7位byte）、<a href="https://www.zhihu.com/search?q=CDC+6600&amp;search_source=Entity&amp;hybrid_search_source=Entity&amp;hybrid_search_extra=%7B%22sourceType%22%3A%22answer%22%2C%22sourceId%22%3A27391534%7D" target="_blank" rel="noreferrer">CDC 6600</a>（60位字长，12位byte）等等。但是我觉得，考虑到包含的信息量不够大（所以4位被弃用了），还有不够整齐美观（即不方便扩展，不适合整齐划一进行工业生产；想象一下假如以7位为一byte，内存和硬盘的大小就不再是2^n bit大小了，而是2^(n-1)*7 bit大小了，有些别扭），所以只有8位作为最通行的标准流行开来。</p>
<p>8位一Byte，字长为2^n bits，这个标准来自于IBM system/360（1950年代到1960年代）。IBM也参与了ASCII码（7位128个字符）的制定（1963），但是同时开展了EBCDIC表（8位256个字符）的制定，作为自己公司的BCDIC标准的一个升级版本，其实就是想与ASCII竞争，但这个表的确很乱，而且版本也不统一，造成了很多吐槽（比如字母表居然不连续，加入了很多用不到的字符等等）这个标准非常坑爹，但是却推广了8 bit为一字节的概念通行开来。</p>
<p>接下来AT&amp;T(American Telephone and Telegraph Company)公司和8位处理器的兴起进一步推广了8位作为一个byte这一事实标准。由于ASCII码只有7位，出于表达英语字母及其他符号的必要，各个国家开始探索如何用多余的一位来表示其他的字符，这样就出现了很多“扩展ASCII字符集”，但是标准不一。IBM也推出了一个，叫做<a href="https://en.wikipedia.org/wiki/Code_page_437" target="_blank" rel="noreferrer">Code page 437</a>。这个表也是MS-DOS所用的扩展ASCII码集，但是并不是最后的唯一标准。 <mark>直到1985年，是<a href="https://zh.wikipedia.org/wiki/%E5%9C%8B%E9%9A%9B%E6%A8%99%E6%BA%96%E5%8C%96%E7%B5%84%E7%B9%94" target="_blank" rel="noreferrer">国际标准化组织</a> （ISO）及<a href="https://zh.wikipedia.org/wiki/%E5%9B%BD%E9%99%85%E7%94%B5%E5%B7%A5%E5%A7%94%E5%91%98%E4%BC%9A" target="_blank" rel="noreferrer">国际电工委员会</a>（IEC）才联合制定的一系列8<a href="https://zh.wikipedia.org/wiki/%E6%95%B8%E7%A2%BC%E8%B3%87%E6%96%99" target="_blank" rel="noreferrer">位</a>字符集的标准，称为ISO 8859，全称ISO/IEC 8859，这才统一了混乱的标准。</mark></p>
<p>说了这么多，只想表明一点：一个字节之所以有8个bit，是历史原因造成的（计算机前身是打印机），但是也是计算机原理，尤其是二进制特性的必然结果，是数据存储需要（必须要能在一个字节内表示超过100种状态，包括常用数字，大小写字母，和打印机上的其他控制符号）和早期计算机存储价格昂贵（所以没有用10个，16个或更多位），加上商业利益追求（IBM的推广）共同作用的结果。</p>
<h2 id="char-的长度" tabindex="-1">char 的长度 <a class="header-anchor" href="#char-的长度" aria-label="Permalink to &quot;char 的长度&quot;">&ZeroWidthSpace;</a></h2>
<p><a href="https://akaedu.github.io/book/apas03.html" target="_blank" rel="noreferrer">在Linux C编程中使用Unicode和UTF-8</a>
但是在printf里直接打印中文字符串就可以</p>
<h2 id="epsilon的含义" tabindex="-1">EPSILON的含义 <a class="header-anchor" href="#epsilon的含义" aria-label="Permalink to &quot;EPSILON的含义&quot;">&ZeroWidthSpace;</a></h2>
<p>有时候计算机判断(1.0 == 10.0 / 10.0)的时候，并不总是返回true。因为浮点数计算可能会产生一定点误差，而这误差是无法避免的。正确的做法是判断两个值是否在这个误差范围内，而误差范围就是从正FLT_EPSILON 到负FLT_EPSILON 内。（1.0 &gt; (10.0 / 10.0) - FLT_EPSILON &amp;&amp; 1.0 &lt; (10.0 / 10.0) + FLT_EPSILON）。双精度为DBL_EPSILON</p>
<p>FLT_EPSILON 在 float.h 头文件 宏定义如下</p>
<p>后面的注释可以理解为 这个数是 能使 (1.0 + FLT_EPSILON != 0) 成立的最小的数
也就是说 小于FLT_EPSILON 的数 加上 1.0 都等于 1.0
<a href="https://blog.csdn.net/l773575310/article/details/52791392" target="_blank" rel="noreferrer">https://blog.csdn.net/l773575310/article/details/52791392</a>  //TODO</p>
<p><a href="https://queue.acm.org/detail.cfm?id=2010365" target="_blank" rel="noreferrer">The Most Expensive One-byte Mistake - ACM Queue</a>
最贵的1Byte错误我</p>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[第三章 数据和C]]></title>
            <link>http://ooowl.fun/blogs/Book/C-primer-plus/%E7%AC%AC%E4%B8%89%E7%AB%A0-%E6%95%B0%E6%8D%AE%E5%92%8CC/README.html</link>
            <guid isPermaLink="false">http://ooowl.fun/blogs/Book/C-primer-plus/%E7%AC%AC%E4%B8%89%E7%AB%A0-%E6%95%B0%E6%8D%AE%E5%92%8CC/README.html</guid>
            <pubDate>Mon, 18 Apr 2022 05:49:03 GMT</pubDate>
            <content:encoded><![CDATA[<h1 id="第三章-数据和c" tabindex="-1">第三章 数据和C <a class="header-anchor" href="#第三章-数据和c" aria-label="Permalink to &quot;第三章 数据和C&quot;">&ZeroWidthSpace;</a></h1><p class="article-meta">创建于 2022年4月18日 13:49:03 · 约0字</p>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[第二章 C语言概述]]></title>
            <link>http://ooowl.fun/blogs/Book/C-primer-plus/%E7%AC%AC%E4%BA%8C%E7%AB%A0-C%E8%AF%AD%E8%A8%80%E6%A6%82%E8%BF%B0.html</link>
            <guid isPermaLink="false">http://ooowl.fun/blogs/Book/C-primer-plus/%E7%AC%AC%E4%BA%8C%E7%AB%A0-C%E8%AF%AD%E8%A8%80%E6%A6%82%E8%BF%B0.html</guid>
            <pubDate>Sat, 16 Apr 2022 16:24:00 GMT</pubDate>
            <content:encoded><![CDATA[<h1 id="第二章-c语言概述" tabindex="-1">第二章 C语言概述 <a class="header-anchor" href="#第二章-c语言概述" aria-label="Permalink to &quot;第二章 C语言概述&quot;">&ZeroWidthSpace;</a></h1><p class="article-meta">创建于 2022年4月17日 00:24:00 · 约0字</p>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Obsidian博客搭建]]></title>
            <link>http://ooowl.fun/about/Obsidian%E5%8D%9A%E5%AE%A2%E6%90%AD%E5%BB%BA.html</link>
            <guid isPermaLink="false">http://ooowl.fun/about/Obsidian%E5%8D%9A%E5%AE%A2%E6%90%AD%E5%BB%BA.html</guid>
            <pubDate>Sat, 16 Apr 2022 13:46:00 GMT</pubDate>
            <description><![CDATA[这个库是用来写技术笔记和搞个人知识库的，为避免忘记以及分享后其他人能看懂，记录 库会的blog会被vuepress渲染，所以在满足需求的情况下尽量使用兼容的Markdown+插件的语法 上一个博客因为各种原因，废弃了，一开始是因为写得多了之后太过于庞杂，没有后台管理导致内容和组织越来越混乱，一边写一边思考解决方法，最后发现了Obsidian简直是理想中的模式，遂直接重开，用Obsidian写笔记，寻找最大兼容的语法，直接放进博客渲染。]]></description>
            <content:encoded><![CDATA[<h1 id="obsidian博客搭建" tabindex="-1">Obsidian博客搭建 <a class="header-anchor" href="#obsidian博客搭建" aria-label="Permalink to &quot;Obsidian博客搭建&quot;">&ZeroWidthSpace;</a></h1><p class="article-meta">创建于 2022年4月16日 21:46:00 · 约1,934字</p>
<h2 id="库的目的" tabindex="-1">库的目的 <a class="header-anchor" href="#库的目的" aria-label="Permalink to &quot;库的目的&quot;">&ZeroWidthSpace;</a></h2>
<p>这个库是用来写技术笔记和搞个人知识库的，为避免忘记以及分享后其他人能看懂，记录<br>
库会的blog会被vuepress渲染，所以在满足需求的情况下尽量使用兼容的Markdown+插件的语法<br>
上一个博客因为各种原因，废弃了，一开始是因为写得多了之后太过于庞杂，没有后台管理导致内容和组织越来越混乱，一边写一边思考解决方法，最后发现了Obsidian简直是理想中的模式，遂直接重开，用Obsidian写笔记，寻找最大兼容的语法，直接放进博客渲染。</p>
<h3 id="库的插件" tabindex="-1">库的插件 <a class="header-anchor" href="#库的插件" aria-label="Permalink to &quot;库的插件&quot;">&ZeroWidthSpace;</a></h3>
<ul>
<li><strong>Obsidian git</strong>用来同步github和多平台
<ul>
<li>注意不要同步.obsidian文件夹，在gitignore里面配置一下就可了，有很多文件实时变更每次都冲突</li>
</ul>
</li>
<li><strong>show whitespace</strong> 显示空格 选项全打开</li>
<li><strong>show current file path</strong> 右下角显示文件路径点击可复制</li>
<li><strong>Advanced Tables</strong> 表格辅助插件
<ul>
<li>Excel to Markdown Table 可以直接从excel粘贴</li>
<li>obsidian-table-editor 还未发布从github上找的</li>
</ul>
</li>
<li><strong>Auto pair chinese symbol</strong> 中文符号自动成对</li>
<li><strong>Remember cursor position</strong> 切换文件时记住鼠标位置</li>
<li><strong>Search on Internet</strong> 搜索</li>
<li><strong>Mind Map</strong> 思维导图
<ul>
<li><strong>enhancing-mindmap</strong> 可以编辑的思维导图，兼容md语法
<ul>
<li>mindmap-plugin: basic 在formatter里面加入这一个启用</li>
</ul>
</li>
<li><strong>markmind</strong> <s>批注pdf，不能手写，其他的都可以，可以类似于marginnote3那种。</s></li>
<li>直接配合OneNote使用思维导图，不需要批注了，可开启大纲表格视图</li>
</ul>
</li>
<li><strong>Editor Syntax Highlight</strong> 代码高亮</li>
<li><strong>Natural Language Dates</strong> 按@输出日期
<ul>
<li>YYYY-MM-DD dddd 表示 年-月-日 星期</li>
</ul>
</li>
<li><strong>calendar</strong> 日历
<ul>
<li>配合日记</li>
<li>obsidian-periodic-notes 自动日报周报分类，看插件github官网怎么配置的路径</li>
<li><code>MM[月]/[第]WW[周]/YY-MM-DD[日报]</code>,<code>MM[月]/[第]WW[周]/[周报]YYYY-WW</code></li>
</ul>
</li>
<li><strong>Admonition</strong> 功能提示块 ^5925eb
<ul>
<li>语法在vuepress上可能会渲染为白色代码块可以接受</li>
<li>类型有ad-(type)
<ul>
<li><code>note</code>,<code>abstract</code>,<code>info</code>,<code>tip</code>,<code>success</code>,<code>question</code>,<code>warning</code>,<code>failure</code>,<code>danger</code>,<code>bug</code>,<code>example</code>,<code>quote</code></li>
<li><a href="https://squidfunk.github.io/mkdocs-material/reference/admonitions/#inline-blocks" target="_blank" rel="noreferrer">样式参考</a></li>
</ul>
</li>
<li>主要用的参数写在内容第一行,<code>collapse:open/none</code>,<code>title:xxx</code>，一般只用这俩就行</li>
</ul>
</li>
<li><strong>dynamic table of contents</strong> 生成大纲，暂时用不着
<ul>
<li>默认是toc代码块渲染，用脚本直接更改为双括号[[toc]] 就可以在vuepress中渲染</li>
<li>有BUG不能用行数错误，有些行无法复制,作者自己不修复，寄了，插件是个好插件</li>
</ul>
</li>
<li><strong>Sliding panes</strong> 多栏侧边划的</li>
<li><strong>Note Refactor</strong> 大文档拆分wiki链接</li>
<li><strong>Auto Link Title</strong> 粘贴链接的时候自动抓取网页的标题，填充为文字
<ul>
<li>关闭自动替换链接</li>
</ul>
</li>
<li><strong>Paste URL into Selection</strong> 链接粘贴自动标题
<ul>
<li>剪贴板链接「<a href="https://example.com/" target="_blank" rel="noreferrer">https://example.com</a>」选中一段文字「TEXT」粘贴，这个链接就会和文字结合在一起成为<br>
<code>[TEXT](https://example.com)</code></li>
</ul>
</li>
<li><strong>Obsidian-Charts</strong> 命令行输入chart 从表创建和自己创建图
<ul>
<li>在vuepress里面会简单渲染为一个不认识的代码块</li>
</ul>
</li>
<li>脚注有点用但不多
<ul>
<li><strong>Obsidian Tidy Footnotes</strong> 生成脚注<sup class="footnote-ref"><a href="#fn1" id="fnref1">[1]</a></sup>，我设置快捷键为<code>ctrl+6</code>直接在光标处插入脚注<sup class="footnote-ref"><a href="#fn2" id="fnref2">[2]</a></sup>
<ul>
<li>修改main.js,在footnoteDetail字符串添加<code>\n</code>,脚注后带俩空格，但是用的时候需要向前两下粘贴</li>
</ul>
</li>
<li><strong>Tidy Footnotes</strong> 脚注整理，命令行输入tidy，不过好像没怎么用到</li>
</ul>
</li>
<li><strong>Consistent attachments and links</strong> 转换插件
<ul>
<li>使用双链接时需要回来重新嵌入一下为文件格式以便兼容</li>
<li>设置快捷键为<code>ctrl+l</code> 把双链全转为标准md，双链都转换,但是只会在本目录下配合下面使用</li>
<li>设置快捷键为<code>ctrl+p</code> 把文件链接都转换为相对链接，双链转换完后用这个重新确定路径，多个重名时会是遍历目录的第一个</li>
<li>直接使用转换插件把所有选项全关了，留下move attachments with note和update links</li>
</ul>
</li>
<li><strong>Attachment Name Formatting</strong> 自动重命名附件
<ul>
<li>移动文档的时候提前关掉</li>
<li>默认粘贴附件和图片空格会被替换成%，vuepress无法渲染</li>
<li>进入JS<code>main.js</code> 把<code>join(&quot; &quot;)</code>替换为<code>join(&quot;-&quot;)</code> 这样就可以随便渲染了</li>
<li><s>还是没解决图片路径前面加一个<code>./</code> 的问题</s> 脚本解决了</li>
</ul>
</li>
<li><strong>dataview</strong> 最核心的插件之一，但我不会</li>
<li><strong>Tag Wrangler</strong> 标签管理没什么用，tag可以批量重命名，但是tag必须<strong>不能含有符号</strong>，可以有emoji</li>
<li><strong>Various Complements</strong> 一些自动补全 打开当前文件夹和dict，IME选项，关掉space after</li>
</ul>
<h3 id="自定义css" tabindex="-1">自定义CSS <a class="header-anchor" href="#自定义css" aria-label="Permalink to &quot;自定义CSS&quot;">&ZeroWidthSpace;</a></h3>
<p>下面有附代码，建立一个css文件他自己会读取</p>
<ol>
<li>主题使用的是Obsidian Nord</li>
<li>圆点调整，不同层级用不同的样式没有实现，但是修改之后可接受</li>
<li>添加链接的小文件图标</li>
<li>大纲连接线和文件层级连接线</li>
<li>背景图片太复杂而且还要多一个文件直接放弃，可自定义透明度</li>
<li>所使用的自定义<a href="https://1drv.ms/u/s!Ave4mfYaItDJhMdWWLsPoUdrShE2lw?e=H3snSQ" target="_blank" rel="noreferrer">CSS</a></li>
</ol>
<h4 id="obsidian" tabindex="-1">obsidian <a class="header-anchor" href="#obsidian" aria-label="Permalink to &quot;obsidian&quot;">&ZeroWidthSpace;</a></h4>
<ul>
<li>写作时双链就只是好看，用Markdown标准文件链接渲染的时候还不会出错</li>
<li>使用 <a href="#^5925eb">功能提示块</a>的时候如果要包含代码，外面用四层`里面用三层点,不要用拓展语法<code>!!!</code>和<code>???</code> vuepress中不渲染，但是嵌套代码块会渲染，就用这仨功能就行了</li>
<li>插入时间设置 <code>YYYY-MM-DD HH:mm:ss</code> @可以直接在vuepress里面渲染生成时间轴</li>
<li>标签使用#tag，不要有空格,文章内的标签不要使用符号，vuepress的meta信息里只能有单层标签，所以不要用嵌套标签</li>
<li>嵌入文件的时候，[|300]中加入数字调整Obsidian内显示大小是可以兼容的</li>
<li>块引用是<code>[[^^]]</code>和<code>[[#]]</code>,是兼容的，只是不渲染</li>
<li>不要使用Obsidian中的自带注释，直接用html的注释</li>
<li>大附件扔Onedrive放个链接</li>
<li><mark>嵌入非图片jpg png svg文件的时候，文件名不要带有英文</mark></li>
</ul>
<h4 id="vitepress" tabindex="-1">vitepress <a class="header-anchor" href="#vitepress" aria-label="Permalink to &quot;vitepress&quot;">&ZeroWidthSpace;</a></h4>
<ol>
<li>日期一定要 <mark>2022-01-02 00:00:00</mark> 要全不然会报错</li>
<li>使用Admonition时的对应关系，事先约定规则，在ts中转换Admonition语法为Markdown-it-container
<ol>
<li>vuepress使用markdown-it-container,支持 tip danger warning theorem details，类型 标题</li>
<li>Admonition支持<code>note</code>,<code>abstract</code>,<code>info</code>,<code>tip</code>,<code>success</code>,<code>question</code>,<code>warning</code>,<code>failure</code>,<code>danger</code>,<code>bug</code>,<code>example</code>,<code>quote</code></li>
<li>example默认collapse是open，用detail，不加前缀，其他的collapse默认关闭直接删除。</li>
<li>把所有的<code>(./static/</code> 替换为<code>(./static/</code> 省得自己配置了</li>
<li>其他的把title拿上去，前面加前缀，例子ad-note 你好= 📝Note 你好</li>
</ol>
<ul>
<li>info:<code>note</code> =📝Note,<code>info</code>=📄Info，蓝色</li>
<li>tip: <code>abstract</code>=📘Abstract,<code>tip</code>=📌Tip,<code>success</code>=🎉Success，绿色</li>
<li>warning: <code>question</code>=❓Question,<code>warning</code>=⚠️Warning，橙色</li>
<li>danger: <code>failure</code>=❌Failure,<code>danger</code>=⚡️Danger,<code>bug</code>=🐛BUG，红色</li>
<li>theorem,details: <code>details</code> 这俩直接加标题白色</li>
</ul>
</li>
<li>标签和分类
<ul>
<li>成系列的文章放一个category</li>
<li>category分类按技术方向也就是文件夹tag填着玩就行</li>
</ul>
</li>
</ol>
<h3 id="metadata信息" tabindex="-1">metadata信息 <a class="header-anchor" href="#metadata信息" aria-label="Permalink to &quot;metadata信息&quot;">&ZeroWidthSpace;</a></h3>
<p>文件的开头会有metadata信息，如下代码块</p>
<div class="language-yaml vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">yaml</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">---</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">title</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">first page</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">date</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">2022-02-11 15:31:09</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> </span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">order</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">sidebar</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">true</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">prev</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">next</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">comment</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">false</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">category</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">- </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">系列1</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">tag</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">- </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">说明</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">---</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br></div></div><ul>
<li>title 必填不要重名</li>
<li>date 必填用@可以直接生成</li>
<li>order 在侧边栏中的排序</li>
<li>sidebar 是否在此篇中显示侧边栏</li>
<li>next和prev，就是上下页，如果已经被纳入侧边栏系列文章就可以不用配置，自己会生成</li>
<li>comment 要不要评论区</li>
<li>category 可以用中文，类似于系列，只要新出现的都会自动创建，可以一篇文章多个category</li>
<li>tag 标签可以用中文，vuepress只会解析metadata里的<a href="./Obsidian博客搭建.html#^d604fe">标签</a>，可以用Tag Wrangler插件管理</li>
</ul>
<h2 id="cicd" tabindex="-1">CICD <a class="header-anchor" href="#cicd" aria-label="Permalink to &quot;CICD&quot;">&ZeroWidthSpace;</a></h2>
<p>内置了Giscus 去照着文档配置一下</p>
<p>DroneCI+gitea</p>
<h2 id="语法示例" tabindex="-1">语法示例 <a class="header-anchor" href="#语法示例" aria-label="Permalink to &quot;语法示例&quot;">&ZeroWidthSpace;</a></h2>
<details class="details custom-block"><summary>CSS</summary>
<p>SS
我能吞下玻璃而不伤身体<br>
I can eat glass, it does not hurt me</p>
</details>
<p><a href="https://zhuanlan.zhihu.com/p/393550306" target="_blank" rel="noreferrer">dataview的教程</a><br/>
<a href="https://www.bilibili.com/video/BV1eS4y1C7wu" target="_blank" rel="noreferrer">领导年终奖50万，却只分给我100块_哔哩哔哩_bilibili</a></p>
<hr class="footnotes-sep">
<section class="footnotes">
<ol class="footnotes-list">
<li id="fn1" class="footnote-item"><p><a href="https://docs.djangoproject.com/zh-hans/2.2/" target="_blank" rel="noreferrer">Django 文档 | Django 文档 | Django</a> <a href="#fnref1" class="footnote-backref">↩︎</a></p>
</li>
<li id="fn2" class="footnote-item"><p><a href="https://v1.vuepress.vuejs.org/zh/guide/directory-structure.html" target="_blank" rel="noreferrer">目录结构 | VuePress</a> <a href="#fnref2" class="footnote-backref">↩︎</a></p>
</li>
</ol>
</section>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[第一章 初识C语言]]></title>
            <link>http://ooowl.fun/blogs/Book/C-primer-plus/%E7%AC%AC%E4%B8%80%E7%AB%A0-%E5%88%9D%E8%AF%86C%E8%AF%AD%E8%A8%80.html</link>
            <guid isPermaLink="false">http://ooowl.fun/blogs/Book/C-primer-plus/%E7%AC%AC%E4%B8%80%E7%AB%A0-%E5%88%9D%E8%AF%86C%E8%AF%AD%E8%A8%80.html</guid>
            <pubDate>Sat, 16 Apr 2022 09:12:00 GMT</pubDate>
            <content:encoded><![CDATA[<h1 id="第一章-初识c语言" tabindex="-1">第一章 初识C语言 <a class="header-anchor" href="#第一章-初识c语言" aria-label="Permalink to &quot;第一章 初识C语言&quot;">&ZeroWidthSpace;</a></h1><p class="article-meta">创建于 2022年4月16日 17:12:00 · 约0字</p>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[服务器装机]]></title>
            <link>http://ooowl.fun/blogs/Web%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/%E6%B5%8B%E8%AF%95%E8%BF%90%E7%BB%B4/%E6%9C%8D%E5%8A%A1%E5%99%A8%E8%A3%85%E6%9C%BA.html</link>
            <guid isPermaLink="false">http://ooowl.fun/blogs/Web%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/%E6%B5%8B%E8%AF%95%E8%BF%90%E7%BB%B4/%E6%9C%8D%E5%8A%A1%E5%99%A8%E8%A3%85%E6%9C%BA.html</guid>
            <pubDate>Sat, 19 Mar 2022 12:50:00 GMT</pubDate>
            <description><![CDATA[[💡Tip]]]></description>
            <content:encoded><![CDATA[<h1 id="服务器装机" tabindex="-1">服务器装机 <a class="header-anchor" href="#服务器装机" aria-label="Permalink to &quot;服务器装机&quot;">&ZeroWidthSpace;</a></h1><p class="article-meta">创建于 2022年3月19日 20:50:00 · 约1,358字</p>
<div class="tip custom-block"><p class="custom-block-title">[💡Tip]</p>
<p>折腾死我了，服务器资源利用的差不多了，踩好多坑。</p>
</div>
<h2 id="linux装机" tabindex="-1">Linux装机 <a class="header-anchor" href="#linux装机" aria-label="Permalink to &quot;Linux装机&quot;">&ZeroWidthSpace;</a></h2>
<p>技术选择的原则是便于小团体日常开发，可维护，开箱即用的开发测试生产环境。如果需要带个桌面建议先安装英文版时区选择新加坡，装完之后自己需要中文的地方调回来。<br>
发行版选择Debian最新的LTS，非LTS支持3年LTS支持5年<br>
换源更新，常见源 <a href="https://developer.aliyun.com/mirror/debian" target="_blank" rel="noreferrer">debian镜像-阿里开源镜像站</a> <a href="https://mirrors.cloud.tencent.com/help/debian.html" target="_blank" rel="noreferrer">Debian-腾讯镜像源</a> <a href="https://mirrors.tuna.tsinghua.edu.cn/help/debian/" target="_blank" rel="noreferrer">debian 清华开源软件镜像站</a></p>
<div class="language-bash vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">source</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> /etc/os-release</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> &#x26;&#x26; </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">echo</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> $VERSION_CODENAME </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 查看自己Debian发行版代号，也可以直接看*-release文件</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">vim</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> /etc/apt/sources.list</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 换源，可以先备份</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 更新源</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">apt-get</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> update</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">apt-get</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> upgrade</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 开发编译工具环境</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">apt-get</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> install</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -y</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> wget</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> vim</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> sudo</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> tree</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> net-tools</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> gcc</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> curl</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> htop</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> btop</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> lsof</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> iotop</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> iproute2</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> dnsutils</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> tcpdump</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> traceroute</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> mtr</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> iputils-ping</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> nmap</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> socat</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> telnet</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> netcat-openbsd</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> rsync</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> sshpass</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> lvm2</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> zip</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> unzip</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> p7zip-full</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> perl</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> cpio</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> asciidoc</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> xmlto</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> build-essential</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> libssl-dev</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> sqlite3</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> ripgrep</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 生产机精简环境</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">apt-get</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> install</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -y</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> wget</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> vim</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> sudo</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> tree</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> net-tools</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> curl</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> htop</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> lsof</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> iotop</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> iproute2</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> dnsutils</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> tcpdump</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> traceroute</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> mtr</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> iputils-ping</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> nmap</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> netcat-openbsd</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> rsync</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> lvm2</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> zip</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> unzip</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> p7zip-full</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> sqlite3</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> ripgrep</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 镜像base仅排障</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">apt-get</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> install</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> vim</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> sudo</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> tree</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> net-tools</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> wget</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> curl</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> iputils-ping</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> dnsutils</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> procps</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> tcpdump</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> lsof</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> mtr-tiny</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> strace</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> sysstat</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># Arch系我不是很常用</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># sudo pacman -S --needed wget vim tree net-tools gcc curl htop btop lsof iotop iproute2 bind tcpdump traceroute mtr iputils nmap socat inetutils tmux rsync sshpass lvm2 zip unzip p7zip unrar fastfetch perl cpio asciidoc xmlto base-devel pcre openssl sqlite</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">wget</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> https://github.com/fastfetch-cli/fastfetch/releases/latest/download/fastfetch-linux-amd64.deb</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # fastfetch没有提供deb源</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">sudo</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> apt</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> install</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> ./fastfetch-linux-amd64.deb</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br></div></div><p>git最好安装最新版</p>
<div class="language-bash vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">sudo</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> add-apt-repository</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> ppa:git-core/ppa</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">sudo</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> apt</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> update</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">sudo</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> apt</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> install</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> git</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> config</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> --global</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> user.email</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "xxxxxx@gmail.com"</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> config</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> --global</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> user.name</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "remoteServer"</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br></div></div><p>调整时间和本地化</p>
<div class="language-bash vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 设置时间</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">sudo</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> timedatectl</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> set-ntp</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> true</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  # 启用 NTP 同步</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">sudo</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> ln</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -sf</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> /usr/share/zoneinfo/Asia/Shanghai</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> /etc/localtime</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  # 设置时区为上海</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">sudo</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> hwclock</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> --systohc</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  # 将硬件时钟同步到系统时间</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">date</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -R</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  # 检查当前时间 (RFC 5322 格式)</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 语言本地化</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">sudo</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> apt</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> install</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -y</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> locales</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  # 安装 locales 基础包</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">sudo</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> locale-gen</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> zh_CN.UTF-8</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  # 生成 zh_CN.UTF-8 语言环境</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">sudo</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> update-locale</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> LANG=zh_CN.UTF-8</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  # 设置系统默认语言</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">source</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> /etc/default/locale</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  # 立即生效当前 shell</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br></div></div><h2 id="使用zimfw" tabindex="-1">使用zimfw <a class="header-anchor" href="#使用zimfw" aria-label="Permalink to &quot;使用zimfw&quot;">&ZeroWidthSpace;</a></h2>
<p>安装zsh切换默认，所有的设置都存放在<code>~/.zshrc</code>文件里</p>
<div class="language-bash vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">apt-get</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> install</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -y</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> zsh</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">chsh</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -s</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> /bin/zsh</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">sudo</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> chsh</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -s</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> /bin/zsh</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> player</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 为其他用户切换默认，如果切回用户之后不要让他自动设置zsh，然后安装zimfw</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 如果之前安装过omz需要先删除，记得先备份zshrc</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">uninstall_oh_my_zsh</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">rm</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -rf</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> ~/.oh-my-zsh</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br></div></div><p>没卸载omz的先找GPT卸载掉omz的东西和插件，autojupm可以保留，注意备份一下<code>.zshrc</code>卸载的时候给你删除很多内容。有些残留也需要清掉<br>
然后安装<a href="https://zimfw.sh/#install" target="_blank" rel="noreferrer">Zim Framework</a>，先安装主题<code>.zimrc</code>中添加 <code>zmodule romkatv/powerlevel10k</code>，然后<code>zimfw install &amp;&amp; zimfw update</code>，使用<code>p10k configure</code>可重复配置<br>
关注文件<code>.zshrc .p10k.zsh</code>，在p10k的配置文件中配置</p>
<details class="details custom-block"><summary>自定义p10k</summary>
<p>定义p10k</p>
<div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 自定义shell头</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">...</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">function</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> prompt_my_at_user</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">() {</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">  p10k</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> segment</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -f</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> yellow</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -t</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">USER</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">}@MacOS"</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 想放什么都可以，什么变量能用用到的时候去查查</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  # The list of segments shown on the left. Fill it with the most important segments.</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">  typeset</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -g</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> POWERLEVEL9K_LEFT_PROMPT_ELEMENTS</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    my_at_user</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">               # os identifier</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    # os_icon               # os identifier</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    dir</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">                     # current directory</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    vcs</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">                     # git status</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    # prompt_char           # prompt symbol</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  )</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">...</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 防止路径自动折叠</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 搜索 POWERLEVEL9K_SHORTEN 改和添加</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">typeset</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -g</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> POWERLEVEL9K_SHORTEN_DIR</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">none </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">typeset</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -g</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> POWERLEVEL9K_SHORTEN_STRATEGY</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">none</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">typeset</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -g</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> POWERLEVEL9K_SHORTEN_DIR_LENGTH</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">999</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">...</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br></div></div></details>
<p>安装autojump，支持j直接跳转（zim目前还没有原生支持</p>
<div class="language-bash vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> clone</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> https://github.com/joelthelion/autojump.git</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">cd</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> autojump</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">./install.py</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 如果已经用了zimfw，那么第二句auto compinit 可以删除不加</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br></div></div><p>把提示的东西添加到<code>~/.zshrc</code>文件尾。<br>
可以给命令行加代理(⚠️注意docker真正运行的进程是docker deamon，所以不会走shell的代理)</p>
<div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">export</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> http_proxy</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">http://127.0.0.1:7890</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">export</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> https_proxy</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">http://127.0.0.1:7890</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">export</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> all_proxy</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">socks5://127.0.0.1:7890</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br></div></div><p>nvm一定要安完zsh之后搞，这样就不用手动加了<br>
<code>curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash</code><br>
<code>nvm ls-remote</code> 记得安个最新的LTS
conda可以使用<a href="https://conda-forge.org/download/" target="_blank" rel="noreferrer">MiniForge</a>作为上位替代，安装完之后按照提示<code>conda init</code><br>
在zshrc里面把conda和nvm初始化替换为懒加载，启动shell的时候就可以瞬间加载</p>
<details class="details custom-block"><summary>让你的shell飞起来</summary>
<p>你的shell飞起来</p>
<div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># ---环境注入---</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 避免没有初次执行的时候没有node和python用(如果使用的miniforge则替换路径即可)</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">export</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> PATH</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"/opt/anaconda3/bin:</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">$PATH</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">export</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> PATH</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">$HOME</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">/.nvm/versions/node/v22.16.0/bin:</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">$PATH</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># !! Contents within this block are managed by 'conda init' !!</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># {</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># __conda_setup="$('/opt/anaconda3/bin/conda' 'shell.bash' 'hook' 2> /dev/null)"</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># if [ $? -eq 0 ]; then</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#     eval "$__conda_setup"</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># else</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#     if [ -f "/opt/anaconda3/etc/profile.d/conda.sh" ]; then</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># # . "/opt/anaconda3/etc/profile.d/conda.sh"  # commented out by conda initialize</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#     else</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># # export PATH="/opt/anaconda3/bin:$PATH"  # commented out by conda initialize</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#     fi</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># fi</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># unset __conda_setup</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># Lazy-load conda</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">conda</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">() {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    unset</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -f</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> conda</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> [ </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-f</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "/opt/anaconda3/etc/profile.d/conda.sh"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> ]; </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">then</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        source</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "/opt/anaconda3/etc/profile.d/conda.sh"</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    elif</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> [ </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-f</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">$HOME</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">/miniconda3/etc/profile.d/conda.sh"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> ]; </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">then</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        source</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">$HOME</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">/miniconda3/etc/profile.d/conda.sh"</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    else</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        echo</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "Error: conda.sh not found!"</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> >&#x26;2</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 127</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    fi</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    conda</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">$@</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># export PATH="/opt/anaconda3/bin:$PATH"  # commented out by conda initialize</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># >>> conda initialize >>></span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># NVM setting</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># {</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># export NVM_DIR="$HOME/.nvm"</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># [ -s "$NVM_DIR/nvm.sh" ] &#x26;&#x26; \. "$NVM_DIR/nvm.sh"  # This loads nvm</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># [ -s "$NVM_DIR/bash_completion" ] &#x26;&#x26; \. "$NVM_DIR/bash_completion"  # This loads nvm bash_completion</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">export</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> NVM_DIR</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">$HOME</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">/.nvm"</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">nvm</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">() {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">  unset</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -f</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> nvm</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  # 删除这个函数自身</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  [ </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-s</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">$NVM_DIR</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">/nvm.sh"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> ] &#x26;&#x26; </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">\.</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">$NVM_DIR</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">/nvm.sh"</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  [ </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-s</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">$NVM_DIR</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">/bash_completion"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> ] &#x26;&#x26; </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">\.</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">$NVM_DIR</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">/bash_completion"</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">  nvm</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">$@</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">      # 正常执行真正的 nvm 命令</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br><span class="line-number">50</span><br><span class="line-number">51</span><br><span class="line-number">52</span><br></div></div></details>
<p>其他的东西用起来和omz没区别，运行速度飞快。</p>
<h2 id="ssh-vscode相关" tabindex="-1">SSH&amp;Vscode相关 <a class="header-anchor" href="#ssh-vscode相关" aria-label="Permalink to &quot;SSH&amp;Vscode相关&quot;">&ZeroWidthSpace;</a></h2>
<p>生成的时候使用 <code>ssh-keygen -t ed25519 -C jacksAir</code>密钥会短，但是在一些过老和安全要求的系统里会不认ed25519,不能用的时候使用-v调试一下。<br>
ssh 隧道，直接ssh B 就可以直接代理过去，不用别的配置，有时候在docker里面的ssh会连接失败但是大部分场景都够用。</p>
<div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Host</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> A</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">  HostName</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 192.168.1.2</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">  User</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> root</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">  Port</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 22</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Host</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> B</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">  HostName</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 192.168.1.3</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">  User</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> root</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">  Port</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 8890</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">  ProxyJump</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> root@192.168.1.2</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br></div></div><p>vscode搜索完之后按下<code>Alt+Enter</code>快捷键，即可快速选取所有匹配的文本创建多行光标</p>
<h3 id="ssh目录权限" tabindex="-1">ssh目录权限 <a class="header-anchor" href="#ssh目录权限" aria-label="Permalink to &quot;ssh目录权限&quot;">&ZeroWidthSpace;</a></h3>
<p>为了安全，如果sshd对属主的目录和文件权限不对，则ssh的免密码登陆不生效。<br>
所属用户的.ssh目录权限应为 755 或者 700，不能是77x、777，需要保障other用户不能有w权限。<br>
<strong>rsa_id.pub及authorized_keys known_hosts的权限一般为644, rsa_id的权限必须为600</strong></p>
<h2 id="docker" tabindex="-1">docker <a class="header-anchor" href="#docker" aria-label="Permalink to &quot;docker&quot;">&ZeroWidthSpace;</a></h2>
<p>安装<a href="https://docs.docker.com/engine/install/debian/" target="_blank" rel="noreferrer">docker</a>和<a href="https://docs.portainer.io/start/install-ce/server/docker/linux" target="_blank" rel="noreferrer">Portainer</a> 在安装CE和Desktop的时候，会把compose自动带，docker v2默认带着compose命令，standalone的方式在2023.7不再更新。</p>
<div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">/usr/sbin/usermod</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -aG</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> sudo</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> player</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # debian精简版要用完整路径</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">/usr/sbin/usermod</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -aG</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> docker</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> player</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br></div></div><h3 id="域名配置" tabindex="-1">域名配置 <a class="header-anchor" href="#域名配置" aria-label="Permalink to &quot;域名配置&quot;">&ZeroWidthSpace;</a></h3>
<p>nginxWebUI里面直接添加。<br>
几个资源，<a href="https://nginxconfig.io" target="_blank" rel="noreferrer">自动生成配置文件</a>，<a href="https://www.bilibili.com/video/BV1Ef4y1F7Pe" target="_blank" rel="noreferrer">申请证书</a>。<br>
申请SSL，cloudflare-&gt;个人配置-&gt;API key -&gt; Global API Key -&gt; view API key 邮箱+key填进去</p>
<p>ssl 接收到一个超出最大准许长度的记录。 错误代码 ssl_error_rx_record_too_long 谷歌搜索443 ssl<br>
加了ssl之后不能自动跳转https，纯域名访问就可以，原理我也没深究<br>
头部添加特殊的header自动跳转https</p>
<h3 id="防火墙" tabindex="-1">防火墙 <a class="header-anchor" href="#防火墙" aria-label="Permalink to &quot;防火墙&quot;">&ZeroWidthSpace;</a></h3>
<p>用户防火墙，配置完nginx之后，依然可以通过http+域名:端口访问，配置user fire wall禁止端口特定放行。<br>
配合http跳转https，就可以强制只能通过域名访问了。<br>
记得配置nginx的转发要用127.0.0.1。</p>
<div class="warning custom-block"><p class="custom-block-title">[⚠️Warning]</p>
<p>开了个 Docker 容器，绑定了 <code>-p 3306:3306</code> 并开启了 <code>ufw</code> 。发现竟然外网可以直接访问！！<br>
原来 Docker 会默认直接加规则到 iptables，所以 UFW 防火墙对 docker 无效。<br>
基本上可以找到的解决办法就是首先禁用 docker 的 iptables 功能，但这也意味着放弃了 docker 的网络管理功能<br>
github有个答案</p>
</div>
<p><strong>无法解决，就这样了，丑陋</strong><br>
因为docker是添加iptables管理网络，ufw直接没用，如果手动更改它的iptables那就相当于docker的网络管理没用了，没办法，正式生产环境肯  定会有网关和内部服务器，就可以完美避免了。<br>
丑陋。</p>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[自顶向下]]></title>
            <link>http://ooowl.fun/blogs/Book/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C%E8%87%AA%E9%A1%B6%E5%90%91%E4%B8%8B/%E8%87%AA%E9%A1%B6%E5%90%91%E4%B8%8B.html</link>
            <guid isPermaLink="false">http://ooowl.fun/blogs/Book/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C%E8%87%AA%E9%A1%B6%E5%90%91%E4%B8%8B/%E8%87%AA%E9%A1%B6%E5%90%91%E4%B8%8B.html</guid>
            <pubDate>Wed, 16 Mar 2022 15:01:06 GMT</pubDate>
            <content:encoded><![CDATA[<h1 id="自顶向下" tabindex="-1">自顶向下 <a class="header-anchor" href="#自顶向下" aria-label="Permalink to &quot;自顶向下&quot;">&ZeroWidthSpace;</a></h1><p class="article-meta">创建于 2022年3月16日 23:01:06 · 约258字</p>
<p><a href="https://www.bilibili.com/video/BV1JV411t7ow" target="_blank" rel="noreferrer">中科大郑烇、杨坚全套《计算机网络（自顶向下方法 第7版，James F.Kurose，Keith W.Ross）》</a></p>
<div class="tip custom-block"><p class="custom-block-title">[💡Tip] 我来试试</p>
<p>来试试
dhahuasj是大师</p>
</div>
<h3 id="localhost-不完全等于-127-0-0-1" tabindex="-1">localhost 不完全等于 127.0.0.1 <a class="header-anchor" href="#localhost-不完全等于-127-0-0-1" aria-label="Permalink to &quot;localhost 不完全等于 127.0.0.1&quot;">&ZeroWidthSpace;</a></h3>
<p>localhost 是 <strong>主机名</strong> （hostname），它通常被用来表示本地计算机，并且默认被解析到 127.0.0.1 这个地址。<br>
但是你只要修改主机文件（hosts），就可以把 localhost 解析到其他地址，跟域名解析类似。<br>
而 127.0.0.1 是 IPv4 的一个特殊的 <strong>IP 地址</strong>，直接指向本地回环接口，用于在本地进行网络通信。<br>
为了兼容 IPv4 和 IPv6，我们访问 localhost 时，操作系统会首先尝试解析 IPv6 的回环地址 <code>::1</code> 。如果系统不支持 IPv6，或者无法解析为 IPv6 地址，才会继续解析为 IPv4 的回环地址 127.0.0.1。<br>
而直接访问 127.0.0.1 时，系统会默认解析到 IPv4 的回环接口。这才导致输入这两个地址时，使用的服务 / 访问到的内容不一样。</p>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Scrapy-Redis分布式爬虫]]></title>
            <link>http://ooowl.fun/blogs/Python/%E7%88%AC%E8%99%AB/Scrapy-Redis%E5%88%86%E5%B8%83%E5%BC%8F%E7%88%AC%E8%99%AB.html</link>
            <guid isPermaLink="false">http://ooowl.fun/blogs/Python/%E7%88%AC%E8%99%AB/Scrapy-Redis%E5%88%86%E5%B8%83%E5%BC%8F%E7%88%AC%E8%99%AB.html</guid>
            <pubDate>Tue, 15 Mar 2022 15:07:00 GMT</pubDate>
            <content:encoded><![CDATA[<h1 id="scrapy-redis分布式爬虫" tabindex="-1">Scrapy-Redis分布式爬虫 <a class="header-anchor" href="#scrapy-redis分布式爬虫" aria-label="Permalink to &quot;Scrapy-Redis分布式爬虫&quot;">&ZeroWidthSpace;</a></h1><p class="article-meta">创建于 2022年3月15日 23:07:00 · 约0字</p>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Scrapy爬虫]]></title>
            <link>http://ooowl.fun/blogs/Python/%E7%88%AC%E8%99%AB/Scrapy-%E7%88%AC%E8%99%AB.html</link>
            <guid isPermaLink="false">http://ooowl.fun/blogs/Python/%E7%88%AC%E8%99%AB/Scrapy-%E7%88%AC%E8%99%AB.html</guid>
            <pubDate>Tue, 15 Mar 2022 15:04:00 GMT</pubDate>
            <content:encoded><![CDATA[<h1 id="scrapy爬虫" tabindex="-1">Scrapy爬虫 <a class="header-anchor" href="#scrapy爬虫" aria-label="Permalink to &quot;Scrapy爬虫&quot;">&ZeroWidthSpace;</a></h1><p class="article-meta">创建于 2022年3月15日 23:04:00 · 约0字</p>
<div class="tip custom-block"><p class="custom-block-title">[💡Tip] 萨德萨德爱迪生撒</p>
<p>德萨德爱迪生撒
sasdas</p>
</div>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Py踩坑记录]]></title>
            <link>http://ooowl.fun/blogs/Python/%E8%AF%AD%E6%B3%95%E5%92%8C%E5%BA%93/Py%E8%B8%A9%E5%9D%91%E8%AE%B0%E5%BD%95.html</link>
            <guid isPermaLink="false">http://ooowl.fun/blogs/Python/%E8%AF%AD%E6%B3%95%E5%92%8C%E5%BA%93/Py%E8%B8%A9%E5%9D%91%E8%AE%B0%E5%BD%95.html</guid>
            <pubDate>Tue, 15 Mar 2022 11:09:00 GMT</pubDate>
            <content:encoded><![CDATA[<h1 id="py踩坑记录" tabindex="-1">Py踩坑记录 <a class="header-anchor" href="#py踩坑记录" aria-label="Permalink to &quot;Py踩坑记录&quot;">&ZeroWidthSpace;</a></h1><p class="article-meta">创建于 2022年3月15日 19:09:00 · 约238字</p>
<h2 id="pydicom" tabindex="-1">pydicom <a class="header-anchor" href="#pydicom" aria-label="Permalink to &quot;pydicom&quot;">&ZeroWidthSpace;</a></h2>
<p>使用pydicom的时候，版本依赖有很强的限制，场景是在宿主机上安装docker，在docker里面运行python程序识别dicom转为图片，出现<code>PyDICOM can't read pixel data and needs GDCM or Pillow</code>。如果是从别的地方先用pip download是不行的，但是直接在docker环境中pip安装就没有什么问题。</p>
<h2 id="jupyterhub自定义鉴权" tabindex="-1">JupyterHub自定义鉴权 <a class="header-anchor" href="#jupyterhub自定义鉴权" aria-label="Permalink to &quot;JupyterHub自定义鉴权&quot;">&ZeroWidthSpace;</a></h2>
<p>找了无数资料真的好痛苦<br>
今晚基于的是公司自己的lab镜像。先基于<a href="https://gist.github.com/tanbro/a94bfa4a552381f599e7e6b551ccadcf" target="_blank" rel="noreferrer">这个指南</a>去操作，操作到用户环境隔离之前
把那几个配置文件换上
<code>.jupyter</code>文件夹下鉴权的配置文件撤销掉<code>jupyter_server_config.json</code><br>
<code>jupyter_lab_config.py</code>里面需要替换的在<code>lab_config_change.py</code>，剩下三个都放到<code>/opt/jupyterhub</code><br>
使用<code>/root/miniforge3/envs/intel-opt/bin/jupyterhub -f /opt/jupyterhub/config.py</code> 启动hub。</p>
<h2 id="" tabindex="-1"> <a class="header-anchor" href="#" aria-label="Permalink to &quot;&quot;">&ZeroWidthSpace;</a></h2>
<p>#todo 多进程情况下，@contextlib yield engine pandas不断建立连接的问题，transform main_bak.py</p>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[关于]]></title>
            <link>http://ooowl.fun/about/</link>
            <guid isPermaLink="false">http://ooowl.fun/about/</guid>
            <pubDate>Wed, 09 Feb 2022 19:24:45 GMT</pubDate>
            <content:encoded><![CDATA[<h1 id="关于" tabindex="-1">关于 <a class="header-anchor" href="#关于" aria-label="Permalink to &quot;关于&quot;">&ZeroWidthSpace;</a></h1><p><br/><br/><br/></p>
<div align="center" style="width: 90%;padding-left: 6%; ">  
<div align="left" class="mao-poem">  
西风烈<br/>  
长空雁叫霜晨月<br/><br/>  
霜晨月<br/>   
马蹄声碎 喇叭声咽<br/><br/>  
雄关漫道真如铁 而今迈步从头越<br/><br/>  
从头越<br/>  
苍山如海 残阳如血<br/>  
</div>  
<div align="right"><small>———— 毛泽东《忆秦娥·娄山关》 </small></div>  
</div>  
<br/><br/><br/><br/><br/><br/><br/><br/>  
<div align=center ><img src="../assets/about.jpg" style="height: 250px"/></div>  
<div align="center" style="font-size: 20px;">  
<br/>  
喜欢写代码，喜欢玩单机联机Switch🎮，看好看的电影书还有沙雕(oﾟvﾟ)，也喜欢安静的思考。<br/>     希望踩过的坑能给其他人一点帮助<br/>     
<span style="font-style: italic;font-size: 27px;font-weight: bold;">For Better Engineering, For More Knowledge</span>
<a href="https://www.foreverblog.cn/" target="_blank" > <img src="https://foreverblog.cn/assets/logo/logo_en_default.png" alt="" style="width:auto;height:25px;"> </a>
</div>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[版本控制]]></title>
            <link>http://ooowl.fun/blogs/%E4%BB%A3%E7%A0%81%E4%B9%8B%E5%A4%96/%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6.html</link>
            <guid isPermaLink="false">http://ooowl.fun/blogs/%E4%BB%A3%E7%A0%81%E4%B9%8B%E5%A4%96/%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6.html</guid>
            <pubDate>Tue, 05 Nov 2019 15:16:35 GMT</pubDate>
            <description><![CDATA[这是简单指南，图解git，可以放在收藏夹想不起来了拿起来看看. 装好之后先配置一下账户。]]></description>
            <content:encoded><![CDATA[<h1 id="版本控制" tabindex="-1">版本控制 <a class="header-anchor" href="#版本控制" aria-label="Permalink to &quot;版本控制&quot;">&ZeroWidthSpace;</a></h1><p class="article-meta">创建于 2019年11月5日 23:16:35 · 约4,075字</p>
<h2 id="git操作" tabindex="-1">Git操作 <a class="header-anchor" href="#git操作" aria-label="Permalink to &quot;Git操作&quot;">&ZeroWidthSpace;</a></h2>
<h3 id="初始化" tabindex="-1">初始化 <a class="header-anchor" href="#初始化" aria-label="Permalink to &quot;初始化&quot;">&ZeroWidthSpace;</a></h3>
<p>这是<a href="https://rogerdudler.github.io/git-guide/index.zh.html">简单指南</a>，<a href="http://marklodato.github.io/visual-git-guide/index-zh-cn.html#basic-usage" target="_blank" rel="noreferrer">图解git</a>，可以放在收藏夹想不起来了拿起来看看.<br>
装好之后先配置一下账户。</p>
<p><strong><code>/etc/gitconfig</code></strong> 是系统级别的配置，使用--system，这些配置是会按级别覆盖的，仓库覆盖账户覆盖系统<br>
<strong><code>~/.gitconfig</code></strong> 下是账户级别的配置<br>
<strong><code>git config --global user.name &quot;ooowl&quot; </code></strong><br>
<strong><code>git config --global user.email &quot;123456789@qq.com&quot;</code></strong></p>
<p>作者是谁，仓库commit会有你的名字，名字和email(名字可以重复但email一般唯一)并不作为身份标识，只是一个标记而已所有的独立提交不记名只验证公钥或github账号,你可以通过这样来查看<br>
<strong><code>git config --local user.name </code></strong><br>
<strong><code>git config --local user.email</code></strong></p>
<p>git init就会在该目录下生成一个.git文件夹，想知道这个文件夹里面是什么就自己去搜。<br>
<strong><code>git config --xxxx --list</code></strong> 显示本级下git 的配置</p>
<div class="tip custom-block"><p class="custom-block-title">[💡Tip]</p>
<p>个人习惯git commit的信息<code>类型[add,delete,fix,feature,end]-此功能第几次提交-其他描述</code> 其实这个是有明确规范名的，小项目无所谓，大项目看项目需要，遵守github定义的规范还可以自动生成change logs</p>
</div>
<h3 id="命令" tabindex="-1">命令 <a class="header-anchor" href="#命令" aria-label="Permalink to &quot;命令&quot;">&ZeroWidthSpace;</a></h3>
<h4 id="不用说的命令" tabindex="-1">不用说的命令 <a class="header-anchor" href="#不用说的命令" aria-label="Permalink to &quot;不用说的命令&quot;">&ZeroWidthSpace;</a></h4>
<p><strong><code>git --version</code></strong>
<strong><code>git status</code></strong> 看看自己目前仓库里未跟踪的文件，修改未提交的文件<br>
<strong><code>git clone  </code></strong> 克隆项目<br>
<strong><code>git add (.) </code></strong> 把文件添加到暂存区，未跟踪的文件可以直接添加为跟踪<br>
<strong><code>git pull</code></strong><br>
<strong><code>git commit -m &quot;提交信息&quot;</code></strong><br>
<strong><code>git fetch</code></strong> 从更新分支状态</p>
<ol>
<li>首先，Git 会与指定的远程仓库建立通信，并检查是否有新的提交历史。</li>
<li>Git 查找本地仓库中不存在的远程分支和标签，并将它们的引用（reference）下载到本地。</li>
<li>如果有新的提交历史，Git 会将这些提交的数据下载到本地仓库中，但不会自动合并到当前分支。</li>
<li>如果有远程分支与本地分支存在对应关系，Git 会更新本地分支的指针（引用）以指向远程分支的最新提交。</li>
<li>完成后，你可以运行其他命令（如 <code>git merge</code> 或 <code>git rebase</code>）来将下载的提交合并到当前分支。</li>
</ol>
<h4 id="不常用的命令" tabindex="-1">不常用的命令 <a class="header-anchor" href="#不常用的命令" aria-label="Permalink to &quot;不常用的命令&quot;">&ZeroWidthSpace;</a></h4>
<p><strong><code>git show (id or tag)</code></strong> 查看这次id和tag的详细信息，包括提交时间作者提交了什么更改<br>
<strong><code>git log (--oneline --all --graph ) </code></strong> 查看所有的提交记录，回滚需要至少7位id，-p查看提交具体干了啥,--all查看所有的分支，--graph 尽可能用图形表示。<br>
<strong><code>git reflog </code></strong> 查看命令历史，以便确定要回到未来的哪个版本<br>
<strong><code>git reflog show --date=iso new</code></strong> 查看本分支所有的记录<br>
<strong><code>git blame File</code></strong> 查看File的更改提交历史<br>
<strong><code>git rebase </code></strong> 不要用，会变基！！！</p>
<div class="warning custom-block"><p class="custom-block-title">[⚠️Warning]</p>
<p>merge会在head后面紧接着提交，合并后自动提交一次作为标记，worktree会有一个分支记录。<br>
rebase会在分支根提交点处接着提交，之后再跟上master该节点之后的的提交，worktree不会有分支记录。</p>
</div>
<p>你可以认为 HEAD(大写)是&quot;current branch&quot;(当下的分支)。当你用git checkout切换分支的时候，HEAD 修订版本重新指向新的分支。有的时候HEAD会指向一个没有分支名字的修订版本，这种情况叫”detached HEAD“<br>
head(小写)是commit对象的引用，每个head都有一个名字（分支名字或者标签名字等等），但是默认情况下，每个叫master的repository都会有一个head, 一个repository可以包含任意数量的head。在任何时候，只要这个head被选择成为”current head“，那么这个head就成了HEAD,总是大写</p>
<h4 id="管理远程仓库" tabindex="-1">管理远程仓库 <a class="header-anchor" href="#管理远程仓库" aria-label="Permalink to &quot;管理远程仓库&quot;">&ZeroWidthSpace;</a></h4>
<p>默认的仓库为origin</p>
<div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> remote</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> set-url</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> origin</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> &#x3C;</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">remote-ur</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">l</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">></span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 为已有的源设置url</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> remote</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -vv</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 查看所有的仓库</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> remote</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> add</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> vps</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> ssh://git@addr:port/path/test.git</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 添加远程仓库,只会添加到本地而不会影像其他人的git</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> remote</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> remove</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> vps</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br></div></div><h4 id="管理分支" tabindex="-1">管理分支 <a class="header-anchor" href="#管理分支" aria-label="Permalink to &quot;管理分支&quot;">&ZeroWidthSpace;</a></h4>
<div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> branch</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 查看本地分支</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> branch</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -r</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 查看远程的分支</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> branch</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -vv</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 查看所有的本地分支和远程的对应关系</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> checkout</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -b</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> new</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> [existing] </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 从existing创建新的分支,如果不指定那就是当前所处的分支</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> branch</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> feature/new-feature</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 创建子分支，可以用来归档</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> branch</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -d</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> name</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 本地删除name分支</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> push</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> origin</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> --delete</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> name</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 推送远程删除远程的name分支</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> branch</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -m</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> old_name</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> new_name</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 重命名分支 </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> push</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -u</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> origin</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> new_name</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 将本地的新分支推送到远程</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 此时远程会有两个分支，本地只会有这个重命名的新分支，其他人可以拉新分支，最后删掉旧分支就可以</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 合并分支</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> merge</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> abc</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 当前所在的分支和指定的分支进行合并</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> merge</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> --abort</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 合并冲突之后放弃合并</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 追踪分支</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> branch</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> --set-upstream-to=origin/main</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> main</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 追踪origin/main分支</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> branch</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> --unset-upstream</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> main</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 当前分支不再追踪main分支</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> for-each-ref</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> --format=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'%(committerdate:short): %(refname:short)'</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> refs/heads</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 查看所有的分支的创建时间使用refs/remotes查看远程的</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># %(refname)：完整的分支名</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># %(authordate)：分支创建者的提交时间</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># %(taggerdate)：最近的标签时间</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br></div></div><div class="tip custom-block"><p class="custom-block-title">[💡Tip]</p>
<p>checkout 不仅能切换分支,实际上什么也能切换，分支HEADcommit等都可以<br>
但是switch 是只能切换分支，功能有重合</p>
</div>
<h4 id="管理代码" tabindex="-1">管理代码 <a class="header-anchor" href="#管理代码" aria-label="Permalink to &quot;管理代码&quot;">&ZeroWidthSpace;</a></h4>
<p>提交什么的我就不说了，暂存会使代码恢复到上一次提交的状态，如果又修改了文件导致冲突，那就需要解决冲突</p>
<div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> diff</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> [文件] </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 对比哪些文件被修改了</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 从历史区回退本次commit</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> diff</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> --check</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 分支合并之后检查是否还有没结局的冲突</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 暂存代码</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> stash</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> save</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "暂时保存"</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> stash</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> list</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 列出所有的暂存</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> stash</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> apply</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> stash@{</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">}</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 应用第一个暂存</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> stash</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> drop</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> stash@{</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">}</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 删除第一个暂存</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> stash</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> pop</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> stash@{</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">}</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 应用第一个暂存并删除</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> stash</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> show</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -p</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> stash@{</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">}</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 查看某存储的文件改动加-p是带内容</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> checkout</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> commitid</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 回滚到某次commit。可用于在此分支提交新的分支</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> push</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> --force</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 用当前覆盖远程此分支的所有commit记录，可以用来清理旧的提交，先删除.git文件夹，然后新建分支追踪远程，最后强制推送</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> pull</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> --rebase</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 先拉取代码，然后再把你的提交放到拉取的最新提交之后，相当于先pull下来再作你的更改提交</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> rebase</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> --abort</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 如果pull rebase的代码有冲突了，你可以使用这个命令回归到没有pull rebase的状态，就可以正常pull解决冲突合并推送</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br></div></div><p>当你不小心改错了分支，本该在这个分支改但是你却在另一个分支改了。</p>
<ol>
<li>拿到你想转移的commit的hash</li>
<li>切换到你应该提交到的分支</li>
<li>使用cherry-pick</li>
</ol>
<div class="language-sh vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> log</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 查看你想转移commit的hash</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> cherry-pick</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> commit-hash</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 复制某个commit到目前的分支现在的状态下(樱桃是坏文明)</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br></div></div><p>cherry-pick如果遇到了冲突，那么会和merge的冲突一样。如果pick中涉及到了一个文件，但是这个分支没有这个文件创建的历史，那么git会尝试创建并把内容直接全都放到这个文件而不是只应用pick过来的更改</p>
<h3 id="恢复" tabindex="-1">恢复 <a class="header-anchor" href="#恢复" aria-label="Permalink to &quot;恢复&quot;">&ZeroWidthSpace;</a></h3>
<div class="language-bash vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> restore</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> file（path）#</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 恢复文件</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">某路径的所有文件</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">到上次提交的状态，丢弃已经更改的！！！</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">回滚之后又修改，和远程进行merge，直接覆盖远程</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> reset</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> --soft</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> HEAD~1</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 我想恢复上次的提交，就是我后悔上次提交，还应该再改改再提交</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> reset</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> --hard</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> HEAD~1</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 我想回到上次的提交，但是不保留提交内容</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> reset</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> HEAD</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> [file] </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 在已经add状态下撤销add,不带文件名就是整个仓库</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br></div></div><h3 id="管理tag" tabindex="-1">管理tag <a class="header-anchor" href="#管理tag" aria-label="Permalink to &quot;管理tag&quot;">&ZeroWidthSpace;</a></h3>
<p>相当于给某一次的commit加标记，标签是唯一的，标签打出来之后可以在github选择进行release<sup class="footnote-ref"><a href="#fn1" id="fnref1">[1]</a></sup></p>
<div class="language-bash vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> tag</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 列出所有标签</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> log</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> --oneline</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 也会列出标签</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> log</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -p</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 显示每次提交的diff</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">git tag -l</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 'V1*'</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 列出符合正则表达式的标签</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">git show</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> [tag_name] </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 显示特定标签的细节</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">git tag -a</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> tag_name</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> [-m 备注信息] [commitID(不指定就是当前的head)] </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 给一个commit打标签，可以添加备注信息</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">git tag -d</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> tag_name</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 删除本地的标签</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">git push origin -d tag</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 标签1名称</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 标签n名称</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 删除远程的若干个标签</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">git push origin</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> tag_1</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> tag_2</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 推送若干标签到远端</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">git push origin --tags</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 推送所有的标签到远端</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br></div></div><h2 id="git的管理结构" tabindex="-1">git的管理结构 <a class="header-anchor" href="#git的管理结构" aria-label="Permalink to &quot;git的管理结构&quot;">&ZeroWidthSpace;</a></h2>
<p><img src="./static/版本控制_images_1.png" alt="">
当你切换分支的时候，Git 会用该分支的最后提交的快照替换你的工作目录的内容， 所以多个分支不需要多个目录</p>
<p><a href="https://blog.csdn.net/hancoder/article/details/120748968" target="_blank" rel="noreferrer">【git】原理与.git文件夹解读-CSDN博客</a></p>
<h4 id="head相关的东西" tabindex="-1">HEAD相关的东西 <a class="header-anchor" href="#head相关的东西" aria-label="Permalink to &quot;HEAD相关的东西&quot;">&ZeroWidthSpace;</a></h4>
<p>HEAD是指向当前的指针，就是指向任何一个东西都可以。<br>
例如想要从已经提交过的commit历史创建记录没必要回滚回去， 直接把HEAD移过去就可以checkout 当你的当你的HEAD不在最新的分支的时候，<code>You are in 'detached HEAD' state.</code>，就意味着你的提交和修改都会在一个匿名的分支上，如果你不管它直接切回别的分支，那么此分支会被git标记为可清除，会在适当的时候被git自己的垃圾回收清除<br>
如果要保留那就直接从此处新建分支</p>
<details class="details custom-block"><summary>Click to see more</summary>
<div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> jack</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> ~/Desktop/gitdemo</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> main</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> ↑2</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> checkout</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 78a9df1</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">                                                               </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> ✔</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 5423</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 23:27:08</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Note:</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> switching</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> to</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> '78a9df1'.</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">You</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> are</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> in</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 'detached HEAD'</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> state.</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> You</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> can</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> look</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> around,</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> make</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> experimental</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">changes</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> and</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> commit</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> them,</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> and</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> you</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> can</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> discard</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> any</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> commits</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> you</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> make</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> in</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> this</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">state</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> without</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> impacting</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> any</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> branches</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> by</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> switching</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> back</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> to</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> a</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> branch.</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">If</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> you</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> want</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> to</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> create</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> a</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> new</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> branch</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> to</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> retain</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> commits</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> you</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> create,</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> you</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> may</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">do</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> so</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (now </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">or</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> later</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) by using -c with the switch command. Example:</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">  git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> switch</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -c</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> &#x3C;</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">new-branch-nam</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">e</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">></span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Or</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> undo</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> this</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> operation</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> with:</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">  git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> switch</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> -</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Turn</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> off</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> this</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> advice</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> by</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> setting</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> config</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> variable</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> advice.detachedHead</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> to</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> false</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">HEAD</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> is</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> now</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> at</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 78a9df1</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 匿名修</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> jack</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> ~/Desktop/gitdemo</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 78a9df1</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> checkout</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 78a9df1</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">                                                               </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> ✔</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 5424</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 23:27:19</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">HEAD</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> is</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> now</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> at</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 78a9df1</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 匿名修</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br></div></div></details>
<p>HEAD常用有三种</p>
<ul>
<li>HEAD~1 是在当前分支上找父提交，往回退1次</li>
<li>HEAD^1 是在merge过来的分支找父提交，往回退1次</li>
<li>HEAD@{1} 是从哪里过来的，就指回哪里去，但是此时也是指针分离状态，小心操作</li>
</ul>
<div class="tip custom-block"><p class="custom-block-title">[💡Tip]</p>
<p>git中的@{n} n∈[0,+♾️] 从0开始,stash和HEAD中都是</p>
</div>
<h2 id="服务器git-repo" tabindex="-1">服务器Git repo <a class="header-anchor" href="#服务器git-repo" aria-label="Permalink to &quot;服务器Git repo&quot;">&ZeroWidthSpace;</a></h2>
<p>客户机生成公钥</p>
<div class="tip custom-block"><p class="custom-block-title">[💡Tip]</p>
<p>只要你的服务器上 OpenSSH 版本大于 6.5（2014 年的古早版本），就可以利用 Ed25519 算法生成的密钥，生成密钥的时候使用<code>ssh-keygen -t ed25519 -C Name@client.com</code>，性能高更安全，而且密钥长度比RSA短很多
<a href="https://www.taurusxin.com/ssh-key-ed25519/" target="_blank" rel="noreferrer">更换你的 SSH 公钥算法</a></p>
</div>
<h3 id="申请用户" tabindex="-1">申请用户 <a class="header-anchor" href="#申请用户" aria-label="Permalink to &quot;申请用户&quot;">&ZeroWidthSpace;</a></h3>
<p>申请用户并设置密码，申请git组,把用到的用户加到这个组里，一般git就够了</p>
<div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">groupadd</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> git</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">useradd</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> git</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -g</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> git</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br></div></div><p>在<mark>服务器</mark>上root进入<code>/etc/ssh</code> 目录，编辑 <code>sshd_config</code>，打开以下三个配置的注释：</p>
<div class="language-bash vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">RSAAuthentication</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> yes</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">PubkeyAuthentication</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> yes</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">AuthorizedKeysFile</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> .ssh/authorized_keys</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">/etc/rc.d/init.d/sshd</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> restart</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> //重启ssh</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br></div></div><h3 id="修改权限并创建仓库" tabindex="-1">修改权限并创建仓库 <a class="header-anchor" href="#修改权限并创建仓库" aria-label="Permalink to &quot;修改权限并创建仓库&quot;">&ZeroWidthSpace;</a></h3>
<p>在home下建立对应的工程最好,每个用管理自己的工程，<mark>别忘了改repo的权限和所有者为git</mark>，不然可能会引发权限错误</p>
<div class="language-bash vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">sudo</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> init</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> --bare</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> /home/git/gitdemo.git</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">chown</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -R</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> git:git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> /home/git/gitdemo.git</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 千万别忘了改所有权，尤其是权限不够的时候，root是可以直接clone的</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">mkdir</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -p</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> /home/git/.ssh</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">touch</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> /home/git/.ssh/authorized_keys</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br></div></div><p><strong>一定要修改权限!!!</strong><br>
免密登录也是这个权限,本身就是免密登录ssh传送的文件.<br>
如果权限对的话就不用管</p>
<div class="warning custom-block"><p class="custom-block-title">[⚠️Warning]</p>
<p>修改 .ssh 目录的权限为 700<br>
修改 .ssh/authorized_keys 文件的权限为 600<br>
仓库 .ssh目录和authorized_keys都要修改所有者</p>
</div>
<div class="language-bash vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">chown</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -R</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> git:git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> /home/git</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">chmod</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 700</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">  /home/git/.ssh</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">chmod</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 600</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">  /home/git/.ssh/authorized_keys</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br></div></div><p>然后将客户机们的公钥<code>id_rsa.pub</code>里面的内容复制到git用户的<code>authorized_keys</code>里面<br>
每个用户单独的ssh K,这样就可以一个用户对应一个工程互不影响,多个工程只要申请多个用户,放到git用户组更管理就可以了.</p>
<p>最后设置用户只能使用git禁止登陆ssh,并修改密码,编辑<code>/etc/passwd</code></p>
<div class="language-bash vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">git:x:502:504::/home/git:/bin/bash</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> //找到这一行</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">git:x:502:504::/home/git:/bin/git-shell//改为这个</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br></div></div><h3 id="连接远程分支" tabindex="-1">连接远程分支 <a class="header-anchor" href="#连接远程分支" aria-label="Permalink to &quot;连接远程分支&quot;">&ZeroWidthSpace;</a></h3>
<p>这时候<mark>客户机本地</mark>应该可以clone了,url有两种写法(推荐ssh)</p>
<div class="language-bash vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">git@192.168.0.100:/home/git/gitdemo.git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> //SCP写法</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">ssh://git@192.168.0.100:23456/home/git/gitdemo.git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> //SSH写法,适用于非22端口</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">//Https的写法没有配置,而且每次都要输密码,团队协作Ω不好用</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br></div></div><p>如果是本地已经有repo了，可和远程连接起来<br>
<code>git remote add origin git@192.168.0.100:/home/git/gitdemo.git</code><br>
<code>git push --set-upstream origin main</code> 把本地的main分支和远程main关联起来(假设只有main分支)<br>
pull，merge就可以用来了<br>
冷知识，仓库的语言是server设置的，没用的知识增加了。</p>
<h4 id="保存用户名和密码" tabindex="-1">保存用户名和密码 <a class="header-anchor" href="#保存用户名和密码" aria-label="Permalink to &quot;保存用户名和密码&quot;">&ZeroWidthSpace;</a></h4>
<p>主要就是这个命令<code>git config --global credential.helper store</code>，相当于修改<code>.gitconfig</code>使用global的时候， 会在<code>~/.git-credentials</code>中以<strong>明文</strong>存用户名和密码，每个网站单独存储，不带的时候存储在当前仓库的 <code>.git/config</code> 作用范围不一样。<a href="https://stackoverflow.com/questions/68775869/message-support-for-password-authentication-was-removed" target="_blank" rel="noreferrer">有些网站使用token验证https的repo</a><br>
当然也可以使用<code>cache</code>而不是<code>store</code>这样是默认记住15min，也可以自己设置时间，感觉不常用。<br>
git push 超过100M解决办法 <code>git config http.postBuffer 524288000</code>（500M）</p>
<h2 id="参考" tabindex="-1">参考 <a class="header-anchor" href="#参考" aria-label="Permalink to &quot;参考&quot;">&ZeroWidthSpace;</a></h2>
<h3 id="gitflow工作流" tabindex="-1">gitflow工作流 <a class="header-anchor" href="#gitflow工作流" aria-label="Permalink to &quot;gitflow工作流&quot;">&ZeroWidthSpace;</a></h3>
<p>gitflow<a href="https://www.atlassian.com/git/tutorials/comparing-workflows/gitflow-workflow">工作流</a>，团队开发的范例。<br>
<img src="./static/版本控制_images_2.png" alt="800"></p>
<h3 id="github工作流" tabindex="-1">github工作流 <a class="header-anchor" href="#github工作流" aria-label="Permalink to &quot;github工作流&quot;">&ZeroWidthSpace;</a></h3>
<div class="language-mermaid vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">mermaid</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">gitGraph</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    commit id: "初始化"</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    commit id: "main"</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    branch feature</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    checkout feature</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    commit id: "新建分支" type: HIGHLIGHT</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    commit id: "提交修改" tag: "commit" type: HIGHLIGHT</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    commit id: "创建PR" tag: "PR" type: HIGHLIGHT</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    checkout main</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    merge feature tag: "代码评审" type: REVERSE</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    commit id: "部署" tag: "v1.0" type: HIGHLIGHT</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    commit id: "合并完成✓"</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br></div></div><p>主要流程为:</p>
<ul>
<li>新建分支（Create a branch）</li>
<li>提交修改（Add commits）</li>
<li>创建PR（Open a Pull Request）</li>
<li>代码评审（Discuss and review your code）</li>
<li>部署（Deploy）</li>
<li>合并（Merge）</li>
</ul>
<h3 id="在github提pr" tabindex="-1">在github提PR <a class="header-anchor" href="#在github提pr" aria-label="Permalink to &quot;在github提PR&quot;">&ZeroWidthSpace;</a></h3>
<p>单纯的提PR，不对github这种代码平台和协作的操作记录，如果以后要用到gitlab或者github协作的时候再去看
#TODO</p>
<h3 id="ignore参考" tabindex="-1">ignore参考 <a class="header-anchor" href="#ignore参考" aria-label="Permalink to &quot;ignore参考&quot;">&ZeroWidthSpace;</a></h3>
<p><a href="https://github.com/github/gitignore" target="_blank" rel="noreferrer">gitignore语法模板</a></p>
<ol>
<li><code>#</code> 此为注释</li>
<li><code>*.a</code> 忽略所有.a结尾的文件</li>
<li><code>!lib.a</code> 但lib.a除外</li>
<li><code>/todo</code> 仅仅忽略项目根目录下的todo文件，不包括subdir/todo</li>
<li><code>build/*</code> 忽略build/目录下的所有文件</li>
<li><code>doc/*.txt</code>忽略doc/notes.txt(只忽略doc下本身的文件)，但不包括doc/server/arch.txt(子目录下的文件)</li>
<li>原来已经被跟踪的文件是无效的，必须先取消跟踪git rm --cache，下次提交就不会生效了</li>
<li><code>.idea/**/*</code> 忽略某个(idea)文件夹下所有的文件和子文件夹(递归忽略所有)</li>
</ol>
<h2 id="踩坑" tabindex="-1">踩坑 <a class="header-anchor" href="#踩坑" aria-label="Permalink to &quot;踩坑&quot;">&ZeroWidthSpace;</a></h2>
<h3 id="多平台换行符问题-lf-or-crlf" tabindex="-1">多平台换行符问题(LF or CRLF) <a class="header-anchor" href="#多平台换行符问题-lf-or-crlf" aria-label="Permalink to &quot;多平台换行符问题(LF or CRLF)&quot;">&ZeroWidthSpace;</a></h3>
<h4 id="出现的问题" tabindex="-1">出现的问题<sup class="footnote-ref"><a href="#fn2" id="fnref2">[2]</a></sup> <a class="header-anchor" href="#出现的问题" aria-label="Permalink to &quot;出现的问题[^1]&quot;">&ZeroWidthSpace;</a></h4>
<p><strong>git提示code analyze的时候换行符是否要转换</strong><br>
<strong>文本文件所使用的换行符，在不同的系统平台上是不一样的</strong>。UNIX/Linux 使用的是 <code>0x0A（LF）</code>，早期的 Mac OS 使用的是 <code>0x0D（CR）</code>，后来的 OS X 在更换内核后与 UNIX 保持一致了。但 DOS/Windows 一直使用 <code>0x0D0A（CRLF）</code> 作为换行符<br>
在不同平台上，换行符发生改变时，Git 会认为整个文件被修改，这就造成我们没法 <code>diff</code>，不能正确反映本次的修改。会出现所有文件都冲突的情况</p>
<p>git使用<code>git config --global core.autocrlf true</code>用于在提交和检出时自动转换换行符，选项有三个</p>
<ul>
<li><code>true</code>提交时转换为LF，检出时转换为CRLF</li>
<li><code>input</code>提交时转换为LF，检出时不转换</li>
<li><code>false</code>提交检出均不转换</li>
</ul>
<p>git使用 <code>git config --global core.safecrlf true</code> 用于检查文件是否包含混合换行符，该配置也有三个可选项：</p>
<ul>
<li><code>true</code> 禁止提交混合换行符的文本文件(git add 的时候会被拦截，提示异常)</li>
<li><code>warn</code> 提交混合换行符的文本文件的时候发出警告，但是不会阻止 git add 操作</li>
<li><code>false</code> 不禁止提交混合换行符的文本文件（默认配置）</li>
</ul>
<h4 id="解决方法" tabindex="-1">解决方法 <a class="header-anchor" href="#解决方法" aria-label="Permalink to &quot;解决方法&quot;">&ZeroWidthSpace;</a></h4>
<p>直接无视然后提交，两个属性都设为<code>false</code>不转换不警告，这样会造成换行符混乱，diff可能会失效<br>
一种规范换行符的方式是这样的：<br>
使用 Windows 系统的开发者设置：<code>git config --global core.aurocrlf true</code><br>
使用 Linux/MacOS 的开发者设置：<code>git config --global core.autocrlf input</code></p>
<h3 id="大小写问题" tabindex="-1">大小写问题 <a class="header-anchor" href="#大小写问题" aria-label="Permalink to &quot;大小写问题&quot;">&ZeroWidthSpace;</a></h3>
<p>git在win和mac上是不区分大小写的，linux上区分。使用<code>git config --get core.ignorecase</code>查看为true，<code>git config core.ignorecase false</code>设置之后就区分了。</p>
<ol>
<li>新建test文件(大小写不敏感的状态)并提交</li>
<li>本地修改test变为Test，文件内容无变更，无法检测到变动</li>
<li>设置大小写敏感后push，此时远程仓库会存在大小写同时存在的文件，但本地仓库却只看到其中一个文件</li>
<li>甚至可能出现本地暂存区的文件怎么删也删不掉,再之后从test尝试改为Test提示命名冲突</li>
</ol>
<p>如果项目还没开始，提前设置大小写敏感。如果是已有的项目先执行命令再改名<br>
git项目中文件夹/文件的路径，很多时候就代表了网站地址、页面url的路径。而<strong>网站地址也是不区分大小写的</strong>，这可能是git这么做的关键的原因之一</p>
<h3 id="离线同步git" tabindex="-1">离线同步git <a class="header-anchor" href="#离线同步git" aria-label="Permalink to &quot;离线同步git&quot;">&ZeroWidthSpace;</a></h3>
<p>问题场景:
目前可以用的解决方案:<br>
在git的服务器服务端的仓库repo.git，复制到离线的服务器，假设放在<code>/dev/repo.git</code>。<br>
在服务器项目目录先clone一下<code>git clone /dev/repo.git</code>，如果是一个新的repo，有可能分支不对，克隆完是空的。<br>
进入目录，如果分支对不上且目录是空的，需要手动同步过来。</p>
<p>也有git patch 然后apply commit，和git bundle</p>
<p>使用ssh进行repo的隧道转发代理，相当于吧ssh做了网络代理，注意合不合规</p>
<h3 id="停止对某文件跟踪" tabindex="-1">停止对某文件跟踪 <a class="header-anchor" href="#停止对某文件跟踪" aria-label="Permalink to &quot;停止对某文件跟踪&quot;">&ZeroWidthSpace;</a></h3>
<p>现在有个需求是每个平台的config文件的配置是不一样的，想要从git中将此文件取消跟踪，手动置换机器中的此文件(其实开不一样的分支就行，但是开分支也怪麻烦的)<br>
在全内网的环境下是无法进行git同步的，这种情况下与其复制过去再修改不如新建分支，每次是把main分支的代码往上合，到时候直接把这个分支的代码复制过去就可以跑了</p>
<p><strong><code>git rm --cached 文件名</code></strong> 停止对git已跟踪的文件跟踪，但保留之前该文件的跟踪状态</p>
<blockquote>
<p>在一个分支下开发，这种做法是没有问题的。即在 master 分支里，使用如上操作之后，config.js 就从 git 管理中剔除了，但是仍然存在于硬盘上。并不会影响到本地开发环境的正常调试。<br>
如果同时满足以下条件的情况下就会出问题<br>
1 多分支同时存在 config.php 文件。例如，master 分支，dev 分支都有 config.php 文件<br>
2 一个分支删除了该文件，然后在另一个分支，merge 了该提交<br>
这时候dev和master分支的config.js就全消失了。</p>
</blockquote>
<p><strong><code>git update-index --assume-unchanged 文件名</code></strong> 暂时让git忽略已跟踪的文件,具体看<a href='https://segmentfault.com/q/1010000000430426'>这一篇</a></p>
<blockquote>
<p>虽然能达到（暂时的）目的，但并非最正确的做法，这样做是误解了 git update-index 的含义，而且这样做带来的最直接（不良）后果是这样的：</p>
<p>1 所有的团队成员都必须对目标文件执行：git update-index --assume-unchanged PATH。这是因为即使你让 Git 假装看不见目标文件的改变，但文件本身还是在 Git 的历史记录里的，所以团队的每个人在 fetch 的时候都会拉到目标文件的变更。（但实际上目标文件是根本不想被 Git 记录的，而不是假装看不见它发生了改变）</p>
<p>2 一旦有人改变目标文件之后没有 git update-index --assume-unchanged PATH 就直接 push 了，那么接下来所有拉取了最新代码的成员必须重新执行 update-index，否则 Git 又会开始记录目标文件的变化。这一点实际上很常见的，比如说某成员换了机器或者硬盘，重新 clone 了一份代码库，由于目标文件还在 Git 的历史记录里，所以他／她很可能会忘记 update-index。</p>
</blockquote>
<blockquote>
<p><strong>git update-index --assume-unchanged</strong> 的真正用法是这样的：<br>
1 你正在修改一个巨大的文件，你先对其 <code>git update-index --assume-unchanged</code>，这样 Git 暂时不会理睬你对文件做的修改；<br>
2 当你的工作告一段落决定可以提交的时候，重置改标识：<br>
<code>git update-index --no-assume-unchanged</code>，于是 Git 只需要做一次更新，这是完全可以接受的了；<br>
3 提交＋推送。</p>
</blockquote>
<hr>
<h2 id="perforcep4" tabindex="-1">PerforceP4 <a class="header-anchor" href="#perforcep4" aria-label="Permalink to &quot;PerforceP4&quot;">&ZeroWidthSpace;</a></h2>
<hr>
<h2 id="svn" tabindex="-1">SVN <a class="header-anchor" href="#svn" aria-label="Permalink to &quot;SVN&quot;">&ZeroWidthSpace;</a></h2>
<hr>
<h2 id="踩坑-1" tabindex="-1">踩坑 <a class="header-anchor" href="#踩坑-1" aria-label="Permalink to &quot;踩坑&quot;">&ZeroWidthSpace;</a></h2>
<h3 id="网关限制文件大小" tabindex="-1">网关限制文件大小 <a class="header-anchor" href="#网关限制文件大小" aria-label="Permalink to &quot;网关限制文件大小&quot;">&ZeroWidthSpace;</a></h3>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>$ git push</span></span>
<span class="line"><span>Enumerating objects: 4, done.</span></span>
<span class="line"><span>Counting objects: 100% (4/4), done.</span></span>
<span class="line"><span>Delta compression using up to 12 threads</span></span>
<span class="line"><span>Compressing objects: 100% (3/3), done.</span></span>
<span class="line"><span>error: RPC failed; HTTP 413 curl 22 The requested URL returned error: 413</span></span>
<span class="line"><span>send-pack: unexpected disconnect while reading sideband packet</span></span>
<span class="line"><span>Writing objects: 100% (3/3), 483.05 MiB | 43.82 MiB/s, done.</span></span>
<span class="line"><span>Total 3 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)</span></span>
<span class="line"><span>fatal: the remote end hung up unexpectedly</span></span>
<span class="line"><span>Everything up-to-date</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br></div></div><p>注意<code>error: RPC failed; HTTP 413 curl 22 The requested URL returned error: 413 send-pack: unexpected disconnect while reading sideband packet</code>说明某一层网关或者gitea自己的网关发送文件包太大了，断开连接。在nginx的<code>server</code>块里添加<code>client_max_body_size 2g;</code>更改一次性接受文件大小</p>
<hr class="footnotes-sep">
<section class="footnotes">
<ol class="footnotes-list">
<li id="fn1" class="footnote-item"><p><a href="https://www.bilibili.com/video/BV16M411z7uH" target="_blank" rel="noreferrer">git分支详解（约10分钟掌握分支80%操作），git-branch，git分支管理，git分支操作，git分支基础和操作，2023年git基础使用教程_哔哩哔哩_bilibili</a> <a href="#fnref1" class="footnote-backref">↩︎</a></p>
</li>
<li id="fn2" class="footnote-item"><p><a href="https://sampwood.github.io/2019/01/07/git%E5%A4%9A%E5%B9%B3%E5%8F%B0%E6%8D%A2%E8%A1%8C%E7%AC%A6%E9%97%AE%E9%A2%98-LF-CRLF/" target="_blank" rel="noreferrer">git多平台换行符问题(LF/CRLF) - Sampwood的One Piece</a><br/> <a href="#fnref2" class="footnote-backref">↩︎</a></p>
</li>
</ol>
</section>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[开源协议]]></title>
            <link>http://ooowl.fun/blogs/%E4%BB%A3%E7%A0%81%E4%B9%8B%E5%A4%96/%E5%BC%80%E6%BA%90%E5%8D%8F%E8%AE%AE.html</link>
            <guid isPermaLink="false">http://ooowl.fun/blogs/%E4%BB%A3%E7%A0%81%E4%B9%8B%E5%A4%96/%E5%BC%80%E6%BA%90%E5%8D%8F%E8%AE%AE.html</guid>
            <pubDate>Sun, 12 May 2019 12:09:05 GMT</pubDate>
            <content:encoded><![CDATA[<h1 id="开源协议" tabindex="-1">开源协议 <a class="header-anchor" href="#开源协议" aria-label="Permalink to &quot;开源协议&quot;">&ZeroWidthSpace;</a></h1><p class="article-meta">创建于 2019年5月12日 20:09:05 · 约2,081字</p>
<h2 id="开源协议-1" tabindex="-1">开源协议 <a class="header-anchor" href="#开源协议-1" aria-label="Permalink to &quot;开源协议&quot;">&ZeroWidthSpace;</a></h2>
<p>^ba2714</p>
<p>先上图</p>
<div class="language-mermaid vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">mermaid</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">graph TD</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    A["他人修改源码后，是否可以闭源？"] -->|No| B["新增代码是否采用同样许可证？"]</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    A -->|Yes| C["每一个修改过的文件，是否都必须放置版权说明？"]</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    B -->|No| D["是否需要对源码的修改之处提供说明文档？"]</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    B -->|Yes| E[LGPL许可证]</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    D -->|No| F[GPL许可证]</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    D -->|Yes| G[Mozilla许可证]</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    C -->|Yes| H["是否可以用你的名字促销？"]</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    C -->|No| I["是否需要对源码的衍生软件的广告说明？"]</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    H -->|Yes| J[MIT许可证]</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    H -->|No| K[BSD许可证]</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    I -->|Yes| L[Apache许可证]</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    I -->|No| M[BSD许可证]</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    style A fill:#f9f,stroke:#333,stroke-width:2px</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br></div></div><p><img src="./static/开源协议_images_1.svg" alt=""></p>
<h2 id="bsd开源协议" tabindex="-1">BSD开源协议 <a class="header-anchor" href="#bsd开源协议" aria-label="Permalink to &quot;BSD开源协议&quot;">&ZeroWidthSpace;</a></h2>
<p>^4fd49b</p>
<p>BSD开源协议是一个给于使用者很大自由的协议。基本上使用者可以”为所欲为”,可以自由的使用，修改源代码，也可以将修改后的代码作为开源或者专有软件再发布。</p>
<p>但”为所欲为”的前提当你发布使用了BSD协议的代码，或则以BSD协议代码为基础做二次开发自己的产品时，需要满足三个条件：</p>
<ul>
<li>如果再发布的产品中包含源代码，则在源代码中必须带有原来代码中的BSD协议</li>
<li>如果再发布的只是二进制类库/软件,则需要在类库/软件的文档和版权声明中包含原来代码中的BSD协议</li>
<li>不可以用开源代码的作者/机构名字和原来产品的名字做市场推广</li>
</ul>
<p>BSD 代码鼓励代码共享，但需要尊重代码作者的著作权。BSD由于允许使用者修改和重新发布代码，也允许使用或在BSD代码上开发商业软件发布和销售，因此是对商业集成很友好的协议。而很多的公司企业在选用开源产品的时候都首选BSD协议，因为可以完全控制这些第三方的代码，在必要的时候可以修改或者二次开发。</p>
<h2 id="apache-licence-2-0" tabindex="-1">Apache Licence 2.0 <a class="header-anchor" href="#apache-licence-2-0" aria-label="Permalink to &quot;Apache Licence 2.0&quot;">&ZeroWidthSpace;</a></h2>
<p>Apache Licence是著名的非盈利开源组织Apache采用的协议。该协议和BSD类似，同样鼓励代码共享和尊重原作者的著作权，同样允许代码修改，再发布（作为开源或商业软件）。需要满足的条件也和BSD类似：</p>
<ul>
<li>需要给代码的用户一份Apache Licence</li>
<li>如果你修改了代码，需要再被修改的文件中说明。</li>
<li>在延伸的代码中（修改和有源代码衍生的代码中）需要带有原来代码中的协议，商标，专利声明和其他原来作者规定需要包含的说明。</li>
<li>如果再发布的产品中包含一个Notice文件，则在Notice文件中需要带有Apache Licence。你可以在Notice中增加自己的许可，但不可以表现为对Apache Licence构成更改。</li>
</ul>
<p>Apache Licence也是对商业应用友好的许可。使用者也可以在需要的时候修改代码来满足需要并作为开源或商业产品发布/销售。</p>
<h2 id="gpl" tabindex="-1">GPL <a class="header-anchor" href="#gpl" aria-label="Permalink to &quot;GPL&quot;">&ZeroWidthSpace;</a></h2>
<p>^b38a21</p>
<p>我们很熟悉的Linux就是采用了GPL。GPL协议和BSD, Apache Licence等鼓励代码重用的许可很不一样。GPL的出发点是代码的开源/免费使用和引用/修改/衍生代码的开源/免费使用，但不允许修改后和衍生的代码做为闭源的商业软件发布和销售。<br>
这也就是为什么我们能用免费的各种linux，包括商业公司的linux和linux上各种各样的由个人，组织，以及商业软件公司开发的免费软件了。</p>
<p>GPL协议的主要内容是只要在一个软件中使用(”使用”指类库引用，修改后的代码或者衍生代码)GPL 协议的产品，则该软件产品必须也采用GPL协议，既必须也是开源和免费。这就是所谓的”传染性”。GPL协议的产品作为一个单独的产品使用没有任何问题，还可以享受免费的优势。</p>
<p>由于GPL严格要求使用了GPL类库的软件产品必须使用GPL协议，对于使用GPL协议的开源代码，商业软件或者对代码有保密要求的部门就不适合集成/采用作为类库和二次开发的基础。</p>
<p>其它细节如再发布的时候需要伴随GPL协议等和BSD/Apache等类似。</p>
<h2 id="lgpl" tabindex="-1">LGPL <a class="header-anchor" href="#lgpl" aria-label="Permalink to &quot;LGPL&quot;">&ZeroWidthSpace;</a></h2>
<p>LGPL是GPL的一个为主要为类库使用设计的开源协议。和GPL要求任何使用/修改/衍生之GPL类库的的软件必须采用GPL协议不同。LGPL 允许商业软件通过类库引用(link)方式使用LGPL类库而不需要开源商业软件的代码。这使得采用LGPL协议的开源代码可以被商业软件作为类库引用并发布和销售。</p>
<p>但是如果修改LGPL协议的代码或者衍生，则所有修改的代码，涉及修改部分的额外代码和衍生的代码都必须采用LGPL协议。因此LGPL协议的开源代码很适合作为第三方类库被商业软件引用，但不适合希望以LGPL协议代码为基础，通过修改和衍生的方式做二次开发的商业软件采用。</p>
<p>GPL/LGPL都保障原作者的知识产权，避免有人利用开源代码复制并开发类似的产品</p>
<h2 id="mit" tabindex="-1">MIT <a class="header-anchor" href="#mit" aria-label="Permalink to &quot;MIT&quot;">&ZeroWidthSpace;</a></h2>
<p>MIT是和BSD一样宽范的许可协议,作者只想保留版权,而无任何其他了限制.也就是说,你必须在你的发行版里包含原许可协议的声明,无论你是以二进制发布的还是以源代码发布的.</p>
<h2 id="mpl" tabindex="-1">MPL <a class="header-anchor" href="#mpl" aria-label="Permalink to &quot;MPL&quot;">&ZeroWidthSpace;</a></h2>
<p>MPL是The Mozilla Public License的简写，是1998年初Netscape的 Mozilla小组为其开源软件项目设计的软件许可证。MPL许可证出现的最重要原因就是，Netscape公司认为GPL许可证没有很好地平衡开发者对源代码的需求和他们利用源代码获得的利益。同著名的GPL许可证和BSD许可证相比，MPL在许多权利与义务的约定方面与它们相同（因为都是符合OSIA 认定的开源软件许可证）。但是，相比而言MPL还有以下几个显著的不同之处:</p>
<ul>
<li>MPL虽然要求对于经MPL许可证发布的源代码的修改也要以MPL许可证的方式再许可出来，以保证其他人可以在MPL的条款下共享源代码。但是，在MPL 许可证中对“发布”的定义是“以源代码方式发布的文件”，这就意味着MPL允许一个企业在自己已有的源代码库上加一个接口，除了接口程序的源代码以MPL 许可证的形式对外许可外，源代码库中的源代码就可以不用MPL许可证的方式强制对外许可。这些，就为借鉴别人的源代码用做自己商业软件开发的行为留了一个豁口。</li>
<li>MPL许可证第三条第7款中允许被许可人将经过MPL许可证获得的源代码同自己其他类型的代码混合得到自己的软件程序。</li>
<li>对软件专利的态度，MPL许可证不像GPL许可证那样明确表示反对软件专利，但是却明确要求源代码的提供者不能提供已经受专利保护的源代码（除非他本人是专利权人，并书面向公众免费许可这些源代码），也不能在将这些源代码以开放源代码许可证形式许可后再去申请与这些源代码有关的专利。</li>
<li>对源代码的定义，在MPL（1.1版本）许可证中，对源代码的定义是:“源代码指的是对作品进行修改最优先择取的形式，它包括:所有模块的所有源程序，加上有关的接口的定义，加上控制可执行作品的安装和编译的‘原本’（原文为‘Script’），或者不是与初始源代码显著不同的源代码就是被源代码贡献者选择的从公共领域可以得到的程序代码。”</li>
<li>MPL许可证第3条有专门的一款是关于对源代码修改进行描述的规定，就是要求所有再发布者都得有一个专门的文件就对源代码程序修改的时间和修改的方式有描述。</li>
</ul>
<h2 id="参考" tabindex="-1">参考: <a class="header-anchor" href="#参考" aria-label="Permalink to &quot;参考:&quot;">&ZeroWidthSpace;</a></h2>
<p><a href="http://www.ruanyifeng.com/blog/2011/05/how_to_choose_free_software_licenses.html" target="_blank" rel="noreferrer">阮一峰的网络日志</a><br>
<a href="https://blog.csdn.net/testcs_dn/article/details/38496107" target="_blank" rel="noreferrer">另一个吊人的博客</a><br>
<a href="https://www.mozilla.org/en-US/MPL/1.1/" target="_blank" rel="noreferrer">mozill原文</a></p>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Py自动化办公]]></title>
            <link>http://ooowl.fun/blogs/Python/%E8%AF%AD%E6%B3%95%E5%92%8C%E5%BA%93/Py%E8%87%AA%E5%8A%A8%E5%8C%96%E5%8A%9E%E5%85%AC.html</link>
            <guid isPermaLink="false">http://ooowl.fun/blogs/Python/%E8%AF%AD%E6%B3%95%E5%92%8C%E5%BA%93/Py%E8%87%AA%E5%8A%A8%E5%8C%96%E5%8A%9E%E5%85%AC.html</guid>
            <pubDate>Tue, 01 Jan 2019 20:37:45 GMT</pubDate>
            <content:encoded><![CDATA[<h1 id="py自动化办公" tabindex="-1">Py自动化办公 <a class="header-anchor" href="#py自动化办公" aria-label="Permalink to &quot;Py自动化办公&quot;">&ZeroWidthSpace;</a></h1><p class="article-meta">创建于 2019年1月2日 04:37:45 · 约146字</p>
<h2 id="pyautogui-的函数" tabindex="-1">PyAutoGUI 的函数 <a class="header-anchor" href="#pyautogui-的函数" aria-label="Permalink to &quot;PyAutoGUI 的函数&quot;">&ZeroWidthSpace;</a></h2>
<p>介绍了许多不同函数，下面是快速的汇总参考<br>
<a href="https://pyautogui.readthedocs.io/en/latest/" target="_blank" rel="noreferrer">文档</a></p>
<div class="warning custom-block"><p class="custom-block-title">[⚠️Warning]</p>
<p>pyautogui.FAILSAFE=False#关闭文件安全
记得引入pythoncom</p>
</div>
<h3 id="速览cheatsheet" tabindex="-1">速览Cheatsheet <a class="header-anchor" href="#速览cheatsheet" aria-label="Permalink to &quot;速览Cheatsheet&quot;">&ZeroWidthSpace;</a></h3>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> pyautogui</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">screenWidth, screenHeight </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> pyautogui.size() </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 获取当前屏幕分辨率</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">currentMouseX, currentMouseY </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> pyautogui.position() </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 获取当前鼠标位置</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">pyautogui.doubleClick() </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 鼠标双击 </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">pyautogui.moveTo(x,y)</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 将鼠标移动到指定的 x、y 坐标。最左上角为0,0</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">pyautogui.moveRel (xOffset,yOffset)</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 相对于当前位置移动鼠标。</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">pyautogui.dragTo(x,y)</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 按下左键移动鼠标。</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">pyautogui.dragRel(xOffset,yOffset) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 按下左键,相对于当前位置移动鼠标。</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">pyautogui.click(x,y,button,</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">clicks</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">interval</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0.25</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 模拟点击(默认是左键),点两次，间隔0.25s</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">pyautogui.rightClick() </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 模拟右键点击。x=moveToX, y=moveToY</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">pyautogui.middleClick() </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 模拟中键点击。x=moveToX, y=moveToY</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">pyautogui.doubleClick() </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 模拟左键双击。x=moveToX, y=moveToY</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">pyautogui.mouseDown(x,y,button)</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 模拟在 x、y 处按下指定鼠标按键。</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">pyautogui.mouseUp(x,y,button)</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 模拟在 x、y 处释放指定键。</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">pyautogui.scroll (units)</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 模拟滚动滚轮。正参数表示向上滚动,负参数表示向下滚动。</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br></div></div><h3 id="控制鼠标" tabindex="-1">控制鼠标 <a class="header-anchor" href="#控制鼠标" aria-label="Permalink to &quot;控制鼠标&quot;">&ZeroWidthSpace;</a></h3>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">pyautogui.</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">PAUSE</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 将 pyautogui.PAUSE 设置为 1，即每次函数调用后暂停一秒。</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">pyautogui.</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">FAILSAFE</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">True</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 启动自动防故障功能。</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br></div></div><div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 移动到提供的坐标，每次移动耗时 0.25 秒，</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">pyautogui.moveTo(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">100</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">100</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">duration</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0.25</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)    </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 向右水平移动多少个像素，向下垂直移动多少个像素，以及（可选的）花多少时间完成移动。数值参数若为负，鼠标将向左或向上移动（反方向）</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">pyautogui.moveRel(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">100</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">duration</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0.25</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 按住鼠标左键，把鼠标拖拽到(100, 200)位置</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">pyautogui.dragTo(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">100</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">200</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">button</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'left'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 按住鼠标左键，用2秒钟把鼠标拖拽到(300, 400)位置</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">pyautogui.dragTo(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">300</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">400</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">button</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'left'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 按住鼠标右键，用2秒钟把鼠标拖拽到(30,0)位置</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">pyautogui.dragTo(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">30</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">button</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'right'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br></div></div><h3 id="键盘" tabindex="-1">键盘 <a class="header-anchor" href="#键盘" aria-label="Permalink to &quot;键盘&quot;">&ZeroWidthSpace;</a></h3>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">pyautogui.typewrite(message)</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 键入给定消息字符串中的字符。 </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">pyautogui.typewrite([key1,key2,key3])</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 键入给定键字符串。 </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">pyautogui.press(key)按下并释放给定键。</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">pyautogui.keyDown(key)模拟按下给定键。</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">pyautogui.keyUp(key)模拟释放给定键。</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">pyautogui.hotkey([key1,key2,key3])</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 模拟按顺序按下给定键字符串,然后以相反的顺序释放。</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">pyautogui.screenshot() </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 返回屏幕截图的Pillow/PIL的Image对象_对象</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br></div></div><h3 id="弹窗" tabindex="-1">弹窗 <a class="header-anchor" href="#弹窗" aria-label="Permalink to &quot;弹窗&quot;">&ZeroWidthSpace;</a></h3>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">pyautogui.alert(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'这个消息弹窗是文字+OK按钮'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">pyautogui.confirm(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'这个消息弹窗是文字+OK+Cancel按钮'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">pyautogui.prompt(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'这个消息弹窗是让用户输入字符串，单击OK'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 如果用户什么都不输入，返回None</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br></div></div><p><img src="./static/Py自动化办公_images_1.png" alt="|700"></p>
<div class="danger custom-block"><p class="custom-block-title">[🚨Danger]</p>
<p>pyautogui并不能输入中文,他的输入只能模拟某个按键</p>
</div>
<h3 id="使用pyperclip输入中文" tabindex="-1">使用pyperclip输入中文 <a class="header-anchor" href="#使用pyperclip输入中文" aria-label="Permalink to &quot;使用pyperclip输入中文&quot;">&ZeroWidthSpace;</a></h3>
<p>很简单的API</p>
<div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">pyperclip.copy(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"你好呀"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 先复制</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">pyautogui.hotkey(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'ctrl'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'v'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 再粘贴</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br></div></div><h2 id="键盘hook" tabindex="-1">键盘HOOK <a class="header-anchor" href="#键盘hook" aria-label="Permalink to &quot;键盘HOOK&quot;">&ZeroWidthSpace;</a></h2>
<p>关于HOOK 一般使用pyhook3但是pyhook并不支持python3，会出现错误，python3使用扩展库pyhook_py3k，hook不支持python3，pyhook_3k也只支持32位<br>
真没几个好用的，用到的时候再找吧</p>
<h2 id="ocr" tabindex="-1">OCR <a class="header-anchor" href="#ocr" aria-label="Permalink to &quot;OCR&quot;">&ZeroWidthSpace;</a></h2>
<p>Tesseract OCR</p>
<h2 id="自动化办公" tabindex="-1">自动化办公 <a class="header-anchor" href="#自动化办公" aria-label="Permalink to &quot;自动化办公&quot;">&ZeroWidthSpace;</a></h2>
<h3 id="python-office" tabindex="-1">python-office <a class="header-anchor" href="#python-office" aria-label="Permalink to &quot;python-office&quot;">&ZeroWidthSpace;</a></h3>
<p><a href="https://www.bilibili.com/video/BV1pT4y1k7FH" target="_blank" rel="noreferrer">python-office库 </a></p>
<h3 id="原先办公的包" tabindex="-1">原先办公的包 <a class="header-anchor" href="#原先办公的包" aria-label="Permalink to &quot;原先办公的包&quot;">&ZeroWidthSpace;</a></h3>
<p>xlwt xlrd python-ppt python-docx
<a href="https://www.bilibili.com/video/BV1zp4y1H7LZ" target="_blank" rel="noreferrer">python文件处理专题_哔哩哔哩_bilibili</a></p>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[爬虫基础]]></title>
            <link>http://ooowl.fun/blogs/Python/%E7%88%AC%E8%99%AB/%E5%9F%BA%E7%A1%80%E7%88%AC%E8%99%AB.html</link>
            <guid isPermaLink="false">http://ooowl.fun/blogs/Python/%E7%88%AC%E8%99%AB/%E5%9F%BA%E7%A1%80%E7%88%AC%E8%99%AB.html</guid>
            <pubDate>Fri, 13 Jul 2018 14:05:39 GMT</pubDate>
            <description><![CDATA[[💡Tip]]]></description>
            <content:encoded><![CDATA[<h1 id="爬虫基础" tabindex="-1">爬虫基础 <a class="header-anchor" href="#爬虫基础" aria-label="Permalink to &quot;爬虫基础&quot;">&ZeroWidthSpace;</a></h1><p class="article-meta">创建于 2018年7月13日 22:05:39 · 约3,073字</p>
<div class="tip custom-block"><p class="custom-block-title">[💡Tip]</p>
<p>大学的时候 基本知道的爬虫 很乱其实都很简单</p>
</div>
<p>#TODO 重整爬虫
爬虫的本质，是把数据从服务器请求到本地，提取解析出有用的东西，主要是http请求</p>
<p>网页数据的处理</p>
<p>请求的反爬机制和突破</p>
<p>爬虫效率和监控</p>
<ul>
<li>多线程多进程和异步加速效率
<ul>
<li>一般是多线程因为是IO密集型任务</li>
<li>异步生态还不是特别完善</li>
</ul>
</li>
<li>大批量作业分布式爬虫</li>
<li>任务队列和定时</li>
<li>集成fastapi框架
存储到DB</li>
<li>各种存储方案，从队列取出类似pipline的处理</li>
</ul>
<p>uinotes扒站爬虫</p>
<h2 id="爬虫的基本原理" tabindex="-1">爬虫的基本原理 <a class="header-anchor" href="#爬虫的基本原理" aria-label="Permalink to &quot;爬虫的基本原理&quot;">&ZeroWidthSpace;</a></h2>
<p>基本就是三部分</p>
<h3 id="爬虫攻防" tabindex="-1">爬虫攻防 <a class="header-anchor" href="#爬虫攻防" aria-label="Permalink to &quot;爬虫攻防&quot;">&ZeroWidthSpace;</a></h3>
<p>请求就是http，把网页的源码下载到本地(内存)进行访问的，经常用的有urlib(太老一般只用到urljoin)，requests，scrapy(框架)，twisted(异步事件驱动)，aiohttp(异步)
请求一般用get(直接获取资源)post(表单验证)set等后面不常用<br/>这里会涉及到反爬<br/></p>
<ul>
<li>对网站感兴趣,分析网络请求，用scrapy写爬虫爬取数据<br/>
监控发现某个时间段访问陡增，ip相同，userag-ent都是python，直接限制访问（不能封ip）</li>
<li>User-agen模拟firefox，获取ip代理<br/>
发现ip变化，直接要求登录才能访问</li>
<li>注册账号，每次请求带cookie或者token<br/>
健全账号体系，即A只能访问好友的信息</li>
<li>注册多个账号，多个账号联合爬取<br/>
请求过于频繁，进一步加剧ip访问频率限制</li>
<li>模仿人请求，限制请求速度<br/>
弹出验证码，让识别验证码</li>
<li>通过各种手段识别验证码<br/>
增加动态网站，数据通过js动态加载，增加网络分析复杂度，发现大量请求只请求html，不请求image和CSS</li>
<li>通过selenium和phantomjs完全模拟浏览器操作<br/>
12成本太高，放弃了</li>
</ul>
<h3 id="处理" tabindex="-1">处理 <a class="header-anchor" href="#处理" aria-label="Permalink to &quot;处理&quot;">&ZeroWidthSpace;</a></h3>
<p>BS4,pyQuery,lxml等解析DOM和文件涉及到寻找属性定位xpath,seletor,css定位
最后产生一个自己想要的数据结构</p>
<h3 id="存储" tabindex="-1">存储 <a class="header-anchor" href="#存储" aria-label="Permalink to &quot;存储&quot;">&ZeroWidthSpace;</a></h3>
<p>拿到这个结构的时候，存到数据库。<br/>
pymysql(推荐),aiomysql(异步),存为文件(FileIO)scrapy的pipline,推送消息等等
twisted+pymysql(手动异步)while+eventloop驱动</p>
<h3 id="去重" tabindex="-1">去重 <a class="header-anchor" href="#去重" aria-label="Permalink to &quot;去重&quot;">&ZeroWidthSpace;</a></h3>
<p>爬虫去重策略</p>
<ol>
<li>将访问过的url保存到数据库中</li>
<li>将访问过的url保存到set中，只需要<em>O</em>(1)的代价就可以查询url极限100000000*2byte*50个字符/1024/1024/1024=9G</li>
<li>url经过md5等方法哈希后保存到set中</li>
<li>用bitmap方法，将访问过的url通过hash函数映射到某一</li>
<li>bloomfilter方法对bitmap进行改进，多重hash函数降低冲突</li>
</ol>
<div class="danger custom-block"><p class="custom-block-title">留坑</p>
<p>布隆过滤器</p>
</div>
<h2 id="请求" tabindex="-1">请求 <a class="header-anchor" href="#请求" aria-label="Permalink to &quot;请求&quot;">&ZeroWidthSpace;</a></h2>
<h3 id="requests" tabindex="-1">requests <a class="header-anchor" href="#requests" aria-label="Permalink to &quot;requests&quot;">&ZeroWidthSpace;</a></h3>
<p>request的基本使用<br/>
返回的是一个
一般post之前要查看一下正常的post有没有加密，要不要重写，</p>
<div class="danger custom-block"><p class="custom-block-title">留坑</p>
<p>js断点调试fiddler抓包</p>
</div>
<h4 id="get-post" tabindex="-1">get()&amp;post() <a class="header-anchor" href="#get-post" aria-label="Permalink to &quot;get()&amp;post()&quot;">&ZeroWidthSpace;</a></h4>
<ol>
<li>get(url,参数),写图片
返回的是一个response对象，包含状态码请求成功与否等等</li>
</ol>
<div class="language-py vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">py</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    data</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">        "name"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"zhizhi"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">        "age"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">20</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    files</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"files"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">open</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"baidu.png"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"rb"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)}</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    res</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">requests.get(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"http://www.httpbin.org/get"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">params</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">data)</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#构造一个参数并传进去</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(res.text)</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#直接返回字符串</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(res.json())</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#直接解析json</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(res.contnet)</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#返回网页原始内容</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(res0.status_code)</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#请求的状态码</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    res0.encoding</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"utf-8"</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#把网页的编码转换</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    res1</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">requests.get(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"https://www.baidu.com/img/bd_logo1.png"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    len</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(res1.content)</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#图片的二进制</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    with</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> open</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"baidu.png"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"wb"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">as</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> f:</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#写二进制图片</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        f.write(res1.content)</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br></div></div><ol start="2">
<li>使用header</li>
</ol>
<div class="language-py vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">py</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">headers</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Referer"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"https://www.zhihu.com/signup?next=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">%2F</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"User-Agent"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">res3</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">requests.get(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"https://www.zhihu.com"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">headers</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">headers)</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#添加headers,像某呼这种不加header就不给访问</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(res3.text)</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br></div></div><ol start="3">
<li>传入文件并使用cookie
<br/>data被传入了cookie中可以访问了</li>
</ol>
<div class="language-py vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">py</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">res4 </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> requests.post(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"http://www.httpbin.org/post"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">data</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">data,</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">headers</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">headers, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">files</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">files)</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 构造一个form并传进去</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">pprint(res4.text)</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(res4.cookies)</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> k,v </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> res4.cookies:</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(k,</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">":"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,v)</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br></div></div><ol start="4">
<li>session维持会话，一般session会很久</li>
</ol>
<div class="language-py vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">py</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">s</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">requests.session()</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#维持会话</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">s.get(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"http://www.httpbin.org/cookies/set/abc/svsvdhasb"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">verify</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">False</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 不进行证书验证，可使用cert=("path/server.crt","path/ket")进行证书验证</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">res5</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">s.get(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"http://www.httpbin.org/cookies"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(res5.text)</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br></div></div><ol start="5">
<li>使用ip代理
常用的代理有西刺也可以自己买</li>
</ol>
<div class="language-py vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">py</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">proxies</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"https"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"127.0.0.1:9900"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#使用代理</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">res6</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">requests.get(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"http://www.httpbin.org/get"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">proxies</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">proxies)</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(res6.content)</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br></div></div><h3 id="selenium" tabindex="-1">selenium <a class="header-anchor" href="#selenium" aria-label="Permalink to &quot;selenium&quot;">&ZeroWidthSpace;</a></h3>
<p>selenium浏览器驱动。<br/>当某些网页动态加载js的时候(淘宝)我们需要程序去执行js，(效率自然会低一些)这就是selenium的作用
phantomjs(无界面浏览器)也行但是在多进程的情况下性能下降严重。
<br/>
使用之前先下载一个driver<a href='https://npm.taobao.org/mirrors/chromedriver/2.34/'>淘宝镜像</a></p>
<div class="language-py vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">py</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> selenium </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> webdriver</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">broswer.get(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'http://www.baidu.com'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#打开</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(broswer.page_source) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 拿到F12的代码(经过渲染的)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">broswer.maximize_window()</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#最大化窗口</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">broswer.set_window_size(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">600</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">800</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#设置窗口大小</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">broswer.back()</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#后退一步</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">broswer.forward()</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#前进一步</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">broswer.refresh()</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#刷新</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(broswer.title)</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#拿到浏览器的标题</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(broswer.current_url)</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#拿到url</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">broswer.get_cookies()</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#拿到cookie</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">broswer.delete_all_cookies()</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#删除所有的cookie</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">broswer.add_cookie({k</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">v})</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#增加cookie</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br></div></div><div class="tip custom-block"><p class="custom-block-title">可用的驱动</p>
<p>webdriver.Firefox<br/>
webdriver.FirefoxProfile<br/>
webdriver.Chrome<br/>
webdriver.ChromeOptions<br/>
webdriver.Ie<br/>
webdriver.Opera<br/>
webdriver.PhantomJS<br/>
webdriver.Remote<br/>
webdriver.DesiredCapabilities<br/>
webdriver.ActionChains<br/>
webdriver.TouchActions<br/></p>
</div>
<h4 id="查找元素" tabindex="-1">查找元素 <a class="header-anchor" href="#查找元素" aria-label="Permalink to &quot;查找元素&quot;">&ZeroWidthSpace;</a></h4>
<p>不建议使用自带的，因为会拖慢速度，性能会变差。<br/>
可以用其他的包lxml bs等代替，不过有时候不能代替</p>
<div class="language-py vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">py</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(broswer.find_element_by_id(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">id_</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"lg"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">))</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><ol>
<li>id定位：find_element_by_id()</li>
<li>name定位：find_element_by_name()</li>
<li>class定位：find_element_by_class()</li>
<li>tag定位：find_element_by_tag_name()</li>
<li>link定位：find_element_by_link_text()</li>
<li>partial link 定位： find_element_by_partial_link_text()</li>
<li>Xpath定位:<br/>
<ul>
<li>绝对路径：find_element_by_xpath(&quot;绝对路径&quot;)</li>
<li>元素属性：find_element_by_xpath(&quot;//unput[@id='kw']&quot;)</li>
<li>层级与属性结合：find_element_by_xpath(&quot;//form[@id='loginForm']/ul/input[1]&quot;)</li>
<li>逻辑运算符：find_element_by_xpath(&quot;//input[@id='kw' and@class='s_ipt']&quot;)</li>
</ul>
</li>
<li>CSS定位：find_element_by_css_selector()</li>
</ol>
<h4 id="通过selenium模拟登陆微博" tabindex="-1">通过selenium模拟登陆微博 <a class="header-anchor" href="#通过selenium模拟登陆微博" aria-label="Permalink to &quot;通过selenium模拟登陆微博&quot;">&ZeroWidthSpace;</a></h4>
<div class="danger custom-block"><p class="custom-block-title">失败了 留坑</p>
<p>后面再试，填值的时候填不上</p>
</div>
<h4> 往元素中填值并登陆</h4>
<div class="language-py vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">py</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">ele0</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">broswer.find_element_by_id(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">id_</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"lg"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">ele</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">broswer.find_element_by_id(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">id_</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"kw"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">ele.send_keys(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">u</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"qwe"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#模拟按键输入：</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">ele.clear()</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#清除文本：</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">ele.send_keys(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">u</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"abc"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#模拟按键输入：</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">ele1</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">broswer.find_element_by_class_name(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"bg s_btn"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">ele1.click()</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#单击元素</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">ele1.submit()</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#提交表单（相当于"回车"）</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">broswer.execute_script(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'alert("123");'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#执行js</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br></div></div><p>加载的时候不加载图片(节省性能)，如下设置</p>
<div class="language-py vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">py</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> selenium </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> webdriver</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">chrome_options </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> webdriver.ChromeOptions()</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">prefs </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"profile.managed_default_content_settings.images"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">chrome_options.add_experimental_option(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"prefs"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,prefs)</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">driver </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> webdriver.Chrome(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">chrome_options</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">chrome_options)</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br></div></div><h3 id="aiohttp" tabindex="-1">aiohttp <a class="header-anchor" href="#aiohttp" aria-label="Permalink to &quot;aiohttp&quot;">&ZeroWidthSpace;</a></h3>
<p>异步请求的http库</p>
<div class="danger custom-block"><p class="custom-block-title">留坑</p>
<p>异步等过一两天再整理</p>
</div>
<h2 id="处理-1" tabindex="-1">处理 <a class="header-anchor" href="#处理-1" aria-label="Permalink to &quot;处理&quot;">&ZeroWidthSpace;</a></h2>
<p>数据处理就是把DOM的元素内容拿出来</p>
<h3 id="beautifulsoup" tabindex="-1">BeautifulSoup <a class="header-anchor" href="#beautifulsoup" aria-label="Permalink to &quot;BeautifulSoup&quot;">&ZeroWidthSpace;</a></h3>
<p>对dom进行解析<br/>
from bs4 import BeautifulSoup as BS <br/>
dom例子</p>
<pre><code>      &lt;li id=&quot;note-36396362&quot; data-note-id=&quot;36396362&quot; class=&quot;have-img&quot;&gt;
          &lt;a class=&quot;wrap-img&quot; href=&quot;www.baidu.com&quot; target=&quot;_blank&quot;&gt;
            &lt;img class=&quot;  img-blur-done&quot; src=&quot;//upload-images.jianshu.io/upload_images/12240181-bb9399878eae6ddd?imageMogr2/auto-orient/strip|imageView2/1/w/360/h/240&quot; alt=&quot;120&quot;&gt;
          &lt;/a&gt;
        &lt;div class=&quot;content&quot;&gt;
          &lt;a class=&quot;title&quot; target=&quot;_blank&quot; href=&quot;www.baidu.com&quot;&gt;罗永浩最爱的“软件”下凡了！ 让你体验高效记录的感觉&lt;/a&gt;
          &lt;p class=&quot;abstract&quot;&gt;
            听说锤子又发布了新产品！ 锤子科技不是一个卖手机的好公司，却是一个搞软件的领头军，旗下的闪念胶囊和BigBang一直被赞扬，网友戏称： 锤子有三...
          &lt;/p&gt;
          &lt;div class=&quot;meta&quot;&gt;
            &lt;a class=&quot;nickname&quot; target=&quot;_blank&quot; href=&quot;/u/00385c37e5de&quot;&gt;Tools指南&lt;/a&gt;
              &lt;a target=&quot;_blank&quot; href=&quot;www.baidu.com#comments&quot;&gt;
                &lt;i class=&quot;iconfont ic-list-comments&quot;&gt;&lt;/i&gt; 3
      &lt;/a&gt;      &lt;span&gt;&lt;i class=&quot;iconfont ic-list-like&quot;&gt;&lt;/i&gt; 46&lt;/span&gt;
          &lt;/div&gt;
        &lt;/div&gt;
      &lt;/li&gt;
</code></pre>
<div class="language-py vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">py</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> bs4 </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> BeautifulSoup </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">as</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> BS</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">soup</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">BS(dom,</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'lxml'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#生成了一个soup对象使用unicode编码</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br></div></div><div class="tip custom-block"><p class="custom-block-title">注意指定编码</p>
<p>默认lxml<br/>
BeautifulSoup(markup, &quot;lxml&quot;)速度快<br/>
BeautifulSoup(markup, &quot;html.parser&quot;)系统自带<br/>
BeautifulSoup(markup, &quot;xml&quot;)唯一支持xml<br/>
BeautifulSoup(markup, &quot;html5lib&quot;)生成h5浏览器方式解析</p>
</div>
<p>tag.name标签名称可嵌套soup.head.tittle<br/>
tag.attributes标签后面的属性,可添加或者修改,和字典一样<br/>
多值属性,class最多,每个tag可能用多个css<br/>
其他的rel , rev , accept-charset , headers , accesskey返回一个list非多值属性会返回str<br/>
将tag转换为str的时候多值属性会自动合为由空格隔开的字符串,xml没有多值</p>
<div class="language-py vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">py</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(soup.name,soup.attrs)</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#获取名字和属性</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(soup.find(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">class_</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"meta"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">),</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#获取了class为meta的第一个元素</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">soup.find_all_next(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">class_</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"meta"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">),</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#获这也元素的下一个邻居</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">soup.find_all(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">class_</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"meta"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">))</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#列表获取所有meta的元素</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">tag.parent</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#获得父节点beautifulsoup父节点为None</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">tag.descendants</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#子孙节点的递归迭代对象</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">tag.chlidren</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#是包含子节点对象对象对象的可迭代对象</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br></div></div><table tabindex="0">
<thead>
<tr>
<th>方法</th>
<th style="text-align:center">参数</th>
<th style="text-align:right">返回</th>
</tr>
</thead>
<tbody>
<tr>
<td>find</td>
<td style="text-align:center">(self, name, attrs, recursive, text,.… Tag</td>
<td style="text-align:right">1</td>
</tr>
<tr>
<td>find_all</td>
<td style="text-align:center">(self, name, attrs, recursive, te.. Tag</td>
<td style="text-align:right">2</td>
</tr>
<tr>
<td>find_all_previous</td>
<td style="text-align:center">(self, name, att.. PageElement</td>
<td style="text-align:right">3</td>
</tr>
<tr>
<td>find_next</td>
<td style="text-align:center">(self, name, attrs, text.. PageElement</td>
<td style="text-align:right">4</td>
</tr>
<tr>
<td>find_next_sibling</td>
<td style="text-align:center">(self, name, att.. PageElement</td>
<td style="text-align:right">5</td>
</tr>
<tr>
<td>find_next_siblings</td>
<td style="text-align:center">(self, name, at.. PageElement</td>
<td style="text-align:right">6</td>
</tr>
<tr>
<td>find_parent</td>
<td style="text-align:center">(self, name, attrs, kw.. PageElement</td>
<td style="text-align:right">7</td>
</tr>
<tr>
<td>find_parents</td>
<td style="text-align:center">(self, name, attrs,1.. PageElement</td>
<td style="text-align:right">8</td>
</tr>
<tr>
<td>find_previous</td>
<td style="text-align:center">(self, name, attrs,.. PageElement</td>
<td style="text-align:right">9</td>
</tr>
<tr>
<td>find_previous_sibling</td>
<td style="text-align:center">(self, name,.… PageElement</td>
<td style="text-align:right">10</td>
</tr>
<tr>
<td>find previous siblings</td>
<td style="text-align:center">(self, name.. PageElement</td>
<td style="text-align:right">11</td>
</tr>
</tbody>
</table>
<p>这是节点的一些属性，可以获取内容</p>
<div class="warning custom-block"><p class="custom-block-title">WARNING</p>
<p>注意顿号以及换行也算节点<br/>
class_用来标识css可以部分匹配也可全匹配,全匹配的时候注意顺序若不一样无法匹配</p>
</div>
<div class="language-py vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">py</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(soup.find(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">class_</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"meta"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">),</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#获取了class为meta的第一个元素</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">soup.find_all_next(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">class_</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"meta"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">),</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#获这也元素的下一个邻居</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">soup.find_all(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">class_</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"meta"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">),)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">soup1</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">soup.find(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">name</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'p'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">class_</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"abstract"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#获取标签为p，class="abstract"的元素</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(soup.string)</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#没有子节点的情况下得到字符串</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(soup1.strings)</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#得到多个字符串 列表</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">soup1</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">soup.find(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">name</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"div"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">class_</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"content"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(soup1.contents)</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#节点的元素，是个列表</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">soup.get_text()</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#返回所有的及其孩子的文本</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">soup.prettify()</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#自动对齐补全html</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br></div></div><h3 id="pyquery" tabindex="-1">pyQuery <a class="header-anchor" href="#pyquery" aria-label="Permalink to &quot;pyQuery&quot;">&ZeroWidthSpace;</a></h3>
<p>pip安装pyQuery</p>
<h3>打开</h3>
<p>pq=PyQuery(&quot;<a href="http://www.baidu.com" target="_blank" rel="noreferrer">http://www.baidu.com</a>&quot;)#也可以直接打开文件pq=PyQuery(&quot;aa.html&quot;)</p>
<table tabindex="0">
<thead>
<tr>
<th>类型</th>
<th style="text-align:center">形式</th>
<th style="text-align:right">含义</th>
</tr>
</thead>
<tbody>
<tr>
<td>.class</td>
<td style="text-align:center">.color</td>
<td style="text-align:right">选择class=&quot;color”的所有元素</td>
</tr>
<tr>
<td>#id</td>
<td style="text-align:center">#info</td>
<td style="text-align:right">选择id=&quot;info”的所有元素</td>
</tr>
<tr>
<td>*</td>
<td style="text-align:center">*</td>
<td style="text-align:right">选择所有元素</td>
</tr>
<tr>
<td>element</td>
<td style="text-align:center">p</td>
<td style="text-align:right">选择所有的p元素</td>
</tr>
<tr>
<td>element,element</td>
<td style="text-align:center">div,pe</td>
<td style="text-align:right">选择所有div元素和所有p元素</td>
</tr>
<tr>
<td>elemente lement</td>
<td style="text-align:center">div pe</td>
<td style="text-align:right">选择所有div元素内所有p元素</td>
</tr>
<tr>
<td>[attribute]</td>
<td style="text-align:center">[target]</td>
<td style="text-align:right">选择带有targe属性的所有元素。</td>
</tr>
<tr>
<td>[arrtibute=value]</td>
<td style="text-align:center">[target=_blank]</td>
<td style="text-align:right">选择 target=&quot;_blank”的所有元素</td>
</tr>
</tbody>
</table>
<p>可以使用伪类<br/>
可调用的函数<br/></p>
<ul>
<li>pq.find()#发现标签</li>
<li>pq.parent()#发现标签的父标签</li>
<li>pq.parents()#递归发现父标签</li>
<li>pq.children()#发现子标签</li>
<li>pq.text()#获取所有文本,忽略标签</li>
</ul>
<div class="warning custom-block"><p class="custom-block-title">WARNING</p>
<p>pq本身是具有标签的字符串
pq.html()不含本身的标签</p>
</div>
<p>程序如下<br/></p>
<div class="language-py vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">py</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">使用上面的dom</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">x</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">pq(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'li a'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">pq.find(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'a'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">pq.parent(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'a'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">pq.parents(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'a'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">pq.children(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'a'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(x.attr(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"target"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"_blank"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">))</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(x.attr.target)</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(x.text())</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br></div></div><p>结果</p>
<pre><code>&lt;a class=&quot;wrap-img&quot; href=&quot;www.baidu.com&quot; target=&quot;_blank&quot;&gt;
      &lt;img class=&quot;  img-blur-done&quot; src=&quot;//upload-images.jianshu.io/upload_images/12240181-bb9399878eae6ddd?imageMogr2/auto-orient/strip|imageView2/1/w/360/h/240&quot; alt=&quot;120&quot;/&gt;
    &lt;/a&gt;
  &lt;a class=&quot;title&quot; target=&quot;_blank&quot; href=&quot;www.baidu.com&quot;&gt;罗永浩最爱的“软件”下凡了！ 让你体验高效记录的感觉&lt;/a&gt;
    &lt;a class=&quot;nickname&quot; target=&quot;_blank&quot; href=&quot;/u/00385c37e5de&quot;&gt;Tools指南&lt;/a&gt;
        &lt;a target=&quot;_blank&quot; href=&quot;www.baidu.com#comments&quot;&gt;
          &lt;i class=&quot;iconfont ic-list-comments&quot;/&gt; 3
&lt;/a&gt;
_blank
 罗永浩最爱的“软件”下凡了！ 让你体验高效记录的感觉 Tools指南 3
</code></pre>
<h3 id="xpath-cssselector" tabindex="-1">Xpath&amp;CssSelector <a class="header-anchor" href="#xpath-cssselector" aria-label="Permalink to &quot;Xpath&amp;CssSelector&quot;">&ZeroWidthSpace;</a></h3>
<p>利用这些语法定位dom的元素
F12开发者模式，直接复制注意js渲染会扰乱xpath和css</p>
<p><img src="./static/基础爬虫_images_1.png" alt=""></p>
<h3>Xpath</h3>
<table tabindex="0">
<thead>
<tr>
<th>类型</th>
<th style="text-align:right">形式</th>
</tr>
</thead>
<tbody>
<tr>
<td>article</td>
<td style="text-align:right">选取所有article元素的所有子节点</td>
</tr>
<tr>
<td>/article</td>
<td style="text-align:right">选取根元素article</td>
</tr>
<tr>
<td>article/a</td>
<td style="text-align:right">选取所有属于article的子元素的a元素</td>
</tr>
<tr>
<td>//div</td>
<td style="text-align:right">选取所有div子元素（不论出现在文档任何地方）</td>
</tr>
<tr>
<td>article//div</td>
<td style="text-align:right">选取所有属于article元素的后代的div元素，不管它出现在article之下的任何位置</td>
</tr>
<tr>
<td>//@class</td>
<td style="text-align:right">选区这个标签下所有名为class的属性</td>
</tr>
<tr>
<td>/a[@href=&quot;link2.html&quot;]</td>
<td style="text-align:right">选取所有href为&quot;link2.html&quot;的a标签</td>
</tr>
<tr>
<td>@href</td>
<td style="text-align:right">拿到href标签</td>
</tr>
<tr>
<td>?/text()</td>
<td style="text-align:right">?元素下的文本</td>
</tr>
</tbody>
</table>
<h3>css选择器</h3>
<table tabindex="0">
<thead>
<tr>
<th>类型</th>
<th style="text-align:right">形式</th>
</tr>
</thead>
<tbody>
<tr>
<td>*</td>
<td style="text-align:right">选择所有节点</td>
</tr>
<tr>
<td>#container</td>
<td style="text-align:right">选择id为container的节点</td>
</tr>
<tr>
<td>.container</td>
<td style="text-align:right">选取所有class包含container的节点</td>
</tr>
<tr>
<td>li a</td>
<td style="text-align:right">选取所有i下的所有a节点</td>
</tr>
<tr>
<td>ul+p</td>
<td style="text-align:right">选择l后面的第一个p元素</td>
</tr>
<tr>
<td>div#container&gt;ul</td>
<td style="text-align:right">选取id为container的div的第一个ul子元素</td>
</tr>
<tr>
<td>ul~p</td>
<td style="text-align:right">选取与ul相邻的所有p元素</td>
</tr>
<tr>
<td>a[title]</td>
<td style="text-align:right">选取所有有title属性的a元素</td>
</tr>
<tr>
<td>a[href=&quot;http:/jobbole.com&quot;]</td>
<td style="text-align:right">选取所有href属性为jobbole.com值的a元素</td>
</tr>
<tr>
<td>a[href*=&quot;jobole&quot;]</td>
<td style="text-align:right">选取所有href属性包含jobbole的a元素</td>
</tr>
<tr>
<td>a[href^=&quot;http&quot;]</td>
<td style="text-align:right">选取所有href属性值以http开头的a元素</td>
</tr>
<tr>
<td>a[href$=&quot;.jpg”]</td>
<td style="text-align:right">选取所有href属性值以.jpg结尾的a元素</td>
</tr>
<tr>
<td>input[type=radio]:checked</td>
<td style="text-align:right">选择选中的radio的元素</td>
</tr>
<tr>
<td>div:not(#container)</td>
<td style="text-align:right">选取所有id非container的div属性</td>
</tr>
<tr>
<td>li:nth-child(3)</td>
<td style="text-align:right">选取第三个i元素</td>
</tr>
<tr>
<td>tr:nth-child(2n)</td>
<td style="text-align:right">第偶数个tr</td>
</tr>
<tr>
<td>a::text</td>
<td style="text-align:right">拿到标签的文本</td>
</tr>
<tr>
<td>a::attr(href)</td>
<td style="text-align:right">拿到标签href属性</td>
</tr>
</tbody>
</table>
<div class="language-py vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">py</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> lxml </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> etree</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">html</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">etree.HTML(dom)</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#初始化，也可初始化本地网页etree.parse('test.html')</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">result </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> etree.tostring(html)</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#放入lxml中</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">result.decode(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"utf-8"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#对这个html进行编码</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">x</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">html.xpath(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'//div[@class="content"]/text()'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(x)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">y</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">html.cssselect(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'#note-36396362 > div >.title'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#拿到所有class为title的元素</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> y:</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#是个列表</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(i.text,i.attrib[</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'href'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">])</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br></div></div><div class="danger custom-block"><p class="custom-block-title">注意</p>
<p>空格和换行符也算一个文本，看结果</p>
</div>
<p>结果</p>
<pre><code>['\n  听说锤子又发布了新产品！ 锤子科技不是一个卖手机的好公司，
却是一个搞软件的领头军，旗下的闪念胶囊和BigBang一直被赞扬，网友戏称：
锤子有三...\n    ', '\n    ', '\n    ', '\n  ']
罗永浩最爱的“软件”下凡了！ 让你体验高效记录的感觉 
www.baidu.com
</code></pre>
<h2 id="存储-1" tabindex="-1">存储 <a class="header-anchor" href="#存储-1" aria-label="Permalink to &quot;存储&quot;">&ZeroWidthSpace;</a></h2>
<h3 id="pymysql" tabindex="-1">pymysql <a class="header-anchor" href="#pymysql" aria-label="Permalink to &quot;pymysql&quot;">&ZeroWidthSpace;</a></h3>
<ul>
<li>创建连接
参数如下
<img src="./static/基础爬虫_images_2.png" alt="800"></li>
<li>创建游标<br/>
可选择字典形式<br/></li>
<li>构造sql语句<br/>
善用str.format<br/></li>
<li>执行sql<br/>
注意错误回滚<br/></li>
<li>拿回结果<br/>
注意指针的位置<br/></li>
</ul>
<div class="language-py vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">py</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> pymysql</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">conn</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">pymysql.connect(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">host</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'127.0.0.1'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">                    user</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'root'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">                    password</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'不给看！！！'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">                    database</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'aiosql'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">                    charset</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'utf8mb4'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">cur</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">conn.cursor(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">cursor</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">pymysql.cursors.DictCursor)</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#使用DictCursor返回不再是元组是一个代映射的字典</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">sql</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'select * from aio'</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">try</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    reslen</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">cur.execute(sql)</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#执行sql语句</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    conn.commit()</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#注意要提交</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">except</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#发生错误</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    conn.rollback()</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#回滚</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    cur.close()</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    conn.close()</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#关闭</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#行为单位移动</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">cur.description</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#光标详情描述</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(cur.lastrowid)</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#光标</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">cur.scroll(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">mode</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'absolute'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#指针指向第二条</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">cur.scroll(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">mode</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'relative'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#指针相对向后移动两条</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">one</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">cur.fetchone()</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#结果的一条光标后移1</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">all</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">cur.fetchmany(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#拿出三条后移3</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">many</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">cur.fetchall()</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#拿出三条，移到底</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(one,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">all</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,many)</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br></div></div><div class="danger custom-block"><p class="custom-block-title">有坑</p>
<p>插入数据库要保证健壮性，特殊字符提前处理比如去掉单引号，反斜杠，编码字符等<br/>
四字节字符入库时\xF0\x9F\x99\x8F像这样 <br/>
首先修改 my.ini 编码集为utf8mb4 数据库和表改为utf8mb4<br/>
还不行的话删库重新新建选择字符集utf8mb4<br/>
连接数据库的时候改为utf8mb4重启mysqld服务</p>
</div>
<h3 id="pymongo" tabindex="-1">PyMongo <a class="header-anchor" href="#pymongo" aria-label="Permalink to &quot;PyMongo&quot;">&ZeroWidthSpace;</a></h3>
<p><strong><em>pip install pymongo</em></strong><br/>
mongo的操作看<a href='/blog/back/数据相关.html#mongodb'>这里</a></p>
<h4>连接</h4>
<p>简写(默认连接本地)<br/>
client=MongoClient()<br/>
指定端囗和地址<br/>
client=MongoClient(localhost，27017)<br/>
使用URI <br/>
client=MongoClient(mongodb://localhost：27017/&quot;)<br/>
client.PORT,client.HOST,client.list_database_names()<br>
db=client.mydb # 使用mydb，没有就自动创建<br/>
myset=db.my_set<br></p>
<div class="tip custom-block"><p class="custom-block-title">关闭</p>
<p>关闭数据库的时候调用client.close()之后仍然能使用属性，比如在打印一次也能打印出来，yinweimongo默认有个连接池，只要没满随时都能连</p>
</div>
<h4>增删改查</h4>
<ul>
<li>插入<br/>
<strong> <em>my_set.insert([{&quot;name&quot;:&quot;zhangsan&quot;,&quot;age&quot;:18},{&quot;name&quot;:&quot;lilin&quot;,&quot;age&quot;:18}])</em> </strong><br/>
<strong> <em>my_set.save({&quot;name&quot;:&quot;zhangsan&quot;,&quot;age&quot;:18})</em> </strong><br>
save的时候他会遍历，但是insert不会，所以insert快一些<br/></li>
<li>查询这个集合所有的数据(需要用for遍历)
<strong> <em>my_set.find()</em> </strong><br></li>
<li>查找名字为zhangsan的数据(需要用for遍历)<br/>
<strong> <em>my_set.find({&quot;name&quot;:&quot;zhangsan&quot;})</em> </strong><br></li>
<li>取出这条记录的'id'依此类推可以往后取<br>
<strong> <em>id=my_set.find({&quot;name&quot;:&quot;zhangsan&quot;})<br/>['id']</em> </strong><br></li>
<li>移除这个记录的id<br>
<strong> <em>my_set.remove(id)</em> </strong><br></li>
<li>把name为zhangsan的age改为20<br/>
<strong> <em>my_set.update({&quot;name&quot;:&quot;zhangsan&quot;},{'$set':{&quot;age&quot;:20}})</em> </strong><br></li>
<li>移除张三这个数据的全部记录<br>
<strong> <em>my_set.remove({'name': 'zhangsan'})</em> </strong><br></li>
<li>删掉这个库<br/>
<strong> <em>db.remove()</em> </strong><br></li>
</ul>
<h4>操作和查询符</h4>
<ol>
<li>查询符
<ul>
<li>&gt;  大于 - $gt</li>
<li>&lt;  小于 - $lt</li>
<li>&gt;=  大于等于 - $gte</li>
<li>&lt;=  小于等于 - $lte</li>
</ul>
</li>
</ol>
<ul>
<li>age大于25的记录
<strong> <em>my_set.find({&quot;age&quot;:{&quot;$gt&quot;:25}})</em> </strong><br></li>
</ul>
<ol start="2">
<li>类型判断<br/>
发现字符串类型的name<br/>
<strong> <em>my_set.find({'name':{'$type':2}})</em> </strong><br></li>
</ol>
<div align=center>类型对照表<br></div><br>
<table tabindex="0">
<thead>
<tr>
<th>类型</th>
<th style="text-align:right">码</th>
</tr>
</thead>
<tbody>
<tr>
<td>Double</td>
<td style="text-align:right">类型代码 1</td>
</tr>
<tr>
<td>String</td>
<td style="text-align:right">类型代码 2</td>
</tr>
<tr>
<td>Object</td>
<td style="text-align:right">类型代码 3</td>
</tr>
<tr>
<td>Array</td>
<td style="text-align:right">类型代码 4</td>
</tr>
<tr>
<td>Binary data</td>
<td style="text-align:right">类型代码 5</td>
</tr>
<tr>
<td>Boolean</td>
<td style="text-align:right">类型代码 8</td>
</tr>
<tr>
<td>Date</td>
<td style="text-align:right">类型代码 9</td>
</tr>
<tr>
<td>Null</td>
<td style="text-align:right">类型代码 10</td>
</tr>
<tr>
<td>Regular Expression</td>
<td style="text-align:right">类型代码 11</td>
</tr>
<tr>
<td>JavaScript</td>
<td style="text-align:right">类型代码 13</td>
</tr>
<tr>
<td>Symbol</td>
<td style="text-align:right">类型代码 14</td>
</tr>
<tr>
<td>JavaScript (with scope)</td>
<td style="text-align:right">类型代码 15</td>
</tr>
<tr>
<td>32-bit integer</td>
<td style="text-align:right">类型代码 16</td>
</tr>
<tr>
<td>Timestamp</td>
<td style="text-align:right">类型代码 17</td>
</tr>
<tr>
<td>64-bit integer</td>
<td style="text-align:right">类型代码 18</td>
</tr>
<tr>
<td>Min key</td>
<td style="text-align:right">类型代码 255</td>
</tr>
<tr>
<td>Max key</td>
<td style="text-align:right">类型代码 127</td>
</tr>
</tbody>
</table>
<ol start="3">
<li>条件查询</li>
</ol>
<div class="language- vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>- 排序&#x3C;br/></span></span>
<span class="line"><span>age升序查询&#x3C;br></span></span>
<span class="line"><span>&#x3C;strong> *my_set.find().sort([("age",1)])* &#x3C;/strong>&#x3C;br></span></span>
<span class="line"><span>- 读取</span></span>
<span class="line"><span>跳过两条之后读六条&#x3C;br/></span></span>
<span class="line"><span>&#x3C;strong> *my_set.find().skip(2).limit(6)* &#x3C;/strong>&#x3C;br></span></span>
<span class="line"><span></span></span>
<span class="line"><span>- in&#x3C;br/></span></span>
<span class="line"><span>发现年龄（20，30，53）中的数据&#x3C;br/></span></span>
<span class="line"><span></span></span>
<span class="line"><span></span></span>
<span class="line"><span>&#x3C;strong> *my_set.find({"age":{"$in":(20,30,35)}})* &#x3C;/strong>&#x3C;br></span></span>
<span class="line"><span>- or&#x3C;br/></span></span>
<span class="line"><span></span></span>
<span class="line"><span>发现age是20或35的数据</span></span>
<span class="line"><span>&#x3C;br/></span></span>
<span class="line"><span></span></span>
<span class="line"><span></span></span>
<span class="line"><span>&#x3C;strong> *my_set.find({"$or":[{"age":20},{"age":35}]})* &#x3C;/strong>&#x3C;br></span></span>
<span class="line"><span>- all&#x3C;br/></span></span>
<span class="line"><span>查询序列的包含&#x3C;br/></span></span>
<span class="line"><span></span></span>
<span class="line"><span>dic = {"name":"xiahong","age":18,"li":[1,2,3]}&#x3C;br/></span></span>
<span class="line"><span>dic2 = {"name":"xiaoming","age":18,"li":[1,2,3,4,5,6]}&#x3C;br/></span></span>
<span class="line"><span></span></span>
<span class="line"><span>&#x3C;strong> *my_set.find({'li':{'$all':[1,2,3,4]}})* &#x3C;/strong>&#x3C;br></span></span>
<span class="line"><span>结果只会出现dic2</span></span>
<span class="line"><span>- push[ALL]</span></span>
<span class="line"><span>更改序列&#x3C;br/></span></span>
<span class="line"><span>单个值: my_set.update({'name':"xiaohong"}, {'$push':{'li':[4]}})&#x3C;br/></span></span>
<span class="line"><span>多个追加: my_set.update({'name':"xiaohong"}, {'$pushAll':{'li':[4,5]}})&#x3C;br/></span></span>
<span class="line"><span>dic = {"name":"xiahong","age":18,"li":[1,2,3,4,4,5]}</span></span>
<span class="line"><span>- pop/pullAll</span></span>
<span class="line"><span>单个值: my_set.update({'name':"xiaohong"}, {'$pop':{'li':[4]}})&#x3C;br/></span></span>
<span class="line"><span>去除多个: my_set.update({'name':"xiaohong"}, {'$pullAll':{'li':[4,5]}})&#x3C;br/></span></span>
<span class="line"><span>dic = {"name":"xiahong","age":18,"li":[1,2,3]}</span></span>
<span class="line"><span>- 多级目录操作&#x3C;br/></span></span>
<span class="line"><span>取的时候用.连接，结果用['字典调用']方式连接&#x3C;br/></span></span>
<span class="line"><span>查找a属性的b属性的c属性值为5的数据&#x3C;br/></span></span>
<span class="line"><span>&#x3C;strong> *my_set.find(a.b.c:5)* &#x3C;/strong>&#x3C;br></span></span>
<span class="line"><span>拿到结果的a属性的b属性的c属性值&#x3C;br/></span></span>
<span class="line"><span>&#x3C;strong> *res['a']['b']['c']* &#x3C;/strong></span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br></div></div><br>
:::tip 提示
update,$set等也是这么寻找
:::
### redis
<h4>pip install redis</h4><br/>
### aiomysql
依赖<br>
- Python3.5+
- asyncio
- PyMySQL<br>
eventloop+while True模式进行插入异步进行
<div class="language-py vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">py</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> asyncio</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> aiomysql </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> create_pool</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> aiohttp</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">loop</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">asyncio.get_event_loop()</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">async</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> go</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">():</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    async</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> with</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> create_pool(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">host</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'127.0.0.1'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">port</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">3306</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">user</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'root'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">password</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'1118'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">db</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'aiosql'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">charset</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'utf8mb4'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">loop</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">loop) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">as</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> pool:</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        async</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> with</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> pool.acquire() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">as</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> conn:</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#获得pool</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            async</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> with</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> conn.cursor() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">as</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> cur:</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#创建游标</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">                for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> range</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">100</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">):</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">#异步运行了一百次这个sql语句</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">                    await</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> cur.execute(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'select * from aio limit 1;'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">                    value</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> await</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> cur.fetchone()</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">                    print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(value)</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">loop.run_until_complete(go())</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br></div></div><p>通过连接池来连接</p>
<div class="language-py vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">py</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">async</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> test</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(loop):</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    pool</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=await</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> create_pool(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">host</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'127.0.0.1'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">port</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">3306</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">user</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'root'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">password</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'1118'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">db</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'aiosql'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">charset</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'utf8mb4'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">loop</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">loop)</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    async</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> with</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> pool.acquire() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">as</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> conn:</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        async</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> with</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> conn.cursor() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">as</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> cur:</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> range</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1000000</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">):</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">                await</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> cur.execute(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'select * from aio limit 1;'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">                print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(cur.description)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">                (r,)</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=await</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> cur.fetchone()</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">                print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(r)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    pool.close()</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    await</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> pool.wait_closed()</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">loop</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">asyncio.get_event_loop()</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">loop.run_until_complete(test(loop))</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br></div></div><h2 id="scrapy" tabindex="-1">Scrapy <a class="header-anchor" href="#scrapy" aria-label="Permalink to &quot;Scrapy&quot;">&ZeroWidthSpace;</a></h2>
<p>看<a href='/blog/back/python/scrapy%E7%9B%B8%E5%85%B3.html'>这里</a>或者下一篇</p>
<p>rad爬虫 you-get</p>
<p>我看看能不能执</p>
]]></content:encoded>
        </item>
        <item>
            <link>http://ooowl.fun/blogs/Game/%E6%B8%B8%E6%88%8F%E5%B8%B8%E8%AF%86%E5%92%8CGPU/%E6%9A%82%E5%AD%98.html</link>
            <guid isPermaLink="false">http://ooowl.fun/blogs/Game/%E6%B8%B8%E6%88%8F%E5%B8%B8%E8%AF%86%E5%92%8CGPU/%E6%9A%82%E5%AD%98.html</guid>
            <pubDate>Thu, 01 Jan 1970 00:00:00 GMT</pubDate>
            <content:encoded><![CDATA[<div class="language-txt vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">txt</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>QualitySettings.vSyncCount = 0; //  垂直同步</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div>]]></content:encoded>
        </item>
    </channel>
</rss>