<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Posts on NCJ Tech Blog</title>
    <link>https://blog.chong-zeng.com/posts/</link>
    <description>Recent content in Posts on NCJ Tech Blog</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en</language>
    <lastBuildDate>Sun, 04 Sep 2022 00:00:00 +0000</lastBuildDate>
    <atom:link href="https://blog.chong-zeng.com/posts/rss.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>[Topped] About Me</title>
      <link>https://blog.chong-zeng.com/posts/top/</link>
      <pubDate>Mon, 17 Aug 2020 00:00:00 +0000</pubDate>
      <guid>https://blog.chong-zeng.com/posts/top/</guid>
      <description>Hi, this is NCJ! Welcome to my blog!
Please refer to my homepage (https://www.chong-zeng.com) for more information about me.</description>
      <content:encoded><![CDATA[<p>Hi, this is <strong>NCJ</strong>! Welcome to my blog!</p>
<p>Please refer to my homepage (<a href="https://www.chong-zeng.com">https://www.chong-zeng.com</a>) for more information about me.</p>
<!-- raw HTML omitted -->
]]></content:encoded>
    </item>
    <item>
      <title>我用 AI 画了个新 Logo</title>
      <link>https://blog.chong-zeng.com/posts/2022-09-03_new_logo_with_stable_diffusion/</link>
      <pubDate>Sun, 04 Sep 2022 00:00:00 +0000</pubDate>
      <guid>https://blog.chong-zeng.com/posts/2022-09-03_new_logo_with_stable_diffusion/</guid>
      <description>最近扩散模型加持的 AI Art 有点🔥，周末想着也玩一玩，又受到 OctoSQL 作者的启发，决定体验一下这玩意的同时顺手翻新一下已经用了六年的头像。有一说一最近看到的不少 AI Art 的作品还是很惊艳我的。 不觉得这很酷吗？作为一名理工男我觉得这太酷了，很符合我对未来生活的想象，科技并带着趣味
我选用的模型是 Stable Diffusion，原因非常简单——这玩意真·开源，你可以在本地真正的运行它而不是调云端的 API，同时它生成效果不错且相对来说占用资源还是比较少的。本来一开始想用官方的 codebase，但后来发现 huggingface 出了一个 Diffusers，而且还提供了 fp16 版本的权重，果断换用抱抱脸🤗的产品。然后就开始了玄学的人工 prompt engineering。
改造老 Logo 首先第一想法是能不能用这玩意改造一下现在的 logo。于是找出老 logo，加上一段简单的 prompt，得到了第一个能看的结果：
A silver specular logo saying &amp;lsquo;NCJ&amp;rsquo;, unreal engine, bright color 效果还行，但感觉还缺一点点细节，多加一点元素进 prompt 试试：
a huge transparent glass dome, a logo saying text &amp;lsquo;NCJ&amp;rsquo;, unreal engine, Artstation, PCB electronic design, Massive scale, Fog, Highly detailed, Cinematic, Colorful 感觉有点味道了，于是我悄悄把这个头像换上了，但半天内都没人发现我换头像了！ 一气之下，我决定从头弄一个新的（X
白底黑字的原始图片 Stable Diffusion 和 DALL·E 2 这类 work 的一个缺陷在于他们不能很好的把完整的单词/字母弄到生成的图片上，因此对于 logo 而言还是很有必要把要展示的文字/形象在一开始就放好。</description>
      <content:encoded><![CDATA[<p><img loading="lazy" src="/2022-09-03_new_logo_with_stable_diffusion.assets/1662191295.png" alt="成品图"  />
</p>
<p>最近扩散模型加持的 AI Art 有点🔥，周末想着也玩一玩，又受到 <a href="https://jacobmartins.com/posts/how-i-used-dalle2-to-generate-the-logo-for-octosql/">OctoSQL 作者的启发</a>，决定体验一下这玩意的同时顺手翻新一下已经用了六年的头像。有一说一最近看到的不少 AI Art 的作品还是很惊艳我的。 <del>不觉得这很酷吗？作为一名理工男我觉得这太酷了，很符合我对未来生活的想象，科技并带着趣味</del></p>
<p>我选用的模型是 Stable Diffusion，原因非常简单——这玩意真·开源，你可以在本地真正的运行它而不是调云端的 API，同时它生成效果不错且相对来说占用资源还是比较少的。本来一开始想用<a href="https://github.com/CompVis/stable-diffusion">官方的 codebase</a>，但后来发现 huggingface 出了一个 <a href="https://github.com/huggingface/diffusers">Diffusers</a>，而且还提供了 fp16 版本的权重，果断换用抱抱脸🤗的产品。然后就开始了玄学的人工 prompt engineering。</p>
<h1 id="改造老-logo">改造老 Logo</h1>
<p>首先第一想法是能不能用这玩意改造一下现在的 logo。于是找出老 logo，加上一段简单的 prompt，得到了第一个能看的结果：</p>
<table>
<thead>
<tr>
<th style="text-align:center"><img loading="lazy" src="/2022-09-03_new_logo_with_stable_diffusion.assets/new_logo_1662169331.png" alt=""  />
</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center">A silver specular logo saying &lsquo;NCJ&rsquo;, unreal engine, bright color</td>
</tr>
</tbody>
</table>
<p>效果还行，但感觉还缺一点点细节，多加一点元素进 prompt 试试：</p>
<table>
<thead>
<tr>
<th style="text-align:center"><img loading="lazy" src="/2022-09-03_new_logo_with_stable_diffusion.assets/1662173897.png" alt=""  />
</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center">a huge transparent glass dome, a logo saying text &lsquo;NCJ&rsquo;, unreal engine, Artstation, PCB electronic design, Massive scale, Fog, Highly detailed, Cinematic, Colorful</td>
</tr>
</tbody>
</table>
<p>感觉有点味道了，于是我悄悄把这个头像换上了，但半天内都没人发现我换头像了！ <del>一气之下</del>，我决定从头弄一个新的（X</p>
<h1 id="白底黑字的原始图片">白底黑字的原始图片</h1>
<p>Stable Diffusion 和 DALL·E 2 这类 work 的一个缺陷在于他们不能很好的把完整的单词/字母弄到生成的图片上，因此对于 logo 而言还是很有必要把要展示的文字/形象在一开始就放好。</p>
<table>
<thead>
<tr>
<th style="text-align:center"><img loading="lazy" src="/2022-09-03_new_logo_with_stable_diffusion.assets/ncj_mask.png" alt=""  />
</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center">啊，白底黑字~</td>
</tr>
</tbody>
</table>
<p>选用一些类似 设计稿、蓝图 的 prompt，还是有些效果不错的：</p>
<table>
<thead>
<tr>
<th style="text-align:center"><img loading="lazy" src="/2022-09-03_new_logo_with_stable_diffusion.assets/1662176433.png" alt=""  />
</th>
<th style="text-align:center"><img loading="lazy" src="/2022-09-03_new_logo_with_stable_diffusion.assets/1662176482.png" alt=""  />
</th>
<th style="text-align:center"><img loading="lazy" src="/2022-09-03_new_logo_with_stable_diffusion.assets/1662176697.png" alt=""  />
</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center">design, draft, blueprint</td>
<td style="text-align:center">design, draft, blueprint</td>
<td style="text-align:center">design, logo, colorful, pencil sketch</td>
</tr>
</tbody>
</table>
<p>但也有摆烂的：</p>
<table>
<thead>
<tr>
<th style="text-align:center"><img loading="lazy" src="/2022-09-03_new_logo_with_stable_diffusion.assets/1662176509.png" alt=""  />
</th>
<th style="text-align:center"><img loading="lazy" src="/2022-09-03_new_logo_with_stable_diffusion.assets/1662176572.png" alt=""  />
</th>
<th style="text-align:center"><img loading="lazy" src="/2022-09-03_new_logo_with_stable_diffusion.assets/1662176761.png" alt=""  />
</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center">design, draft, blueprint, icon, logo</td>
<td style="text-align:center">design, draft, blueprint, icon, logo, colorful, pencil sketch</td>
<td style="text-align:center">logo, colorful, design sketch, highly detailed</td>
</tr>
</tbody>
</table>
<p>此时我意识到一个问题，就是说即便不摆烂的输出，它在外围的内容还是偏少，会不会是因为我没有在外围勾画些东西来告诉模型你要在上面画点啥，于是我在原始图片上随手画了一些线条，并把中间的字母改为了镂空的：</p>
<table>
<thead>
<tr>
<th style="text-align:center"><img loading="lazy" src="/2022-09-03_new_logo_with_stable_diffusion.assets/ncj_sketch.png" alt=""  />
</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center">sketch</td>
</tr>
</tbody>
</table>
<p>果然好多了，除了有时候字母还是会被模型给改掉：</p>
<table>
<thead>
<tr>
<th style="text-align:center"><img loading="lazy" src="/2022-09-03_new_logo_with_stable_diffusion.assets/1662177128.png" alt=""  />
</th>
<th style="text-align:center"><img loading="lazy" src="/2022-09-03_new_logo_with_stable_diffusion.assets/1662177310.png" alt=""  />
</th>
<th style="text-align:center"><img loading="lazy" src="/2022-09-03_new_logo_with_stable_diffusion.assets/1662177562.png" alt=""  />
</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center">logo, colorful, design sketch, highly detailed</td>
<td style="text-align:center">logo, colorful, design sketch, electronic PCB design</td>
<td style="text-align:center">electronic PCB design</td>
</tr>
<tr>
<td style="text-align:center"><img loading="lazy" src="/2022-09-03_new_logo_with_stable_diffusion.assets/1662193186.png" alt=""  />
</td>
<td style="text-align:center"><img loading="lazy" src="/2022-09-03_new_logo_with_stable_diffusion.assets/1662193199.png" alt=""  />
</td>
<td style="text-align:center"><img loading="lazy" src="/2022-09-03_new_logo_with_stable_diffusion.assets/1662193137.png" alt=""  />
</td>
</tr>
<tr>
<td style="text-align:center">3D, colorful, Artstation, modern, academic, lasers in the room, rays scattering, neon</td>
<td style="text-align:center">3D, colorful, Artstation, modern, academic, lasers in the room, rays scattering, neon</td>
<td style="text-align:center">3D, colorful, Artstation, modern, academic, lasers in the room, rays scattering, neon</td>
</tr>
</tbody>
</table>
<p>不过感觉这些结果还是不太对胃口， <del>场景还是太单调了</del>，要不我先搭一个场景，然后让模型给我补细节吧（X</p>
<h1 id="cornell-box">Cornell Box</h1>
<p><del>但我哪里会搭场景啊（雾</del>，于是找来了经典的 Cornell Box，然后在上面恬不知耻的加上了 NCJ 三个字母：</p>
<table>
<thead>
<tr>
<th style="text-align:center"><img loading="lazy" src="/2022-09-03_new_logo_with_stable_diffusion.assets/ncj_cornell_box.png" alt=""  />
</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center">Cornell Box</td>
</tr>
</tbody>
</table>
<p>不得不说经典场景的配色确实看着还是挺舒服的（</p>
<table>
<thead>
<tr>
<th style="text-align:center"><img loading="lazy" src="/2022-09-03_new_logo_with_stable_diffusion.assets/1662188006.png" alt=""  />
</th>
<th style="text-align:center"><img loading="lazy" src="/2022-09-03_new_logo_with_stable_diffusion.assets/1662189637.png" alt=""  />
</th>
<th style="text-align:center"><img loading="lazy" src="/2022-09-03_new_logo_with_stable_diffusion.assets/1662189645.png" alt=""  />
</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center">3D, colorful, Artstation</td>
<td style="text-align:center">3D, colorful, Artstation, Information Technology, modern</td>
<td style="text-align:center">3D, colorful, Artstation, Information Technology, modern</td>
</tr>
<tr>
<td style="text-align:center"><img loading="lazy" src="/2022-09-03_new_logo_with_stable_diffusion.assets/1662189910.png" alt=""  />
</td>
<td style="text-align:center"><img loading="lazy" src="/2022-09-03_new_logo_with_stable_diffusion.assets/1662189941.png" alt=""  />
</td>
<td style="text-align:center"><img loading="lazy" src="/2022-09-03_new_logo_with_stable_diffusion.assets/1662189645.png" alt=""  />
</td>
</tr>
<tr>
<td style="text-align:center">3D, colorful, Artstation, Information Technology, modern, academic, CTO</td>
<td style="text-align:center">3D, colorful, Artstation, Information Technology, modern, academic, CTO</td>
<td style="text-align:center">3D, colorful, Artstation, modern, academic</td>
</tr>
<tr>
<td style="text-align:center"><img loading="lazy" src="/2022-09-03_new_logo_with_stable_diffusion.assets/1662190771.png" alt=""  />
</td>
<td style="text-align:center"><img loading="lazy" src="/2022-09-03_new_logo_with_stable_diffusion.assets/1662191432.png" alt=""  />
</td>
<td style="text-align:center"><img loading="lazy" src="/2022-09-03_new_logo_with_stable_diffusion.assets/1662191588.png" alt=""  />
</td>
</tr>
<tr>
<td style="text-align:center">3D, colorful, Artstation, modern, academic, papers</td>
<td style="text-align:center">3D letters placed in the air in the room, 3D, colorful, Artstation, modern, academic, CTO, college</td>
<td style="text-align:center">3D, colorful, Artstation, modern, academic, CTO, lasers in the room, rays scattering</td>
</tr>
</tbody>
</table>
<p>最后，选了开头的那张，它的 prompt 是 3D, colorful, Artstation, modern, academic, CTO</p>
<p>不过这些 prompt 多少还是带了猜和蒙的味道，比如里面的 CTO，本来是想加入一点高端商务风，后来检查发现 stable diffusion 其实都没见过这种图，因为当你直接把 CTO 交给模型，它会给你这样一张图：</p>
<p><img loading="lazy" src="/2022-09-03_new_logo_with_stable_diffusion.assets/1662191772.png" alt=""  />
</p>
<p>所以说写 prompt 前还是应该检查一下模型认识啥不认识啥的（X</p>
<p>总的来说，模型的生成能力还是非常惊艳的，但写 prompt 实在是太玄学了，希望 NLP 的学者们赶紧研究研究怎么把正儿八经的 prompt engineering 用到 diffusion 上。</p>
]]></content:encoded>
    </item>
    <item>
      <title>绕过 macOS 上的 GPG passphrase 要求</title>
      <link>https://blog.chong-zeng.com/posts/2022-07-30_gpg_macos/</link>
      <pubDate>Sat, 30 Jul 2022 00:00:00 +0000</pubDate>
      <guid>https://blog.chong-zeng.com/posts/2022-07-30_gpg_macos/</guid>
      <description>今天在 MacBook 上配置 gpg 的时候，总是要求我设置 passphrase，但我懒，网上查到说可以创建之后再用 passwd 删除，但试了试不行，修改密码的时候不允许新密码为空。
然后发现 quick-gen-key 可以先生成一个没有 passphrase 的密钥，然后再编辑它绑定邮箱和备注啥的。
gpg --batch --passphrase &amp;#39;&amp;#39; --quick-gen-key USER_ID default default 印象中一年前配置黑苹果的时候就遇到了一次，忘了当时咋处理的了，这次还是简单记一下好了。</description>
      <content:encoded><![CDATA[<p>今天在 MacBook 上配置 <code>gpg</code> 的时候，总是要求我设置 passphrase，但我懒，网上查到说可以创建之后再用 <code>passwd</code> 删除，但试了试不行，修改密码的时候不允许新密码为空。</p>
<p>然后发现 <code>quick-gen-key</code> 可以先生成一个没有 passphrase 的密钥，然后再编辑它绑定邮箱和备注啥的。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">gpg --batch --passphrase <span class="s1">&#39;&#39;</span> --quick-gen-key USER_ID default default
</span></span></code></pre></div><p>印象中一年前配置黑苹果的时候就遇到了一次，忘了当时咋处理的了，这次还是简单记一下好了。</p>
]]></content:encoded>
    </item>
    <item>
      <title>小米手环复制 ZJU 校园卡简记</title>
      <link>https://blog.chong-zeng.com/posts/2022-07-23_miband_fakenfc/</link>
      <pubDate>Sat, 23 Jul 2022 00:00:00 +0000</pubDate>
      <guid>https://blog.chong-zeng.com/posts/2022-07-23_miband_fakenfc/</guid>
      <description>两年前在某宝上买了一个 PN532 模块，然后踩了一堆坑复制了本科的校园卡到小米手环 4 NFC上，最近要读研了要换卡，又把坑踩了一遍，遂简记一下避免再次踩坑 （虽然我大概后面再也用不到了（雾
一句话概括 代理卡片不要写完整的扇区 0，要把加密删了，后面扇区 0 的加密是可以改回来的
ZJU 校园卡的特性 0 - 5 扇区会被加密，即第一个扇区也会被加密，这一特性导致网上的方案不可行
小米手环复制门卡的特性 要求门卡非加密，任何一个扇区加密都不行
只能有第一个扇区有内容，即扇区 0
仅复制扇区 0 中的卡号，且强制将厂家信息写为小米自己的（至少手环 4 是这样的）
但是，第一个扇区的其他内容（含加密信息），以及其他扇区的信息都可以在复制完门卡后再次外置写入，利用这一点可以将复制出来的非加密卡转为加密卡
解决方案 软件 xcicode/MifareOneTool: A GUI Mifare Classic tool on Windows
虽然这玩意 19 年就停工了但也不是不能用
另外 Linux 上用 mfcuk 去操作也是可以的
步骤 使用 MifareOneTool 破解原始的校园卡
既然小米手环只能复制第一个扇区的卡号部分，那就使用 CUID 卡创建一个非加密的仅包含卡号信息的代理卡（直接按照网上的方案创建只包含扇区 0 的卡是不行的，一定要把扇区 0 的加密手工删掉，否则无法复制），然后让小米手环去复制这张卡
使用 MifareOneTool 对着手环上新复制的这张卡再次写入完整的数据（即扇区 0 - 15，因为扇区 0 需要靠这个步骤转换回加密的状态），此时选择写普通卡 / 写 CUID 卡区别不大，毕竟小米手环上的卡是不能写卡号和厂商信息的
大功告成，可以使用 MCT 之类的工具检查一下卡片复制是否成功</description>
      <content:encoded><![CDATA[<blockquote>
<p>两年前在某宝上买了一个 PN532 模块，然后踩了一堆坑复制了本科的校园卡到小米手环 4 NFC上，最近要读研了要换卡，又把坑踩了一遍，遂简记一下避免再次踩坑 <del>（虽然我大概后面再也用不到了（雾</del></p>
</blockquote>
<h1 id="一句话概括">一句话概括</h1>
<p>代理卡片不要写完整的扇区 0，要把加密删了，后面扇区 0 的加密是可以改回来的</p>
<h1 id="zju-校园卡的特性">ZJU 校园卡的特性</h1>
<p>0 - 5 扇区会被加密，即第一个扇区也会被加密，这一特性导致网上的方案不可行</p>
<h1 id="小米手环复制门卡的特性">小米手环复制门卡的特性</h1>
<ol>
<li>
<p>要求门卡非加密，任何一个扇区加密都不行</p>
</li>
<li>
<p>只能有第一个扇区有内容，即扇区 0</p>
</li>
<li>
<p>仅复制扇区 0 中的卡号，且强制将厂家信息写为小米自己的（至少手环 4 是这样的）</p>
</li>
<li>
<p><strong>但是</strong>，第一个扇区的其他内容（含加密信息），以及其他扇区的信息都可以在复制完门卡后再次外置写入，利用这一点可以将复制出来的非加密卡转为加密卡</p>
</li>
</ol>
<h1 id="解决方案">解决方案</h1>
<h2 id="软件">软件</h2>
<p><a href="https://github.com/xcicode/MifareOneTool">xcicode/MifareOneTool: A GUI Mifare Classic tool on Windows</a></p>
<p>虽然这玩意 19 年就停工了但也不是不能用</p>
<p>另外 Linux 上用 <code>mfcuk</code> 去操作也是可以的</p>
<h2 id="步骤">步骤</h2>
<ol>
<li>
<p>使用 <code>MifareOneTool</code> 破解原始的校园卡</p>
</li>
<li>
<p>既然小米手环只能复制第一个扇区的卡号部分，那就使用 <strong>CUID</strong> 卡创建一个<strong>非加密的仅包含卡号信息</strong>的代理卡（直接按照网上的方案创建只包含扇区 0 的卡是不行的，一定要把扇区 0 的加密手工删掉，否则无法复制），然后让小米手环去复制这张卡</p>
</li>
<li>
<p>使用 <code>MifareOneTool</code> 对着手环上新复制的这张卡再次写入<strong>完整的数据</strong>（即扇区 0 - 15，因为扇区 0 需要靠这个步骤转换回加密的状态），此时选择写普通卡 / 写 CUID 卡区别不大，毕竟小米手环上的卡是不能写卡号和厂商信息的</p>
</li>
<li>
<p>大功告成，可以使用 <code>MCT</code> 之类的工具检查一下卡片复制是否成功</p>
</li>
</ol>
]]></content:encoded>
    </item>
    <item>
      <title>[Paper Reading] RXMesh: A GPU Mesh Data Structure</title>
      <link>https://blog.chong-zeng.com/posts/2022-02-15_rxmesh/</link>
      <pubDate>Tue, 15 Feb 2022 00:00:00 +0000</pubDate>
      <guid>https://blog.chong-zeng.com/posts/2022-02-15_rxmesh/</guid>
      <description>1. 这篇文章究竟讲了什么问题？ 如何利用 GPU 来并行加速大规模的网格处理
2. 这个问题的性质是什么？如果不完全是一个新问题，那为什么它“仍然重要”？ 属于改进类的问题
以往的网格加速方法要么是：
application-specific 需要从线性代数上对问题进行 reform mesh 会变为稀疏矩阵 减少了中间变量，但是局部性变差，性能不够好 所以需要一个通用的高性能加速框架
3. 这篇文章致力于证明什么假设？ 通过高效的数据结构 + 更好的变成模型，可以实现通用的网格处理加速
4. 有哪些与这篇文章相关的研究？ 高性能编程模型 图像处理：Halide，调度与算法分离 稀疏体素计算 / simulation：太极 纯模拟：Ebb 图处理：Gunrock 5. 这篇文章提出的问题解决方案中，核心贡献是什么？ 一个 high-level 的编程模型
用户顶层 定义好每个 mesh 上执行的计算
八种查询
以计算 vertex normal 为例：
非常清晰
模型底层 通过将整个 mesh 切分成很多 patch，然后按照 patch 来往 GPU 的 block 上分配计算任务，进而增加了局部性
patching 之后的 index 可视化出来如下图，很明显，比起直接按照 global sorting 的划分，patching 下相同 index 的部分会更加集中，相关数据在查询、计算的时候可以常驻 shared memory
那么 patch 如何表示？</description>
      <content:encoded><![CDATA[<h1 id="1-这篇文章究竟讲了什么问题">1. 这篇文章究竟讲了什么问题？</h1>
<p>如何利用 GPU 来并行加速大规模的网格处理</p>
<h1 id="2-这个问题的性质是什么如果不完全是一个新问题那为什么它仍然重要">2. 这个问题的性质是什么？如果不完全是一个新问题，那为什么它“仍然重要”？</h1>
<p>属于改进类的问题</p>
<p>以往的网格加速方法要么是：</p>
<ol>
<li>application-specific</li>
<li>需要从线性代数上对问题进行 reform
<ol>
<li>mesh 会变为稀疏矩阵</li>
<li>减少了中间变量，但是局部性变差，性能不够好</li>
</ol>
</li>
</ol>
<p>所以需要一个通用的高性能加速框架</p>
<h1 id="3-这篇文章致力于证明什么假设">3. 这篇文章致力于证明什么假设？</h1>
<p>通过高效的数据结构 + 更好的变成模型，可以实现通用的网格处理加速</p>
<h1 id="4-有哪些与这篇文章相关的研究">4. 有哪些与这篇文章相关的研究？</h1>
<ol>
<li>高性能编程模型
<ol>
<li>图像处理：Halide，调度与算法分离</li>
<li>稀疏体素计算 / simulation：太极</li>
<li>纯模拟：Ebb</li>
<li>图处理：Gunrock</li>
</ol>
</li>
</ol>
<h1 id="5-这篇文章提出的问题解决方案中核心贡献是什么">5. 这篇文章提出的问题解决方案中，核心贡献是什么？</h1>
<p>一个 high-level 的编程模型</p>
<h2 id="用户顶层">用户顶层</h2>
<ol>
<li>
<p>定义好每个 mesh 上执行的计算</p>
</li>
<li>
<p>八种查询</p>
<p><img loading="lazy" src="/2022-02-15_RXMesh.assets/0.png" alt="Untitled"  />
</p>
</li>
<li>
<p>以计算 vertex normal 为例：</p>
<p><img loading="lazy" src="/2022-02-15_RXMesh.assets/1.png" alt="Untitled"  />
</p>
<p>非常清晰</p>
</li>
</ol>
<h2 id="模型底层">模型底层</h2>
<ol>
<li>
<p>通过将整个 mesh 切分成很多 patch，然后按照 patch 来往 GPU 的 block 上分配计算任务，进而增加了局部性</p>
<p>patching 之后的 index 可视化出来如下图，很明显，比起直接按照 global sorting 的划分，patching 下相同 index 的部分会更加集中，相关数据在查询、计算的时候可以常驻 shared memory</p>
<p><img loading="lazy" src="/2022-02-15_RXMesh.assets/2.png" alt="Untitled"  />
</p>
</li>
<li>
<p>那么 patch 如何表示？</p>
<p>作者选用了 LAR (Linear Algebraic Representation) 来表示每个 patch</p>
<p><img loading="lazy" src="/2022-02-15_RXMesh.assets/3.png" alt="Untitled"  />
</p>
<p>这样的表示更加紧凑</p>
<ul>
<li>另外因为每个 patch 其实不大，所以每个 patch 内的信息都可以使用 16-bit 来表示，使得数据更加紧凑</li>
</ul>
</li>
<li>
<p>负载均衡</p>
<p>设计了类似任务队列的机制，block 内的 thread 不与 vertex 绑定，而是采用协作的模式，使得各个 thread 的负载较为均匀</p>
<p><img loading="lazy" src="/2022-02-15_RXMesh.assets/4.png" alt="Untitled"  />
</p>
</li>
<li>
<p>ribbon 机制</p>
<p>为了减少 block 之间的通信开销，每个 patch 会额外增加边上的一圈网格，从而无需从其他 patch 取计算结果</p>
<p><img loading="lazy" src="/2022-02-15_RXMesh.assets/5.png" alt="Untitled"  />
</p>
</li>
</ol>
<h1 id="6-实验是如何设计的">6. 实验是如何设计的？</h1>
<ol>
<li>查询操作（对比通用性能）
<ol>
<li>与 PDE、OpenMesh、CGAL 等业界库对比性能</li>
</ol>
</li>
<li>应用（对比特定应用性能）
<ol>
<li>Mean Curvature Flow</li>
<li>Geodesic Distance</li>
<li>Bilateral Filtering</li>
<li>Vertex Normal</li>
</ol>
</li>
</ol>
<h1 id="7-实验是在什么样的数据集基础上运行的">7. 实验是在什么样的数据集基础上运行的？</h1>
<p>网格取自 Thingi10K: A Dataset of 10,000 3D-Printing Models</p>
<h1 id="8-实验结果能否有力地支持假设">8. 实验结果能否有力地支持假设？</h1>
<ol>
<li>通用查询
<ol>
<li>速度吊打 OpenMesh 和 CGAL</li>
<li>一些场景比 PDE 略慢
<ol>
<li>比如 EV、EF 的时候，因为 PDE 只需要写 4-bytes per-thread，所以快不少</li>
</ol>
</li>
</ol>
</li>
<li>特定应用
<ol>
<li>Mean Curvature Flow
<ol>
<li>4.6x faster than PDE</li>
</ol>
</li>
<li>Geodesic Distance
<ol>
<li>15.5x faster than PDE</li>
</ol>
</li>
<li>Bilateral Filtering
<ol>
<li>因为 RXMesh 需要读 ribbon，多读了</li>
<li>PDE 比 RXMesh 快 1.12x</li>
</ol>
</li>
<li>Vertex Normal
<ol>
<li>hardwired Indexed triangle 比 RXMesh 快 1.14x</li>
<li>因为 Mesh Matrix / hardwired version 的内存更加规整
<ol>
<li>每个面只读三个顶点，一点都不多读</li>
</ol>
</li>
<li>即便如此，RXMesh 速度还是不错的，毕竟写起来简单多了而且是通用方法</li>
</ol>
</li>
</ol>
</li>
<li>两组实验都充分表明了 RXMesh 的优越</li>
</ol>
<h1 id="9-这篇文章的贡献是什么">9. 这篇文章的贡献是什么？</h1>
<p>一个通用的、高性能的、高级的网格数据处理编程模型</p>
<blockquote>
<p>作者在 slide 里补充了一句作为结论：
Programmer-managed caching is the right way to capture mesh locality and improve GPU performance for mesh processing</p>
</blockquote>
<h1 id="10-下一步可以做什么">10. 下一步可以做什么？</h1>
<ol>
<li>支持动态网格
<ol>
<li>现在的加速结构需要对每个 mesh 进行一次构造</li>
<li>需要想办法支持动态改变的网格</li>
</ol>
</li>
<li>增强 high-order 查询的性能
<ol>
<li>现在都是一级的查询（8种）</li>
</ol>
</li>
<li>支持 quad mesh
<ol>
<li>现在全都是三角网格</li>
<li>也许之后还可以支持体积网格</li>
</ol>
</li>
</ol>
]]></content:encoded>
    </item>
    <item>
      <title>[Paper Reading] Volumetric Appearance Stylization with Stylizing Kernel Prediction Network</title>
      <link>https://blog.chong-zeng.com/posts/2022-02-13_volumetric_style_transfer/</link>
      <pubDate>Sun, 13 Feb 2022 00:00:00 +0000</pubDate>
      <guid>https://blog.chong-zeng.com/posts/2022-02-13_volumetric_style_transfer/</guid>
      <description>1. 这篇文章究竟讲了什么问题？ 通过体积风格转移的方法，来高效地构造颜色外观上符合要求的、异质单反射体积。
网络使用了一个体积的自编码器，并且使用了 stylizing kernel predictor
2. 这个问题的性质是什么？如果不完全是一个新问题，那为什么它“仍然重要”？ 属于改进性质的问题，之前已经有不少人研究过了体积上的风格迁移，但是文章提出的方法能够得到更好的效果。
同时这篇 paper 也属于 Artistic Appearance Design，传统的方法需要较为复杂的人工调整才能得到较好的效果，而本文的方法不需要人工干预，效率更高。
3. 这篇文章致力于证明什么假设？ 证明它的这套风格迁移的框架是 work 的，并且效果很好
4. 有哪些与这篇文章相关的研究？ Neural Style Transfer for Images Neural Style Transfer for 3D Contents Artistic Appearance Design Differentiable Rendering 5. 这篇文章提出的问题解决方案中，核心贡献是什么？ 核心 idea
提出了一个将颜色外观从二维图形转移到三维图形上的框架 细节
设计了一个多尺度的基于 kernel 的神经网络来进行任意的风格迁移并保证时间上的一致性
SKP 首先使用 CNN (VGG) 来提取多个尺度的二维图片上的特征 然后选用 channel-wise 的均值和方差（实际网络中用的是标准差）进行拼接，得到一个特征向量 将这个向量通过一系列全连接层映射到一个 kernel 上 VolAE 经典的 encoder-decoder 结构，中间带有 skip 连接 在 decode 阶段将前面 SKP 得到的 kernel 插入进来，来将二维的风格加入到生成的体积中 引入了一个密度感知的 instance normalization 层，来避免色彩偏移</description>
      <content:encoded><![CDATA[<h1 id="1-这篇文章究竟讲了什么问题">1. 这篇文章究竟讲了什么问题？</h1>
<p>通过体积风格转移的方法，来高效地构造颜色外观上符合要求的、异质单反射体积。</p>
<p>网络使用了一个体积的自编码器，并且使用了 stylizing kernel predictor</p>
<h1 id="2-这个问题的性质是什么如果不完全是一个新问题那为什么它仍然重要">2. 这个问题的性质是什么？如果不完全是一个新问题，那为什么它“仍然重要”？</h1>
<p>属于改进性质的问题，之前已经有不少人研究过了体积上的风格迁移，但是文章提出的方法能够得到更好的效果。</p>
<p>同时这篇 paper 也属于 Artistic Appearance Design，传统的方法需要较为复杂的人工调整才能得到较好的效果，而本文的方法不需要人工干预，效率更高。</p>
<h1 id="3-这篇文章致力于证明什么假设">3. 这篇文章致力于证明什么假设？</h1>
<p>证明它的这套风格迁移的框架是 work 的，并且效果很好</p>
<h1 id="4-有哪些与这篇文章相关的研究">4. 有哪些与这篇文章相关的研究？</h1>
<ul>
<li>Neural Style Transfer for Images</li>
<li>Neural Style Transfer for 3D Contents</li>
<li>Artistic Appearance Design</li>
<li>Differentiable Rendering</li>
</ul>
<h1 id="5-这篇文章提出的问题解决方案中核心贡献是什么">5. 这篇文章提出的问题解决方案中，核心贡献是什么？</h1>
<ul>
<li>
<p>核心 idea</p>
<ul>
<li>提出了一个将颜色外观从二维图形转移到三维图形上的框架</li>
</ul>
<p><img loading="lazy" src="/2022-02-15_volumetric_style_transfer.assets/0.png" alt="Untitled.png"  />
</p>
</li>
<li>
<p>细节</p>
<ul>
<li>
<p>设计了一个多尺度的基于 kernel 的神经网络来进行任意的风格迁移并保证时间上的一致性</p>
<p><img loading="lazy" src="/2022-02-15_volumetric_style_transfer.assets/1.png" alt="Untitled%201.png"  />
</p>
<ul>
<li>SKP
<ul>
<li>首先使用 CNN (VGG) 来提取多个尺度的二维图片上的特征</li>
<li>然后选用 channel-wise 的均值和方差（实际网络中用的是标准差）进行拼接，得到一个特征向量</li>
<li>将这个向量通过一系列全连接层映射到一个 kernel 上</li>
</ul>
</li>
<li>VolAE
<ul>
<li>经典的 encoder-decoder 结构，中间带有 skip 连接</li>
<li>在 decode 阶段将前面 SKP 得到的 kernel 插入进来，来将二维的风格加入到生成的体积中</li>
</ul>
</li>
</ul>
</li>
<li>
<p>引入了一个密度感知的 instance normalization 层，来避免色彩偏移</p>
<ul>
<li>
<p>色彩偏移 / 色差</p>
</li>
<li>
<p>为什么会出现色彩偏移？</p>
<ul>
<li>在一些场景里（比如烟雾模拟），voxel 的分布非常不均匀，一些稀疏却非常致密的 voxel 会导致训练困难，进而产生色彩偏移</li>
</ul>
</li>
<li>
<p>解决</p>
<ul>
<li>
<p>使用 DAIN (density-aware instance normalization) 来给这一部分的 voxel 更大的权重</p>
</li>
<li>
<p>加入了一个平滑的密度 mask: $\textbf{m} = 1 - \text{exp}(-\lambda\textbf{V}_\sigma^2)$</p>
</li>
<li>
<p>于是均值和方差变为：</p>
<p><img loading="lazy" src="/2022-02-15_volumetric_style_transfer.assets/2.png" alt="Untitled%202.png"  />
</p>
</li>
</ul>
</li>
<li>
<p>效果</p>
<p><img loading="lazy" src="/2022-02-15_volumetric_style_transfer.assets/3.png" alt="Untitled%203.png"  />
</p>
</li>
</ul>
</li>
<li>
<p>实现了一个分析性的可微体积渲染层，这样可以方便 loss 的计算</p>
<ul>
<li>
<p>分析性 → 简化模型</p>
<ul>
<li>
<p>假设</p>
<ol>
<li>物体的相位函数是各项异性的，且只被环境光照亮</li>
<li>每个 pixel 上只发射一条光线，且只考虑一次散射</li>
</ol>
</li>
<li>
<p>简化模型</p>
<ol>
<li>ray marching 的 sample 是等距离的</li>
</ol>
<p><img loading="lazy" src="/2022-02-15_volumetric_style_transfer.assets/4.png" alt="Untitled%204.png"  />
</p>
<ol>
<li>每次 sampling 的辐射度都是从各向异性的相位方程中采样出来的</li>
</ol>
<p><img loading="lazy" src="/2022-02-15_volumetric_style_transfer.assets/5.png" alt="Untitled"  />
</p>
</li>
</ul>
</li>
<li>
<p>光源使用环境光，这样可以渲染出比较均匀的体积，避免网络将点光源产生的阴影当作特征进行学习</p>
</li>
<li>
<p>不使用通用的 DTRT 框架，因为太慢了</p>
</li>
</ul>
</li>
<li>
<p>Loss</p>
<ul>
<li>Gran Loss 不好
<ul>
<li>收敛慢</li>
<li>有 artifacts</li>
</ul>
</li>
<li>用 Histogram Loss</li>
<li>另外加上了 total variation loss 和 temporal loss，前者是正则化项，来增强空间平滑性，后者是时域上的平滑性</li>
</ul>
<p><img loading="lazy" src="/2022-02-15_volumetric_style_transfer.assets/6.png" alt="Untitled"  />
</p>
</li>
</ul>
</li>
</ul>
<h1 id="6-实验是如何设计的">6. 实验是如何设计的？</h1>
<ol>
<li>使用 pytorch 实现了整个网络，并与以前的方法进行对比</li>
<li>对比不同的 loss function 的效果</li>
<li>对比不同的 kernel、views 的效果</li>
<li>尝试各种场景的 demo</li>
</ol>
<h1 id="7-实验是在什么样的数据集基础上运行的">7. 实验是在什么样的数据集基础上运行的？</h1>
<ol>
<li>volume 数据集
<ul>
<li>使用 mantaflow 生成了大量体积数据集</li>
<li>simulate 100 groups of smokes with a resolution of 64 × 64 × 64</li>
<li>20 * 128 x 128 x 128
<ul>
<li>避免网络对低分辨率的体积过拟合</li>
<li>增加鲁棒性</li>
</ul>
</li>
</ul>
</li>
<li>style image 数据集
<ul>
<li>DTD 数据集</li>
</ul>
</li>
</ol>
<h1 id="8-实验结果能否有力地支持假设">8. 实验结果能否有力地支持假设？</h1>
<ol>
<li>
<p>与传统方法对比是投票投出来的</p>
<ol>
<li>user study</li>
</ol>
<p><img loading="lazy" src="/2022-02-15_volumetric_style_transfer.assets/7.png" alt="Untitled"  />
</p>
<p>b. 不过确实，风格迁移不太好有非常量化的评价指标，毕竟不存在 ground truth</p>
</li>
<li>
<p>loss 效果好</p>
<ol>
<li>
<p>histogram loss 最符合输入图片的色彩分布</p>
<p><img loading="lazy" src="/2022-02-15_volumetric_style_transfer.assets/8.png" alt="Untitled"  />
</p>
</li>
<li>
<p>temporal loss</p>
<p>加上之后可以消除 flicker</p>
</li>
</ol>
</li>
<li>
<p>不同的 kernel</p>
<p><img loading="lazy" src="/2022-02-15_volumetric_style_transfer.assets/9.png" alt="Untitled"  />
</p>
<p>作者对比了一大堆，但是毕竟我们也不知道 ground truth，所以其实只是呈现了一些不同的效果</p>
</li>
<li>
<p>训练所用的视角数量</p>
<p>越多越好，符合直觉</p>
<p><img loading="lazy" src="/2022-02-15_volumetric_style_transfer.assets/10.png" alt="Untitled"  />
</p>
</li>
<li>
<p>其他 demo</p>
<ol>
<li>通过调整 volume 的分辨率可以调整风格结构的尺寸</li>
<li>这套方法能够模拟玉石这种半透明材料
<ol>
<li>只要输入的风格图片是真实世界中的半透明材料上采集的即可</li>
</ol>
</li>
<li>可以模拟动态的火焰</li>
</ol>
</li>
</ol>
<h1 id="9-这篇文章的贡献是什么">9. 这篇文章的贡献是什么？</h1>
<ol>
<li>提出了一个将颜色外观从二维图形转移到三维图形上的通用框架</li>
<li>设计了一个多尺度的基于 kernel 的神经网络来进行任意的风格迁移，并保证了时域上的一致性</li>
<li>引入了一个 DAIN 层，来避免色彩偏移</li>
<li>实现了一个简化的可微体积渲染层，方便 loss 的计算，提高训练效率</li>
</ol>
<h1 id="10-下一步可以做什么">10. 下一步可以做什么？</h1>
<ol>
<li>缺少细节
<ol>
<li>比如毛发、纤维这种都还不行</li>
<li>因为直接使用的是均值和方差，可能需要补充更多的统计信息</li>
</ol>
</li>
<li>没法对体积本身进行同时的风格迁移
<ol>
<li>尝试套用 TNST，但是效果并不是很好</li>
<li>需要探索一种联合迁移优化的方案</li>
</ol>
</li>
</ol>
]]></content:encoded>
    </item>
    <item>
      <title>[Paper Reading] Antithetic Sampling for Monte Carlo Differentiable Rendering</title>
      <link>https://blog.chong-zeng.com/posts/2022-02-12_dual_diff/</link>
      <pubDate>Sat, 12 Feb 2022 00:00:00 +0000</pubDate>
      <guid>https://blog.chong-zeng.com/posts/2022-02-12_dual_diff/</guid>
      <description>Disclaimer:
这几篇 paper reading 是我去年暑期在 MSRA 实习期间留下的笔记，近期整理文件翻出遂转至博客。其中的内容不保证正确性，观点仅供参考。 “十问” 的格式来源于沈向洋老师的分享，指路 👉 1. 这篇文章究竟讲了什么问题？ 蒙特卡洛可微渲染中的对偶采样 问题： 可微渲染：渲染是在3D场景中进行积分得到2D图片，可微渲染就是逆向渲染的一个方法，通过微分从2D图片得到3D场景的部分参数 本文主要研究的是 physical-based 可微渲染，不是光栅化那种的 传统的 sampling 方法在面对高光表面的时候，会非常低效，尤其是在对全局的几何求导的时候 引入对偶采样可以大幅提高采样效率 2. 这个问题的性质是什么？它的重要性何在？ 对于传统方法的改进，解决掉了传统的 sampling 方法在面对高光物体时的低效问题 重要性： 计算制造、计算成像、遥感 不过感觉高光这件事在成像上重要一些，遥感这种远场的情况很少出现高光 完善了以往的方法，使得整个 BSDF 的对偶采样框架有更好的普适性 3. 这篇文章致力于证明什么假设？ 利用了对偶采样的蒙特卡洛算法能够很好的估计内部积分，从而使得整个采样框架具有更好的效率和普适性
4. 有哪些与这篇文章相关的研究？这一领域有哪些关键人物？ 本文的作者（Zhao Shuang）就是专门做可微渲染的，在去年的 SIGGRAPH20 上给了一个可微渲染的 course，CVPR21 又给了一个 tutorial talk Wenzel Jakob, 开发了 mitsuba2 的团队，mitsuba2 主要解决了可微渲染中高性能 auto diff 的问题 还有 Tzu-Mao Li 老师 5. 这篇文章提出的问题解决方案中，核心贡献是什么？ 面对高光表面，蒙特卡洛为什么慢？
When 𝐹 contains high-magnitude positive and negative regions, estimating 𝐼 using Monte Carlo methods with independent samples can suffer from very slow convergence.</description>
      <content:encoded><![CDATA[<blockquote>
<p>Disclaimer:</p>
<ol>
<li>这几篇 paper reading 是我去年暑期在 MSRA 实习期间留下的笔记，近期整理文件翻出遂转至博客。其中的内容不保证正确性，观点仅供参考。</li>
<li>“十问” 的格式来源于沈向洋老师的分享，指路 <a href="https://zhuanlan.zhihu.com/p/163227375">👉</a></li>
</ol>
</blockquote>
<h1 id="1-这篇文章究竟讲了什么问题">1. 这篇文章究竟讲了什么问题？</h1>
<ol>
<li>蒙特卡洛可微渲染中的对偶采样</li>
<li>问题：
<ol>
<li>可微渲染：渲染是在3D场景中进行积分得到2D图片，可微渲染就是逆向渲染的一个方法，通过微分从2D图片得到3D场景的部分参数</li>
<li>本文主要研究的是 physical-based 可微渲染，不是光栅化那种的</li>
<li>传统的 sampling 方法在面对高光表面的时候，会非常低效，尤其是在对全局的几何求导的时候</li>
<li>引入对偶采样可以大幅提高采样效率</li>
</ol>
</li>
</ol>
<h1 id="2-这个问题的性质是什么它的重要性何在">2. 这个问题的性质是什么？它的重要性何在？</h1>
<ol>
<li>对于传统方法的改进，解决掉了传统的 sampling 方法在面对高光物体时的低效问题</li>
<li>重要性：
<ol>
<li>计算制造、计算成像、遥感
<ol>
<li>不过感觉高光这件事在成像上重要一些，遥感这种远场的情况很少出现高光</li>
</ol>
</li>
<li>完善了以往的方法，使得整个 BSDF 的对偶采样框架有更好的普适性</li>
</ol>
</li>
</ol>
<h1 id="3-这篇文章致力于证明什么假设">3. 这篇文章致力于证明什么假设？</h1>
<p>利用了对偶采样的蒙特卡洛算法能够很好的估计<strong>内部积分</strong>，从而使得整个采样框架具有更好的效率和普适性</p>
<h1 id="4-有哪些与这篇文章相关的研究这一领域有哪些关键人物">4. 有哪些与这篇文章相关的研究？这一领域有哪些关键人物？</h1>
<ol>
<li>本文的作者（Zhao Shuang）就是专门做可微渲染的，在去年的 SIGGRAPH20 上给了一个可微渲染的 course，CVPR21 又给了一个 tutorial talk</li>
<li>Wenzel Jakob, 开发了 mitsuba2 的团队，mitsuba2 主要解决了可微渲染中高性能 auto diff 的问题</li>
<li>还有 Tzu-Mao Li 老师</li>
</ol>
<h1 id="5-这篇文章提出的问题解决方案中核心贡献是什么">5. 这篇文章提出的问题解决方案中，核心贡献是什么？</h1>
<ol>
<li>
<p>面对高光表面，蒙特卡洛为什么慢？</p>
<ol>
<li>When 𝐹 contains high-magnitude positive and negative regions, estimating 𝐼 using Monte Carlo methods with independent samples can suffer from very slow convergence.</li>
<li>简单说就是当被积分的函数包含尺度很大的正负区域的时候，蒙特卡洛方法很难收敛</li>
<li>而高光区域就是这个特点，所以难以快速收敛</li>
</ol>
</li>
<li>
<p>如何加速蒙特卡洛采样？</p>
<ol>
<li>如果被采样的函数是一个<strong>偶函数</strong>，那么一般采用对偶采样的方法，可以大大降低所需的样本数（因为样本的方差变小了）</li>
</ol>
</li>
<li>
<p>为什么可以用对偶采样？</p>
<ol>
<li>
<p>采样的函数需要是偶函数</p>
</li>
<li>
<p>Our key observation is that geometric derivatives of BSDFs, under certain parameterizations, are approximately odd functions.</p>
<ol>
<li>
<p>为什么呢？</p>
<ol>
<li>
<p>首先作者使用的是一个 microfacet 的 BSDF 函数</p>
<p>$$f_s(\omega_\text{i},\omega_\text{o})=D(\omega_\text{h})f_s^{(0)}(\omega_\text{i},\omega_\text{o})$$</p>
<p>D 是正态分布函数，omega_h 是半向量</p>
<p>将这个BSDF函数求导得到：</p>
<p><img loading="lazy" src="/2022-02-15_Dual_Diff.assets/Untitled.png" alt="Untitled.png"  />
</p>
<p>其中的 $f_s^{(0)}$ 和 $d_{f_s}/d\theta$ 很少变化，而 D 在高光区域变化非常大</p>
</li>
</ol>
<p>因此作者提出：</p>
<ol>
<li>
<p>Beckmann、GGX 等常见模型里，D 都是对称的</p>
</li>
<li>
<p>而且在一个局部坐标系里，如果按照 z 轴对齐，D 更是偶函数了</p>
<p>下图是他们对于这个 insight 可视化的结果</p>
<p><img loading="lazy" src="/2022-02-15_Dual_Diff.assets/Untitled_1.png" alt="Untitled%201.png"  />
</p>
</li>
</ol>
</li>
</ol>
</li>
</ol>
</li>
<li>
<p>核心算法：</p>
<p><img loading="lazy" src="/2022-02-15_Dual_Diff.assets/Untitled_2.png" alt="Untitled%202.png"  />
</p>
<p>注意：对偶采样只有在高光部分才会使用，这个是文章的 algorithm 2 主要表明的 idea</p>
</li>
<li>
<p>光路的对偶采样</p>
<p>作者发现对偶采样技术可以适配到 path-level</p>
<ol>
<li>
<p>单向 unidirectional</p>
<p>就是在每个高光的地方做一次对偶，比如下图中就是p3和p4</p>
<p><img loading="lazy" src="/2022-02-15_Dual_Diff.assets/Untitled_3.png" alt="Untitled%203.png"  />
</p>
</li>
<li>
<p>双向 bidirectional</p>
<p><img loading="lazy" src="/2022-02-15_Dual_Diff.assets/Untitled_4.png" alt="Untitled%204.png"  />
</p>
<p>通过对偶采样一个对偶的 source path 和一个对偶的 detector path（图里没画），然后普通的path 和对偶的 path 都要连起来</p>
</li>
</ol>
</li>
</ol>
<h1 id="6-实验是如何设计的">6. 实验是如何设计的？</h1>
<ol>
<li>
<p>Differential rendering comparison</p>
<p>可微部分，比较 Equal quality &amp; Equal time 下的微分结果</p>
<p>作者选用了 6 个带有高光的场景（4个各向同性的 BSDF，2个各向异性的 BRDF），并整合了 edge sampling、unidirectional、bidirectional 等技术，在上面对比使用和不使用对偶采样的效果</p>
</li>
<li>
<p>Inverse-rendering comparison</p>
<p>使用对偶采样得到的微分结果进行逆向渲染，在 bunny、杯子、爱因斯坦画像上进行逆向渲染。</p>
</li>
</ol>
<h1 id="7-实验是在什么样的数据集基础上运行的读文章的人是否能接触到文中所用的数据集">7. 实验是在什么样的数据集基础上运行的？读文章的人是否能接触到文中所用的数据集？</h1>
<p>全都是 CG 里的经典物体/场景了，比如 Cornell Box、Stanford bunny</p>
<h1 id="8-实验结果能否有力地支持假设">8. 实验结果能否有力地支持假设？</h1>
<p>可以。</p>
<ol>
<li>微分结果上：无论是相同时间比质量，还是相同质量比时间，都是吊打以往的方法</li>
<li>逆向渲染上：传统方法会因高光处的噪声太多导致无法平滑的收敛，而加入了对偶渲染的技术之后，收敛的速度和结果都好很多</li>
</ol>
<h1 id="9-这篇文章的贡献是什么">9. 这篇文章的贡献是什么？</h1>
<p>作者发现对于高光表面，其BSDF函数往往在局部是偶函数，因此使用对偶采样可以加速蒙特卡洛采样的收敛速度，从而加快求导的速度。</p>
<h1 id="10-下一步可以做什么">10. 下一步可以做什么？</h1>
<ol>
<li>对偶采样与其他技术都是正交的，也就是说可以整合更多的前向渲染中的技术进来</li>
<li>对偶采样只解决了内部积分的问题，高光材质的<strong>边界积分</strong>估计还没被解决</li>
</ol>
]]></content:encoded>
    </item>
    <item>
      <title>[Paper Reading] Efficient Reflectance Capture Using an Autoencoder</title>
      <link>https://blog.chong-zeng.com/posts/2021-08-05_efficient-reflectance-capture-using-an-autoencoder/</link>
      <pubDate>Thu, 05 Aug 2021 00:00:00 +0000</pubDate>
      <guid>https://blog.chong-zeng.com/posts/2021-08-05_efficient-reflectance-capture-using-an-autoencoder/</guid>
      <description>1 导言 从现实世界中采集高精度的材质信息是一件非常重要而又非常具有挑战性的问题。这个问题可以被建模为空间变化的双向反射分布函数（SVBRDF）的采集，即一个六维的随位置、光照、视角变化而变化的函数。直接采集一个未知的 SVBRDF 函数需要上千张照片，因为你需要足够多的样本去涵盖所有可能的位置、光照、视角，这也直接导致了直接采集在时间和储存上的高成本。
为此，人们开展了很多关于提升采集效率的工作。一类主流的方法就是通过设计精巧的光照模式来实现采样的”并行化“，即在一次拍摄中尽可能采集更多的组合。但是即便是此前最好的解决方案（Guojun Chen, 2014. Reflectance Scanning: Estimating Shading Frame and BRDF with Generalized Linear Light Sources），也需要采集上百张照片。这使得这项技术在落地时仍然遇到巨大的困难。
为此，论文作者提出两个基于光照模式的反射采集方法的根本性问题：
在光照模式的数量有限的情况下，到底什么光照模式是最优的？ 如何从这些模式下采集的照片中，还原出原本的物体？ 以往的工作对于前两个问题的回答都是手工操作，也就是通过手工推导来设计各种复杂的光照模式，然后再解算出重建的方法。但是这样的方法有两个问题：1. 光照模式的数量往往取决于推导的方法，而无法任意根据所需的精度进行选择；2. 这些光照模式并没有在足够多的实际数据中进行其有效性的验证。
因此，论文作者选择使用数据驱动的方法，自动从大量真实物体的材质数据中学到最优的光照模式。
2 相关工作 2.1 直接采样 直接采样就是通过遍历 SVBRDF 的不同参数组合，来重建出整个 SVBRDF 函数。这一系列的工作精度非常的高，但工作量也非常的大，耗时很久，效率很低。
2.2 优化采样 这一方向主要是是增加假设来对于 BRDF 采样本身进行优化，比如 Matusik 等人通过假设一个任意的 BRDF 函数都落在一个预先捕捉好的各向同性的子空间中，成功将采样数量降低到了 800 张。而 Nielsen 等人通过一个能够优化光照和视角的改进算法，将采样数量降低到了 20 张。Xu 等人在 2016 年甚至通过在近场相机忽略掉视角的变化，将采样数降低到了 2 张，并通过假设表面没有法向的变化，将方法拓展到了各向同性的 SVBRDF 上。
2.3 复杂光照模式 但是增加假设的方法对于真实世界中的绝大多数情况都是不具有拓展性的，因此另一个方向是优化采集本身的效率。[Gardener et al. 2003; Ghosh et al. 2009; Aittala et al.</description>
      <content:encoded><![CDATA[<h1 id="1-导言">1 导言</h1>
<p>从现实世界中采集高精度的材质信息是一件非常重要而又非常具有挑战性的问题。这个问题可以被建模为空间变化的双向反射分布函数（SVBRDF）的采集，即一个六维的随位置、光照、视角变化而变化的函数。直接采集一个未知的 SVBRDF 函数需要上千张照片，因为你需要足够多的样本去涵盖所有可能的位置、光照、视角，这也直接导致了直接采集在时间和储存上的高成本。</p>
<p>为此，人们开展了很多关于提升采集效率的工作。一类主流的方法就是通过设计精巧的光照模式来实现采样的”并行化“，即在一次拍摄中尽可能采集更多的组合。但是即便是此前最好的解决方案（Guojun Chen, 2014. Reflectance Scanning: Estimating Shading Frame and BRDF with Generalized Linear Light Sources），也需要采集上百张照片。这使得这项技术在落地时仍然遇到巨大的困难。</p>
<p>为此，论文作者提出两个基于光照模式的反射采集方法的根本性问题：</p>
<ol>
<li>在光照模式的数量有限的情况下，到底什么光照模式是最优的？</li>
<li>如何从这些模式下采集的照片中，还原出原本的物体？</li>
</ol>
<p>以往的工作对于前两个问题的回答都是手工操作，也就是通过手工推导来设计各种复杂的光照模式，然后再解算出重建的方法。但是这样的方法有两个问题：1. 光照模式的数量往往取决于推导的方法，而无法任意根据所需的精度进行选择；2. 这些光照模式并没有在足够多的实际数据中进行其有效性的验证。</p>
<p>因此，论文作者选择使用<strong>数据驱动</strong>的方法，<strong>自动</strong>从大量真实物体的材质数据中学到最优的光照模式。</p>
<h1 id="2-相关工作">2 相关工作</h1>
<h2 id="21-直接采样">2.1 直接采样</h2>
<p>直接采样就是通过遍历 SVBRDF 的不同参数组合，来重建出整个 SVBRDF 函数。这一系列的工作精度非常的高，但工作量也非常的大，耗时很久，效率很低。</p>
<h2 id="22-优化采样">2.2 优化采样</h2>
<p>这一方向主要是是增加假设来对于 BRDF 采样本身进行优化，比如 Matusik 等人通过假设一个任意的 BRDF 函数都落在一个预先捕捉好的各向同性的子空间中，成功将采样数量降低到了 800 张。而 Nielsen 等人通过一个能够优化光照和视角的改进算法，将采样数量降低到了 20 张。Xu 等人在 2016 年甚至通过在近场相机忽略掉视角的变化，将采样数降低到了 2 张，并通过假设表面没有法向的变化，将方法拓展到了各向同性的 SVBRDF 上。</p>
<h2 id="23-复杂光照模式">2.3 复杂光照模式</h2>
<p>但是增加假设的方法对于真实世界中的绝大多数情况都是不具有拓展性的，因此另一个方向是优化采集本身的效率。[Gardener et al. 2003; Ghosh et al. 2009; Aittala et al. 2013] 等三篇论文都尝试通过使用复杂的照明模式来实现光路复用，不过这几篇文章的作者都是手工设计的照明模式。</p>
<h2 id="24-深度学习辅助的反射建模">2.4 深度学习辅助的反射建模</h2>
<p>[Aittala et al. 2016; Li et al. 2017] 两篇工作采用了深度学习来辅助反射建模。Aittala 等人使用单视角的闪光单张照片来建模各向同性的 SVBRDF 和表面法向。Li 等人的工作则能够使用未知的自然光照下的单张照片实现反射建模，通过一个基于 CNN 的网络，经过自增强训练，重建出材质的 SVBRDF 函数。</p>
<h1 id="3-核心框架">3 核心框架</h1>
<h2 id="31-问题形式化">3.1 问题形式化</h2>
<h3 id="311-假设条件">3.1.1 假设条件</h3>
<p>不失一般性，我们假设有一个近场光源，光源中的每一个点都可以被独立控制。装置被假设校准好且相机镜头不带偏振。需要采集的物体被假设为一个理想平面，而材质本身被表示为一个各向异性的 SVBRDF 函数，平面物体上的每个点需要进行独立的采集重建。</p>
<h3 id="312-记号">3.1.2 记号</h3>
<p>此外我们需要定义一些记号：</p>
<table>
<thead>
<tr>
<th>记号</th>
<th>含义</th>
</tr>
</thead>
<tbody>
<tr>
<td>$x_p$</td>
<td>物体样本上 $p$ 点的位置</td>
</tr>
<tr>
<td>$n_p$</td>
<td>物体样本上 $p$ 点的法向</td>
</tr>
<tr>
<td>$x_l$</td>
<td>灯珠 $l$ 的位置</td>
</tr>
<tr>
<td>$n_l$</td>
<td>灯珠 $l$ 的法向</td>
</tr>
<tr>
<td>$\omega_i$</td>
<td>世界坐标系下光照方向</td>
</tr>
<tr>
<td>$\omega_o$</td>
<td>世界坐标系下观察方向</td>
</tr>
<tr>
<td>$\omega&rsquo;_i$</td>
<td>物体坐标系下光照方向</td>
</tr>
<tr>
<td>$\omega&rsquo;_o$</td>
<td>物体坐标系下观察方向</td>
</tr>
<tr>
<td>$I(l)$</td>
<td>灯珠 $l$ 的可编程亮度，取值范围 $[0, 1]$</td>
</tr>
<tr>
<td>$\Psi$</td>
<td>描述灯珠在最大亮度时，亮度随角度的分布</td>
</tr>
<tr>
<td>$f_r$</td>
<td>二维 BRDF 切片</td>
</tr>
<tr>
<td>$\rho_d$</td>
<td>漫反射反照率</td>
</tr>
<tr>
<td>$\rho_s$</td>
<td>镜面反射反照率</td>
</tr>
<tr>
<td>$\alpha_x$</td>
<td>粗糙程度</td>
</tr>
<tr>
<td>$\omega_h$</td>
<td>半向量方向</td>
</tr>
<tr>
<td>$F$</td>
<td>菲涅耳系数</td>
</tr>
<tr>
<td>$G_\text{GGX}$</td>
<td>阴影遮罩系数</td>
</tr>
<tr>
<td>$B$</td>
<td>观测辐射值</td>
</tr>
<tr>
<td>$m$</td>
<td>Lumitexel 亮素</td>
</tr>
</tbody>
</table>
<h3 id="313-测量方程">3.1.3 测量方程</h3>
<p>这样我们就可以定义出特定光照下一点的辐射值：</p>
<p>$$
B(I, \mathbf{p})= \int \frac{1}{\left|\mathbf{x}{\mathbf{l}}-\mathbf{x}{\mathbf{p}}\right|^{2}} I(l) \Psi\left(\mathbf{x}{\mathbf{l}},-\omega_{\mathbf{i}}\right) f_{r}\left(\omega_{\mathbf{i}}^{\prime} ; \omega_{\mathbf{o}}^{\prime}, \mathbf{p}\right) \left(\omega_{\mathbf{i}} \cdot \mathbf{n}_{\mathbf{p}}\right)\left(-\omega_i\cdot n_l\right) d x_l
$$</p>
<p>其中 $\omega_i$ 可以被表示为 $\omega_i=\frac{x_l-x_p}{\left|x_l-x_p\right|}$</p>
<h3 id="314-brdf-表示">3.1.4 BRDF 表示</h3>
<p>BRDF 函数的表示形式选用了各向异性的 GGX BRDF 函数：</p>
<p>$$
f_{r}\left(\omega_{\mathrm{i}} ; \omega_{\mathbf{0}}, \mathbf{p}\right)
= \frac{\rho_{d}}{\pi}+\rho_{s} \frac{D_{\mathrm{GGX}}\left(\omega_{\mathbf{h}} ; \alpha_{x}, \alpha_{y}\right) F\left(\omega_{\mathbf{i}}, \omega_{\mathbf{h}}\right) G_{\mathrm{GGX}}\left(\omega_{\mathbf{i}}, \omega_{\mathbf{o}} ; \alpha_{\mathbf{x}}, \alpha_{\mathbf{y}}\right)}{4\left(\omega_{\mathbf{i}} \cdot \mathbf{n}\right)\left(\omega_{\mathbf{0}} \cdot \mathbf{n}\right)}
$$</p>
<p>作者选用 GGX 的考虑主要有以下三点：</p>
<ol>
<li>GGX 是一个参数化模型，且非常“紧凑”，能够表示非常广泛的材料</li>
<li>GGX 已经是 PBR （基于物理渲染）的行业标准</li>
<li>GGX 能够实现高效的实时渲染</li>
</ol>
<h3 id="315-lumitexel">3.1.5 Lumitexel</h3>
<p>亮素（亮光像素），其实就是将物体的每一个点视为一个 pixel，然后在上面储存该点在不同方向光照下的高光数据。</p>
<p>作者在 slide 里的插图对于 Lumitexel 给出了比较形象的展示：</p>
<ul>
<li>
<p>Lumitexel 本身是一个物体的客观属性，标记了物体上的一个点在受到来自某个单一方向的标准亮度光照照射时，所反射出来的光线亮度</p>
<!-- raw HTML omitted -->
</li>
<li>
<p>将 Lumitexel 与实际的光照模式直接相乘，就得到了采集到的测量结果</p>
<!-- raw HTML omitted -->
</li>
</ul>
<p>Lumitexel 形式化表示如下：
$$
m(j ; \mathbf{p})=B({I(l=j)=1, I(l \neq j)=0}, \mathbf{p})
$$
而观测到的辐射值在物理上其实就是 Lumitexel 与照明模式的点积：
$$
B(I, \mathrm{p})=\sum_{l} I(l) m(l ; \mathrm{p})
$$</p>
<h3 id="316-问题定义">3.1.6 问题定义</h3>
<p>物体材质的采集本质就是在给定物体某一点 $\text{p}$ 的参数 ${\rho_d, \rho_s, \alpha_x, \alpha_y, \text{n}, \text{t}}$ 、一批光照模式 ${I(l\text{p})}_I$ 以及对应光照模式下实际采集到的辐射值 ${B(I, \text{p})}_I$ ，求解一个未知的 BRDF 函数 $f_r$。</p>
<h2 id="32-求解思路与工作框架">3.2 求解思路与工作框架</h2>
<p>问题的本质其实已经在形式化部分给出，简单来说就是下面这张图所需要解的问题：</p>
<!-- raw HTML omitted -->
<p>其中最左边的 Lumitexel 是未知但固有存在的物理属性，中间的光照模式是需要设计的，测量值是客观测量出来的，而最右边的 BRDF 是要求解的。</p>
<p>而这本质是一个编码解码的过程：光照是对物体材质属性的物理编码，而求解就是一个解码过程，可以概括为下图：</p>
<!-- raw HTML omitted -->
<p>以往的方法无论是光照模式还是解码方式，都是手工设计的——这样会带来两个问题：模式不一定最优且模式数量难以降低，进而导致了采样效率低下。于是文章的作者创新性地提出可以使用网络来自动优化出最合适的编码解码方式。</p>
<p>一般来说，最直接的想法是解码器直接从观测值拟合到 BRDF 函数。这一设计非常端到端，但是作者意识到这个映射并不是一个单射关系，而是一个一对多的关系——一个实际的物体其实可以被多组 BRDF 参数描述，典型的就是假如某一点的镜面反射率为 0，那么在法向和漫反射率确定的情况下，其他参数可以任意变化；再比如 BRDF 中的切向 tangent 值可以为正也可以为负，而不影响其含义。这种性质对于回归模型非常不友好。</p>
<p>因此，作者决定使用自编码器 AutoEncoder，来规避这种一对多的关系；而如果对 BRDF 本身进行自编码，会需要引入相机的视角等信息，从而增加网络的复杂度，而且模型会与 BRDF 形式的耦合，每更换一个 BRDF 函数就需要重新训练整个网络；另一方面，从 Lumitexel 到 BRDF 的拟合方法已经非常成熟，并不需要用网络就可以完成；由此作者直接选用 Lumitexel 作为自编码的对象，提出了下面的工作流程：</p>
<p><img loading="lazy" src="/2021-08-05_Efficient-Reflectance-Capture-Using-an-Autoencoder.assets/image-20210627202100536.png" alt="image-20210627202100536"  />
</p>
<h2 id="33-模型结构与损失函数">3.3 模型结构与损失函数</h2>
<h3 id="331-l-dae">3.3.1 L-DAE</h3>
<!-- raw HTML omitted -->
<p>作者把这个自编码 Lumitexel 的网络称为 L-DAE (Lumitexel Deep AutoEncoder)。</p>
<p>对于 L-DAE 的编码器部分，作者将所有的照明模式视为一个 $c \times 1 \times \sharp$ 的卷积核，其中 $c$ 是 Lumitexel 的维度，而 $\sharp$ 代表光照模式的个数。这是硬件设计所产生的约束——每个卷积核的权重都对应了一颗灯珠在一种照明模式下的亮度，所以编码器必须是线性的。不过由于输入的 Lumitexel 维度其实与卷积核的第一个维度一样，整个卷积层其实与一个全连接层是等价的。</p>
<p>而对于解码器部分，由于它是直接运行在计算设备上而非物理采集设备上，所以没有任何的限制。于是作者决定不加入任何假设和先验知识，直接使用 11 层全连接层，构造出一个非线性的解码器。使得解码器能够实现非常复杂的解码任务。</p>
<p>完整的网络结果如下图所示：</p>
<!-- raw HTML omitted -->
<h3 id="332-损失函数">3.3.2 损失函数</h3>
<p>L-DAE 的损失函数包含了两个部分：自编码器的解码误差与 Lumitexel 物理意义上的硬性约束。
$$
L=L_{\text {auto }}(m)+\lambda \sum_{w \in \text { enc. }} L_{\text {barrier }}(w)
$$
自编码器的误差就是输入的 Lumitexel 与重建出来的 Lumitexel 的差异：
$$
L_{\text {auto }}(m)=\sum_{j}\left[\log (1+m(j))-\log \left(1+m_{\mathrm{gt}}(j)\right)\right]^{2}
$$
注意到作者引入了 $log$ 来缓解镜面反射所带来的高光对于损失造成过大的影响。</p>
<p>而由于 Lumitexel 每个值的取值范围都应当在 $[0, 1]$ 之间，作者引入了一个 barrier 损失来刻画对于超出物理取值范围的点的惩罚：
$$
L_{\text {barrier }}(w)=\tanh \left(\frac{w-(1-\epsilon)}{\epsilon}\right)+\tanh \left(\frac{-w+\epsilon}{\epsilon}\right)+2
$$
在实验中，作者发现 $\lambda=0.03, \epsilon=0.005$ 是一组不错的参数。</p>
<h1 id="4-采集实验">4 采集实验</h1>
<p>为了验证方法的可行性，作者进行了真实的采集实验。</p>
<h2 id="41-设备搭建">4.1 设备搭建</h2>
<p>作者首先搭建了一个近场 lightstage （我也不知道中文这个叫啥好，英文非常形象）。lightstage 的底部放置了要采集的平面物体，其他五面环绕了 LED 灯板，如下如所示：</p>
<!-- raw HTML omitted -->
<p>将灯板展开后，我们可以得到下面的图示：</p>
<!-- raw HTML omitted -->
<p>与所有的采集装置一样，整个 lightstage 对相机的内参外参畸变参数、以及灯板的位置进行了校准，得到了精确的空间位置关系。</p>
<p>另外为了实现相机快门与 LED 光照模式的同步，作者使用了 Altera（Intel） 的 Cyclone FPGA 进行高精度控制。亮度上使用了 8-bit 进行刻画，可以描述 256 种不同的亮度。由于装置是近场装置，不同角度与距离对于灯珠光线的衰减影响可以忽略不计。LED 的灯珠颜色使用了 X-Rite 校色仪进行修正。漫反射与镜面反射的尺度模糊问题使用了一个平面均匀漫反射贴片来解决。</p>
<h2 id="42-模型训练">4.2 模型训练</h2>
<p>作者使用纹理生成的方法，利用大量真实世界的物体数据，结合装置的校准结果，随机采样生成了 1,000,000,000 (1 million) 个 Lumitexel，然后交给网络进行训练。</p>
<p>网络使用了 RMSProp 作为优化器；对于编码器的权重使用了正太分布进行初始化，并翻转了为负的权重；对于解码器，使用了 xavier 算法进行初始化。</p>
<h2 id="43-其他实现细节">4.3 其他实现细节</h2>
<p>所有输入的 Lumitexel 都被减去了均值——感觉在机器学习里这是个常规操作了，不管是 PCA 还是其他降维的方法。在物理采集的时候，这个均值会乘上光照模式后在采样结果上减去，然后经过解码之后再加上。</p>
<p>BRDF 的拟合上，作者使用了一个各向异性的 GGX 模型，并使用 Levenberg-Marquardt 算法来对参数拟合出来的结果与实际结果的方差进行优化。</p>
<h1 id="5-实验结果">5 实验结果</h1>
<h2 id="51-时间消耗">5.1 时间消耗</h2>
<p>网络的训练大约持续了 5 小时；训练好的模型编码速度（硬件采集拍摄）大概在 12~25 秒（取决于材质所需的曝光时间以及选用的光照模式数量）；每 1M 大小的 Lumitexel 大约需要 4 分钟解码和 1.6 小时来进行最后的 BRDF 拟合。</p>
<h2 id="52-光照模式">5.2 光照模式</h2>
<p>将模型学习到的线性编码器的每一个模式可视化出来，可以得到下面的一张图：图片从上到下每一列分别是各向异性样本的学习结果、各向同性样本的学习结果、PCA 降维直接得到的结果。可以明显看到这些光照模式都非常复杂，不是人能轻易设计出来的；而模型学习出来的模式是最复杂的。</p>
<!-- raw HTML omitted -->
<h2 id="53-拍摄结果">5.3 拍摄结果</h2>
<p>使用训练出来的光照模式进行采集拍摄，所有的拍摄照片使用两张 SDR 照片合成出一张 HDR 照片，以获得更广泛的亮度范围。</p>
<p>将不同的光照模式拍摄得到的照片与光照模式一起并排放置，可以得到下面的结果：</p>
<!-- raw HTML omitted -->
<p>可以看到，每一张照片看起来都非常不同，这也充分说明这一方法采集的效率之高，在很少的几张照片里涵盖了尽可能多的信息。</p>
<h2 id="54-重建结果">5.4 重建结果</h2>
<p>经过非线性解码和 BRDF 拟合，可以得到下面的重建结果：</p>
<!-- raw HTML omitted -->
<p>其中最后一行是重建结果与 ground truth 的差异，可以看到差异非常的小，说明这一方法的采集精度也非常的高。</p>
<h2 id="55-对比实验">5.5 对比实验</h2>
<h3 id="551-降维策略对比">5.5.1 降维策略对比</h3>
<p>对比 DAE 编码器+非线性解码器、PCA 编码器 + 非线性解码器、DAE 编码器 + 线性解码器、PCA 编码器 + 非线性解码器，可以看到 DAE 编码器+非线性解码器的重建结果是最好的。</p>
<!-- raw HTML omitted -->
<h3 id="552-光照模式数量的影响对比">5.5.2 光照模式数量的影响对比</h3>
<p>调整光照模式的数量，可以看到数量越多，模型训练的 loss 越小，重建效果也越好。</p>
<!-- raw HTML omitted -->
<p>重建结果也映证了这一点：</p>
<!-- raw HTML omitted -->
<h3 id="553-鲁棒性">5.5.3 鲁棒性</h3>
<p>作者增加了不同的高斯噪声，来模拟拍摄时引入的噪声。拟合结果显示这一方法对于不同程度的噪声都表现出很强的抵抗性。</p>
<!-- raw HTML omitted -->
<h3 id="554-训练数据集分布">5.5.4 训练数据集分布</h3>
<p>作者还对比了对于某一个给定的样本，使用不同的训练数据会对采样效率产生什么样的影响。从左到右分别是基准方法（直接采样）、使用了各向异性的样本、使用了各向同性的样本、以及将待采集的样本放入训练集中所需要的光照模式数量。</p>
<!-- raw HTML omitted -->
<p>可以看出，为了达到相同的重建效果，预设的信息越多、需要采集的信息就越少、从而使得光照模式数量变少。</p>
<h1 id="6-局限和展望">6 局限和展望</h1>
<p>这一方法有以下局限：</p>
<ol>
<li>
<p>由于使用了数据驱动的编码器设计方法，所以在面对与数据集显著不同的数据时，模型的重建结果会非常的差，比如下图中的双向高光，就难以被重建：</p>
<!-- raw HTML omitted -->
</li>
<li>
<p>这一方法现在还是只能采集平面物体</p>
</li>
<li>
<p>这一方法目前只利用到了一个视角</p>
</li>
</ol>
<p>不过作者在后一年的 SIGGRAPH Asia 19 上的论文解决了后两个问题，实现了基于多视角的立体物体的采集重建。</p>
<p>未来作者表示还会尝试适配这套方法到远场 lightstage、相机视角设计、以及基于图片的重光照问题。</p>
]]></content:encoded>
    </item>
    <item>
      <title>OptiX 入门笔记</title>
      <link>https://blog.chong-zeng.com/posts/2021-08-01_optix/</link>
      <pubDate>Sun, 01 Aug 2021 00:00:00 +0000</pubDate>
      <guid>https://blog.chong-zeng.com/posts/2021-08-01_optix/</guid>
      <description>这其实是我大三上图形学大作业的报告，最近整理本科期间的项目，于是把报告里面比较关于 OptiX 的部分拿出来水篇博客做个笔记。
个人认为 API 没有什么讲的价值，所以博客里更多是讲讲关于 OptiX 的编程模型/思想。
另外有关光追基本知识的部分此处也不过多赘述。
1 基本架构 OptiX 的主要结构如上图所示，由光追渲染管线、加速结构、着色器表及相关资源构成。
值得注意的是，OptiX 其实只负责了渲染的部分，也就是说每次 OptiX 程序运行完成后返回的都是一帧渲染好的图像，而建模、交互，甚至包括画面的显示，都不是 OptiX 所负责的。你可以搭配 OpenGL 之类的来完成这些显示窗口的维护和交互工作。
1.1 光追渲染管线 光追渲染管线是整个光追的核心，它负责了光线的发射、相交的检测、每条光线的着色，以及这些全部计算的调度 1.2 加速结构 加速结构 (Acceleration Structure) 加速的其实是相交检测，OptiX 中使用加速结构来标记物体的每个面，然后计算的就是每条光线与加速结构的相交情况 加速结构本身是一个树形的结构，使用加速结构可以加速光线相交检测的遍历 在注册完全部的加速结构后，OptiX 会编译一个查询表，通过这个加速表可以实现非常高效的相交检测 但是需要注意的是，当建模发生变化的时候，加速结构就会发生变化，进而导致查询表的重新编译，所以在 OptiX 中，modeling 的变化会使得计算压力增大 1.3 着色器表 着色器表 (Shader Table) 中储存了各种与最后的着色有关的资源的索引，可以用于索引一次光线追踪中可能用到的所有资源，比如材质、纹理、法向等，通过着色器表，我们可以快速的获取到这些资源，然后完成相关的计算 每次渲染时，由光追渲染管线调度光线的发射，当光线发生相交后，加速结构给出发生相交处的物体的属性索引，然后我们在着色器表中按照索引查找相关的属性和资源，再交给着色器进行最后的着色，就得到了这个像素上这条光线渲染出来的结果。
2 光追可编程渲染管线 与光栅化一样，光追的渲染管线也是可编程的。光追的渲染管线在前面已经解释，其中可以编程的主要是光线发射、相交检测、着色三个部分。
2.1 光线发射 OptiX 可以实现比较复杂的光线发射，指向针对光源进行重要性采样，不过在我们这儿因为场景足够亮，所以没有做相关的定制。
2.2 相交检测 相交检测背后的算法是二叉树 BVH (Bounding Volume Hierachy)，是空间切分技术之一。使用树形组织的加速结构，可以加速相交检测的计算。但是即便如此，依然是一个开销非常大的计算，在没有 RT Core 的传统 GPU 上，只能通过软件模拟的方法实现相关的计算。
而在 RTX GPU 上，这一算法有相关的硬件实现，因此可以得到非常高的运行效率。
在 OptiX 中直接提供的加速结构只有三角网格结构，不过三角网格的建模能力已经非常强了，所以暂时也没有新增其他结构的需求。</description>
      <content:encoded><![CDATA[<blockquote>
<p>这其实是我大三上图形学大作业的报告，最近整理本科期间的项目，于是把报告里面比较关于 OptiX 的部分拿出来<del>水篇博客</del>做个笔记。</p>
<p>个人认为 API 没有什么讲的价值，所以博客里更多是讲讲关于 OptiX 的编程模型/思想。</p>
<p>另外有关光追基本知识的部分此处也不过多赘述。</p>
</blockquote>
<h1 id="1-基本架构">1 基本架构</h1>
<p><img loading="lazy" src="/2021-08-01_OptiX.assets/image-20210115205001513.png" alt="image-20210115205001513"  />
</p>
<p>OptiX 的主要结构如上图所示，由光追渲染管线、加速结构、着色器表及相关资源构成。</p>
<p>值得注意的是，OptiX 其实只负责了渲染的部分，也就是说每次 OptiX 程序运行完成后返回的都是一帧渲染好的图像，而建模、交互，甚至包括画面的显示，都不是 OptiX 所负责的。你可以搭配 OpenGL 之类的来完成这些显示窗口的维护和交互工作。</p>
<h2 id="11-光追渲染管线">1.1 光追渲染管线</h2>
<p><img loading="lazy" src="/2021-08-01_OptiX.assets/image-20210115200919276.png" alt="image-20210115200919276"  />
</p>
<ul>
<li>光追渲染管线是整个光追的核心，它负责了光线的发射、相交的检测、每条光线的着色，以及这些全部计算的调度</li>
</ul>
<h2 id="12-加速结构">1.2 加速结构</h2>
<p><img loading="lazy" src="/2021-08-01_OptiX.assets/image-20210115213337256.png" alt="image-20210115213337256"  />
</p>
<ul>
<li>加速结构 (Acceleration Structure) 加速的其实是相交检测，OptiX 中使用加速结构来标记物体的每个面，然后计算的就是每条光线与加速结构的相交情况</li>
<li>加速结构本身是一个树形的结构，使用加速结构可以加速光线相交检测的遍历</li>
<li>在注册完全部的加速结构后，OptiX 会编译一个查询表，通过这个加速表可以实现非常高效的相交检测</li>
<li>但是需要注意的是，当建模发生变化的时候，加速结构就会发生变化，进而导致查询表的重新编译，所以在 OptiX 中，modeling 的变化会使得计算压力增大</li>
</ul>
<h2 id="13-着色器表">1.3 着色器表</h2>
<p><img loading="lazy" src="/2021-08-01_OptiX.assets/image-20210115213438107.png" alt="image-20210115213438107"  />
</p>
<ul>
<li>着色器表 (Shader Table) 中储存了各种与最后的着色有关的资源的索引，可以用于索引一次光线追踪中可能用到的所有资源，比如材质、纹理、法向等，通过着色器表，我们可以快速的获取到这些资源，然后完成相关的计算</li>
</ul>
<p>每次渲染时，由光追渲染管线调度光线的发射，当光线发生相交后，加速结构给出发生相交处的物体的属性索引，然后我们在着色器表中按照索引查找相关的属性和资源，再交给着色器进行最后的着色，就得到了这个像素上这条光线渲染出来的结果。</p>
<h1 id="2-光追可编程渲染管线">2 光追可编程渲染管线</h1>
<p>与光栅化一样，光追的渲染管线也是可编程的。光追的渲染管线在前面已经解释，其中可以编程的主要是<strong>光线发射</strong>、<strong>相交检测</strong>、<strong>着色</strong>三个部分。</p>
<h2 id="21-光线发射">2.1 光线发射</h2>
<p>OptiX 可以实现比较复杂的光线发射，指向针对光源进行重要性采样，不过在我们这儿因为场景足够亮，所以没有做相关的定制。</p>
<h2 id="22-相交检测">2.2 相交检测</h2>
<p><a href="https://github.com/iamNCJ/CG-Project/blob/main/report/report.assets/image-20210115213550410.png"><img loading="lazy" src="/2021-08-01_OptiX.assets/image-20210115213550410.png" alt="image-20210115213550410"  />
</a></p>
<p>相交检测背后的算法是<strong>二叉树 BVH</strong> (Bounding Volume Hierachy)，是空间切分技术之一。使用树形组织的加速结构，可以加速相交检测的计算。但是即便如此，依然是一个开销非常大的计算，在没有 RT Core 的传统 GPU 上，只能通过软件模拟的方法实现相关的计算。</p>
<p><img loading="lazy" src="/2021-08-01_OptiX.assets/image-20210115213859517.png" alt="image-20210115213859517"  />
</p>
<p>而在 RTX GPU 上，这一算法有相关的硬件实现，因此可以得到非常高的运行效率。</p>
<p><img loading="lazy" src="/2021-08-01_OptiX.assets/image-20210115213943505.png" alt="image-20210115213943505"  />
</p>
<p>在 OptiX 中直接提供的加速结构只有三角网格结构，不过三角网格的建模能力已经非常强了，所以暂时也没有新增其他结构的需求。</p>
<h2 id="23-着色">2.3 着色</h2>
<p><a href="https://github.com/iamNCJ/CG-Project/blob/main/report/report.assets/image-20210115205029106.png"><img loading="lazy" src="/2021-08-01_OptiX.assets/image-20210115205029106.png" alt="image-20210115205029106"  />
</a></p>
<p>在光线发生与物体的相交后，OptiX 就会调用相关的着色器开始进行颜色的计算。这一部分也是我们对于渲染管线定制最大的部分。</p>
<p>所有的着色器所干的事情，都是根据相交点的相交类型及相关信息，计算该束光应该拥有什么颜色。</p>
<h3 id="231-最近相交-closest-hit">2.3.1 最近相交 (Closest Hit)</h3>
<p>最近相交，顾名思义就是所有相交中距离相机最近的一个。这样就自然实现了深度检测，而不需要 Z-buffer 之类的辅助。</p>
<h3 id="232-任意相交-any-hit">2.3.2 任意相交 (Any Hit)</h3>
<p>与最近相交不同，任意相交就是所有可以与光线发生相交的地方被调用的着色函数。下面的图非常形象的展示了两者的关系，其中上半部分是 Any Hit，下半部分是 Closest Hit。</p>
<p><img loading="lazy" src="/2021-08-01_OptiX.assets/image-20210115215816573.png" alt="image-20210115215816573"  />
</p>
<h3 id="233-无相交-miss">2.3.3 无相交 (Miss)</h3>
<p>假如光线没有与任何加速结构发生相交，那么最后它将打到无穷远处，进而弱到无法获得任何亮度和颜色。我们可以利用这种情况实现天空盒。</p>
]]></content:encoded>
    </item>
    <item>
      <title>NeRF-Related Review 2020</title>
      <link>https://blog.chong-zeng.com/posts/2021-02-24_nerf/</link>
      <pubDate>Sun, 27 Dec 2020 00:00:00 +0000</pubDate>
      <guid>https://blog.chong-zeng.com/posts/2021-02-24_nerf/</guid>
      <description>2020 年，在 CV/CG 界，一篇叫做 NeRF 的论文爆火，“只需要输入少量静态图片，就能做到多视角的逼真3D效果。”但是实际上，在这篇论文之前，学术界已经有不少这方面的尝试，相关的研究也有不少，因此本文尝试做一个简单的综述，来简单看看这篇论文及其相关的研究。
〇、背景：建模（表面、体积） &amp;amp; 渲染 众所周知，计算机图形学中一个长期研究目标就是将虚拟的世界尽可能的渲染的真实。这里面包括了三个方面：
建模：通过表面建模、曲面建模等方式，将真实世界中的场景在虚拟世界中还原出来 渲染：按照物理中光照的规律，将虚拟世界中建好的模型绘制成人眼可见的画面 动画：通过仿真等方式，模拟出物体真实的运动轨迹等，使得动画看起来更加自然 NeRF 及相关工作所尝试解决的，主要是建模与渲染部分，也就是重建。建模的本质，其实是构造出一个空间中描述物体的函数：传统的建模大多采用显式的表示，比如曲线、曲面等等，或是球体、长方体；而近年来，随着神经网络的发展，有人提出能否使用神经网络来表示这一函数，毕竟神经网络本质上就是一个隐式函数，只不过其形式更加复杂、表示能力也更强。
在三维建模中，两个非常重要的通用建模方式是表面建模和体积建模：表面建模是通过描述表面曲面的方式构建模型，而体积建模则是通过描述空间点（体素）的方式构建模型；在表面建模里没有三维实体，实体只是闭合表面；在体积建模里没有二维表面，表面只是很薄的体素。学界在神经网络建模方面，也进行了类似的尝试，即使用神经网络来表示曲面（神经隐式曲面）和使用神经网络表示体积（神经隐式体积）。基于这两个大的思想，人们逐渐设计出各式各样的网络，并得到了越来越好的效果。
当然，建模之后，如果不能够进行渲染是没有意义的，因此如何高效地渲染出这些隐式表示的模型，也是学术界非常热门的话题。
一、序章：神经隐式曲面 1.1 基于分类的网络 第一大类的尝试，就是使用神经网络来表示曲面（Neural Implicit Surfaces）。前面提到，对于一个物体，实际上就是一个闭合的曲面，因此最直白的表示方法，就是给空间中的点进行分类，标记它在曲面内、还是曲面外。
Occupancy networks 和 IM-Net 都是基于这一思想的，两者主要是网络内部结构上不同，但是输入都是一个特征向量和一个空间点坐标，输出都是一个布尔值：在曲面内或在曲面外。下图是 IM-Net 的网络结构，以作示例：
另外还有将纹理特征一并结合的网络，如 PIFu：它除了编码了每个点是 inside 还是 outside，还将每个点的颜色信息也通过网络编码，从而实现了完整的高分辨率的着装人体数字化重建。
1.2 基于回归的网络 使用分类模型进行的表面建模确实是一个非常大的创新，但是一个很大的缺点就是这个模型所表示的函数并不可导——它不是连续的，毕竟物体内外这一输出本身就决定了函数的值域是一个离散的二值。因此，人们尝试使用一个连续的表示方式：有符号距离场，也就是大名鼎鼎的 SDF。
SDF 的定义很简单，其数值就是空间中的一个点距离曲面最近的距离，而符号表示其在闭合曲面的内部还是外部。这样通过一个有符号数，就将两个信息一起编码进去了，并且得到了一个在空间上可导的量。
SDF 的形式化定义如下：
DeepSDF 那么这样一个函数，非常自然的想到使用神经网络的 regression 进行解决，这也是 DeepSDF 的主要思想 —— 将一个描述物体形状特征的 Code 和空间坐标一并放入网络，然后输出该点的 SDF，从而实现利用深度网络重建一系列同类的物体。
值得关注的一点是，这个特征 Code 的特征是利用 Auto-decoder （注意不是 Auto-encoder）优化提炼的，作者们称之为 Encoder-less Learning，因为他们觉得 encoder 在推导的时候并没有被用到，所以不如不要，实际的重建效果也是非常的好，感觉是个非常有意思的想法。
DeepSDF 的诞生彻底引爆了这个领域，此后涌现出了大量相关的工作，如达摩院的 Curriculum DeepSDF 以及伯克利的 Extending DeepSDF，DeepSDF 本身也成为了不少工作的 baseline。</description>
      <content:encoded><![CDATA[<p>2020 年，在 CV/CG 界，一篇叫做 NeRF 的论文爆火，“只需要输入少量静态图片，就能做到多视角的逼真3D效果。”但是实际上，在这篇论文之前，学术界已经有不少这方面的尝试，相关的研究也有不少，因此本文尝试做一个简单的综述，来简单看看这篇论文及其相关的研究。</p>
<h2 id="背景建模表面体积--渲染">〇、背景：建模（表面、体积） &amp; 渲染</h2>
<p>众所周知，计算机图形学中一个长期研究目标就是将虚拟的世界尽可能的渲染的真实。这里面包括了三个方面：</p>
<ol>
<li><strong>建模</strong>：通过表面建模、曲面建模等方式，将真实世界中的场景在虚拟世界中还原出来</li>
<li><strong>渲染</strong>：按照物理中光照的规律，将虚拟世界中建好的模型绘制成人眼可见的画面</li>
<li><strong>动画</strong>：通过仿真等方式，模拟出物体真实的运动轨迹等，使得动画看起来更加自然</li>
</ol>
<p>NeRF 及相关工作所尝试解决的，主要是建模与渲染部分，也就是重建。建模的本质，其实是构造出一个空间中描述物体的<strong>函数</strong>：传统的建模大多采用显式的表示，比如曲线、曲面等等，或是球体、长方体；而近年来，随着神经网络的发展，有人提出能否<strong>使用神经网络来表示这一函数</strong>，毕竟神经网络本质上就是一个隐式函数，只不过其形式更加复杂、表示能力也更强。</p>
<p>在三维建模中，两个非常重要的通用建模方式是表面建模和体积建模：表面建模是通过描述表面曲面的方式构建模型，而体积建模则是通过描述空间点（体素）的方式构建模型；在表面建模里没有三维实体，实体只是闭合表面；在体积建模里没有二维表面，表面只是很薄的体素。学界在神经网络建模方面，也进行了类似的尝试，即使用神经网络来表示曲面（<strong>神经隐式曲面</strong>）和使用神经网络表示体积（<strong>神经隐式体积</strong>）。基于这两个大的思想，人们逐渐设计出各式各样的网络，并得到了越来越好的效果。</p>
<p>当然，建模之后，如果不能够进行渲染是没有意义的，因此如何高效地渲染出这些隐式表示的模型，也是学术界非常热门的话题。</p>
<h2 id="一序章神经隐式曲面">一、序章：神经隐式曲面</h2>
<h3 id="11-基于分类的网络">1.1 基于分类的网络</h3>
<p>第一大类的尝试，就是使用神经网络来表示曲面（Neural Implicit Surfaces）。前面提到，对于一个物体，实际上就是一个闭合的曲面，因此最直白的表示方法，就是给空间中的点进行分类，标记它在曲面内、还是曲面外。</p>
<p><img loading="lazy" src="/2021-02-24_NeRF.assets/ON-teaser.png" alt="Occupancy as a learned classifier"  />
</p>
<p><strong>Occupancy networks</strong> 和 <strong>IM-Net</strong> 都是基于这一思想的，两者主要是网络内部结构上不同，但是输入都是一个特征向量和一个空间点坐标，输出都是一个布尔值：在曲面内或在曲面外。下图是 IM-Net 的网络结构，以作示例：</p>
<p><img loading="lazy" src="/2021-02-24_NeRF.assets/image-20210222182017395.png" alt="image-20210222182017395"  />
</p>
<p>另外还有将纹理特征一并结合的网络，如 PIFu：它除了编码了每个点是 inside 还是 outside，还将每个点的颜色信息也通过网络编码，从而实现了完整的高分辨率的着装人体数字化重建。</p>
<p><img loading="lazy" src="/2021-02-24_NeRF.assets/image-20210222193033452.png" alt="image-20210222193033452"  />
</p>
<h3 id="12-基于回归的网络">1.2 基于回归的网络</h3>
<p>使用分类模型进行的表面建模确实是一个非常大的创新，但是一个很大的缺点就是这个模型所表示的函数并不可导——它不是连续的，毕竟物体内外这一输出本身就决定了函数的值域是一个离散的二值。因此，人们尝试使用一个连续的表示方式：有符号距离场，也就是大名鼎鼎的 SDF。</p>
<p><img loading="lazy" src="/2021-02-24_NeRF.assets/DeepSDF.png" alt="The Stanford bunny rendered through a learned signed distance function (SDF)"  />
</p>
<p>SDF 的定义很简单，其数值就是空间中的一个点距离曲面最近的距离，而符号表示其在闭合曲面的内部还是外部。这样通过一个有符号数，就将两个信息一起编码进去了，并且得到了一个在空间上可导的量。</p>
<p>SDF 的形式化定义如下：</p>
<p><img loading="lazy" src="/2021-02-24_NeRF.assets/equation.svg" alt="equation"  />
</p>
<h4 id="deepsdf">DeepSDF</h4>
<p>那么这样一个函数，非常自然的想到使用神经网络的 regression 进行解决，这也是 <strong>DeepSDF</strong> 的主要思想 —— 将一个描述物体形状特征的 Code 和空间坐标一并放入网络，然后输出该点的 SDF，从而实现利用深度网络重建一系列同类的物体。</p>
<p><img loading="lazy" src="/2021-02-24_NeRF.assets/image-20210222201532556.png" alt="image-20210222201532556"  />
</p>
<p>值得关注的一点是，这个特征 Code 的特征是利用 Auto-decoder （注意不是 Auto-encoder）优化提炼的，作者们称之为 Encoder-less Learning，因为他们觉得 encoder 在推导的时候并没有被用到，所以不如不要，实际的重建效果也是非常的好，感觉是个非常有意思的想法。</p>
<p><img loading="lazy" src="/2021-02-24_NeRF.assets/image-20210222202136185.png" alt="image-20210222202136185"  />
</p>
<p>DeepSDF 的诞生彻底引爆了这个领域，此后涌现出了大量相关的工作，如达摩院的 Curriculum DeepSDF 以及伯克利的 Extending DeepSDF，DeepSDF 本身也成为了不少工作的 baseline。</p>
<h4 id="overfit-sdf">Overfit SDF</h4>
<p><img loading="lazy" src="/2021-02-24_NeRF.assets/network.png" alt="network"  />
</p>
<p>根据全局逼近定理（Universal Approximation Theory），一个具有充分多隐节点和采用任何激活函数的三层前馈神经网络能以任意精度逼近任何一个连续函数，因此我们其实可以直接对采样到的离散的 SDF 数据进行过拟合——即借助外部的 latent code，直接把物体的形状编码进网络的权重，一个网络对应一个物体即可。这就是 <strong>Overfit-SDF</strong> 的思想。</p>
<p><img loading="lazy" src="/2021-02-24_NeRF.assets/image-20210222230728553.png" alt="image-20210222230728553"  />
</p>
<p>相比于 DeepSDF，Overfit-SDF 面对观察角度的变化能够获得更加鲁棒的重建效果，如下图。</p>
<p><img loading="lazy" src="/2021-02-24_NeRF.assets/image-20210222230941628.png" alt="image-20210222230941628"  />
</p>
<h3 id="13-渲染">1.3 渲染</h3>
<p>对于隐式表示，一般来说常见的渲染方式是两种：<strong>方块遍历</strong>（<strong>marching cube</strong>）和<strong>光线步进</strong>（<strong>ray marching</strong>）。也有地方把 ray marching 称为 sphere tracing，细想想确实很形象，如下图。</p>
<p><img loading="lazy" src="/2021-02-24_NeRF.assets/raymarching2.png" alt="raymarching2"  />
</p>
<p>实际上两者都是在从隐式表示中，采样表面的信息。个人认为相比起 marching cube，光线步进更能展现出这些 SDF 模型的连续性。</p>
<h4 id="131-加速">1.3.1 加速</h4>
<p>但是由于前面的这些模型的网络往往层数比较深，再加上使用了 ray marching，渲染的过程不可避免的会很慢，因此 <strong>Neural Geometric Level of Detail</strong> 这篇文章提出降低网络的深度，使用简单的一个感知机来对不同的细节层次进行自适应拟合，从而达到实时渲染的效果。</p>
<p><img loading="lazy" src="/2021-02-24_NeRF.assets/image-20210222234838118.png" alt="image-20210222234838118"  />
</p>
<p>这个工作首先使用稀疏体素八叉树（<strong>Sparse Voxel Octree, SVO</strong>）对物体的几何特征进行编码—— SVO 的不同层次实际也编码了细节的不同层次，即 <strong>LOD</strong> (Level of Detail)，而每个角点上的体素（可以先理解为一个数据结构，后面会解释）储存了局部的表面特征；在采样的时候，首先找到对应的几个体素，然后将其中储存的特征经过插值获得一个连续的特征，最后通过一个很简单的多层感知机来从这个综合出来的特征解码得到 SDF 的值。整个流程如下图所示：</p>
<p><img loading="lazy" src="/2021-02-24_NeRF.assets/image-20210222233643015.png" alt="image-20210222233643015"  />
</p>
<p>这个工作可以说是又快又好，既提高了渲染精度，又加快了渲染速度，还简化了网络结构。也许它也在启发着我们，真的复杂的就一定是最好的吗？有时候将一些已知的先验信息加入，往往可以达到事半功倍的效果。</p>
<h2 id="二爆发神经隐式体积">二、爆发：神经隐式体积</h2>
<h3 id="21-体素渲染">2.1 体素渲染</h3>
<p>但是在解释这些基于体积的建模工作之前，让我们来先看看这里的体素渲染到底是怎么回事。</p>
<blockquote>
<p>事实上，关于体素渲染和体积渲染的定义已经因为很多商业游戏公司的宣传和炒作变得模糊和混淆，因此这里介绍的体素渲染是针对这两篇论文中采用的建模方法而言的。</p>
</blockquote>
<p>所谓体素（Volume Pixel），就是体积像素的简称，与像素类似，每个体素包含了空间中一个最小分割单位中的信息，比如图片中的像素包含的是该点的 RGB 值，而体素则可以包含一个点的不透光性或者密度等。</p>
<p>基于体素的模型认为三维物体是由很多个体素构成的，每个体素包含自己的颜色和密度（或是不透明度）。那么在观察一个物体的时候，只要沿着光线方向进行积分，就可以得到这一角度所观察到的物体的最终颜色，如下图所示。</p>
<p><img loading="lazy" src="/2021-02-24_NeRF.assets/5e6942d2a99a2eb319075849_volume-rendering-diagram.jpg" alt="Diagram shows a basic diagram of volume rendering using single-pass GPU ray casting."  />
</p>
<p>实际上仔细想想这个设定其实还有点道理，比如一个物体切的无限薄，其终将呈现出半透明乃至透明的状态。而且通过这种方式建模，天然的解决了半透明物体的重建问题。</p>
<p><img loading="lazy" src="/2021-02-24_NeRF.assets/image-20210222220827030.png" alt="image-20210222220827030"  />
</p>
<p>第一个将体积渲染与神经网络相结合的是 <strong>Neural Volumes</strong>，它将一个三维的物体，拆解为一个个体素——每个体素包含了密度信息和颜色信息，这样就得到了一个基于体素的三维物体表示方法；接下来，使用一个 Encoder + Decoder 对输入的多个角度的图片进行编码和采样，就得到了一个能够重建特定物体的 latent code，并且可以从中解码出一个三维空间的 volume；接下来，在这个 volume 中使用 ray marching 进行积分采样，即可得到重建的结果。</p>
<p>训练的时候，Neural Volumes 是直接进行端到端的训练的，即输入多个角度的图像，然后拿对应角度重建的图像计算 loss。</p>
<p>“Neural Volumes 的成功很大程度上归功于这种‘半透明’的几何表示方式，因为它使得梯度能够沿着射线的积分分散开来，进而更加容易收敛到一个较好的结果上”，一篇引用了 Neural Volumes 的论文如是说。</p>
<h3 id="22-nerf">2.2 NeRF</h3>
<p><strong>NeRF</strong> 是神经辐射场（Neural Radiance Fields）的缩写，它彻底引爆了整个领域。</p>
<p>本质上来说，NeRF 与 DeepSDF 的网络结构差不多，但是与 DeepSDF 所回归的 SDF 函数不同，NeRF 回归的是体素的密度和颜色，也就是说，NeRF 将体素信息视作了一个函数，然后使用神经网络去拟合它。</p>
<p><img loading="lazy" src="/2021-02-24_NeRF.assets/image-20210222223550599.png" alt="image-20210222223550599"  />
</p>
<p>值得注意的是，NeRF 的输入是一个 5 维的向量——它包含了一个体素的位置  和观察它的角度 （所以采集的时候还要带上相机的外参），这是因为按照图形学中物体材质相关的理论，一个物体的同一位置（同一材质）在不同的光照角度之下确实会观察到不同的颜色；NeRF 考虑到了这一点，因此直接把材质信息也直接包含了进去；当然，场景的光照信息也被不可避免的烘焙了进去。</p>
<p>另外为了解决高频信息丢失的问题，比如特定角度下的高光（如下图），NeRF 对 voxel position 和 view position 都进行了 embedding，也就是把他们映射到一个高维空间中，进而大大增强了模型对于细节的重建能力。</p>
<p><img loading="lazy" src="/2021-02-24_NeRF.assets/image-20210222224836594.png" alt="image-20210222224836594"  />
</p>
<p>另外 NeRF 的渲染中还利用到了重要性采样，也就是先对一条光线上大致的密度分布进行估计，然后按照这个估计的密度曲线进行重要性采样，这样可以加快采样时收敛的速度。</p>
<p>NeRF 以其简单的原理、简单的模型、超好的重建效果引爆了整个学术界，大量基于 NeRF 的改进工作，如 Relighting、性能提升、动态场景等都被悉数完成，而大量基于 NeRF 的应用也在涌现，比如人物肖像重建、形状重建、场景组合、姿态估计等。这些 NeRF-style 的工作无一不证明着 neural volume 的巨大潜力。</p>
<h2 id="三展望">三、展望</h2>
<p>近年来，采用神经网络来代替传统表示的工作越来越多，如 SLAM 中接替 Kinect Fusion 的 Neural Fusion，再如使用网络表示纹理的 Neural Textures，还有上文的各种工作。神经网络黑箱的属性正在逐渐退去，其函数的本质正在被逐步挖掘。充分利用网络的拟合能力，并融入足够的先验知识，可能才是解锁神经网络潜力的钥匙。</p>
<p>另一方面，neural volume 相关的工作中，人们最终还是不可避免的尝试恢复表面本身，体素会不会只是一种目前效果最好的中间表示？LOD 的工作是否意味着未来人们会重新回归到基于 SDF 的方法？这些问题的答案从目前看来还是未知的。</p>
<p>令人振奋的是，这些工作基本都是近年完成的；也许随着研究的深入、资金的投入，这些问题很快就会得到解答。这一切的一切，都非常值得我们期待。</p>
<blockquote>
<h2 id="参考文献">参考文献</h2>
<ol>
<li>NeRF Explosion 2020 <a href="https://dellaert.github.io/NeRF/">https://dellaert.github.io/NeRF/</a></li>
<li>Tewari, Ayush, Ohad Fried, Justus Thies, Vincent Sitzmann, Stephen Lombardi, Kalyan Sunkavalli, Ricardo Martin-Brualla, et al. “State of the Art on Neural Rendering.” <em>ArXiv:2004.03805 [Cs]</em>, April 8, 2020. <a href="http://arxiv.org/abs/2004.03805">http://arxiv.org/abs/2004.03805</a>.</li>
<li>Mildenhall, Ben, Pratul P. Srinivasan, Matthew Tancik, Jonathan T. Barron, Ravi Ramamoorthi, and Ren Ng. “NeRF: Representing Scenes as Neural Radiance Fields for View Synthesis.” <em>ArXiv:2003.08934 [Cs]</em>, August 3, 2020. <a href="http://arxiv.org/abs/2003.08934">http://arxiv.org/abs/2003.08934</a>.</li>
<li>Williams, Jon. “Occupancy Networks: Learning 3D Reconstruction in Function Space | Autonomous Vision.” Max Planck Institute for Intelligent Systems. Accessed February 22, 2021. <a href="https://is.mpg.de">https://is.mpg.de</a>.</li>
<li>Saito, Shunsuke, Zeng Huang, Ryota Natsume, Shigeo Morishima, Angjoo Kanazawa, and Hao Li. 2019. “PIFu: Pixel-Aligned Implicit Function for High-Resolution Clothed Human Digitization.” ArXiv.org. 2019. <a href="https://arxiv.org/abs/1905.05172">https://arxiv.org/abs/1905.05172</a>.</li>
<li>Park, Jeong Joon, Peter Florence, Julian Straub, Richard Newcombe, and Steven Lovegrove. 2019. “DeepSDF: Learning Continuous Signed Distance Functions for Shape Representation.” <em>Thecvf.com</em>, 165–74. <a href="https://openaccess.thecvf.com/content_CVPR_2019/html/Park_DeepSDF_Learning_Continuous_Signed_Distance_Functions_for_Shape_Representation_CVPR_2019_paper.html">https://openaccess.thecvf.com/content_CVPR_2019/html/Park_DeepSDF_Learning_Continuous_Signed_Distance_Functions_for_Shape_Representation_CVPR_2019_paper.html</a>.</li>
<li>Davies, Thomas, Derek Nowrouzezahrai, and Alec Jacobson. “On the Effectiveness of Weight-Encoded Neural Implicit 3D Shapes.” <em>ArXiv:2009.09808 [Cs]</em>, January 17, 2021. <a href="http://arxiv.org/abs/2009.09808">http://arxiv.org/abs/2009.09808</a>.</li>
<li>Takikawa, Towaki, Joey Litalien, Kangxue Yin, Karsten Kreis, Charles Loop, Derek Nowrouzezahrai, Alec Jacobson, Morgan McGuire, and Sanja Fidler. “Neural Geometric Level of Detail: Real-Time Rendering with Implicit 3D Shapes.” <em>ArXiv:2101.10994 [Cs]</em>, January 26, 2021. <a href="http://arxiv.org/abs/2101.10994">http://arxiv.org/abs/2101.10994</a>.</li>
<li>“Neural Volumes: Learning Dynamic Renderable Volumes from Images - Facebook Research.” 2019. Facebook Research. 2019. <a href="https://research.fb.com/publications/neural-volumes-learning-dynamic-renderable-volumes-from-images/">https://research.fb.com/publications/neural-volumes-learning-dynamic-renderable-volumes-from-images/</a>.</li>
<li>Mildenhall, Ben, Srinivasan, Pratul P, Matthew Tancik, Jonathan T Barron, Ravi Ramamoorthi, and Ren Ng. 2020. “NeRF: Representing Scenes as Neural Radiance Fields for View Synthesis.” ArXiv.org. 2020. <a href="https://arxiv.org/abs/2003.08934">https://arxiv.org/abs/2003.08934</a>.</li>
<li>Weder, Silvan, Johannes L. Schönberger, Marc Pollefeys, and Martin R. Oswald. “NeuralFusion: Online Depth Fusion in Latent Space.” <em>ArXiv:2011.14791 [Cs]</em>, November 30, 2020. <a href="http://arxiv.org/abs/2011.14791">http://arxiv.org/abs/2011.14791</a>.</li>
<li>Thies, Justus, Michael Zollhöfer, and Matthias Nießner. “Deferred Neural Rendering: Image Synthesis Using Neural Textures.” <em>ArXiv:1904.12356 [Cs]</em>, April 28, 2019. <a href="http://arxiv.org/abs/1904.12356">http://arxiv.org/abs/1904.12356</a>.</li>
</ol>
</blockquote>
]]></content:encoded>
    </item>
    <item>
      <title>使用 Docker 完成 GNS3 网络实验</title>
      <link>https://blog.chong-zeng.com/posts/2020-12-27_gns3_docker/</link>
      <pubDate>Sun, 27 Dec 2020 00:00:00 +0000</pubDate>
      <guid>https://blog.chong-zeng.com/posts/2020-12-27_gns3_docker/</guid>
      <description>Dockerfile 及 Compose-file 下载：https://github.com/iamNCJ/gns3-docker
众所周知 GNS3 是全球有名的一大坨屎网络软件模拟器。广大 cs 学子为了混到学分熟练掌握计算机网络知识，常年使用 GNS3 做实验到要死要活。GNS3 采用了典型的 C/S 架构设计，其运行时需要一个 gns3-server 作为其后端，并通过 web api 在客户端和服务器之间进行通信。一个标准的 GNS3 桌面程序中一般包含了一个 local-server，随程序一起启动。但是在本地直接开启 server 的时候，往往容易受到外部网络的干扰，而虚拟机又显得过于笨重了，因此很自然的想到使用 Docker 来解决这个问题。
首先在 Docker Hub 上找了一圈，没找到特别好的 GNS3 的 image，索性自己写了一个 Dockerfile，反正也没几行。
开起来之后发现 Cloud Node 没法给 VPC 分配 IP 地址。
PC1&amp;gt; ip dhcp DDD Can&amp;#39;t find dhcp server 这是因为 Docker 的网络接口中，容器的 IP 都是由 deamon 在创建分配的，也就是说 Docker 的虚拟网卡并不会提供 DHCP 服务，这也解释了为啥 VPC 得不到来自 Cloud Node 分发的 IP 地址。
既然 Docker 没有提供 DHCP Server，那么我们可以直接创建一个新的网络接口，然后将一个单独的 DHCP Server 放进这个网络里即可。</description>
      <content:encoded><![CDATA[<blockquote>
<p>Dockerfile 及 Compose-file 下载：<a href="https://github.com/iamNCJ/gns3-docker">https://github.com/iamNCJ/gns3-docker</a></p>
</blockquote>
<p>众所周知 GNS3 是全球有名的<del>一大坨屎</del>网络软件模拟器。广大 cs 学子为了<del>混到学分</del>熟练掌握计算机网络知识，常年使用 GNS3 做实验到要死要活。GNS3 采用了典型的 C/S 架构设计，其运行时需要一个 gns3-server 作为其后端，并通过 web api 在客户端和服务器之间进行通信。一个标准的 GNS3 桌面程序中一般包含了一个 local-server，随程序一起启动。但是在本地直接开启 server 的时候，往往容易受到外部网络的干扰，而虚拟机又显得过于笨重了，因此很自然的想到使用 Docker 来解决这个问题。</p>
<p>首先在 Docker Hub 上找了一圈，没找到特别好的 GNS3 的 image，索性自己写了一个 Dockerfile，反正也没几行。</p>
<p>开起来之后发现 Cloud Node 没法给 VPC 分配 IP 地址。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">PC1&gt; ip dhcp
</span></span><span class="line"><span class="cl">DDD
</span></span><span class="line"><span class="cl">Can<span class="err">&#39;</span>t find dhcp server
</span></span></code></pre></div><p>这是因为 Docker 的网络接口中，容器的 IP 都是由 deamon 在创建分配的，也就是说 Docker 的虚拟网卡并不会提供 DHCP 服务，这也解释了为啥 VPC 得不到来自 Cloud Node 分发的 IP 地址。</p>
<p>既然 Docker 没有提供 DHCP Server，那么我们可以直接创建一个新的网络接口，然后将一个单独的 DHCP Server 放进这个网络里即可。</p>
<p>说干就干，随手写了一个 Docker Compose-file，测试了一下，真的可以了！</p>
<p><img loading="lazy" src="/2020-12-27_GNS3_Docker.assets/suc.png" alt="Success"  />
</p>
<p>针不戳，顺便发现 GNS3 Server 自带的 Web Panel 还挺好用，所以有一说一，直接一行 <code>docker-compose up -d</code> ，你就可以愉快的<del>糊</del>写完计网实验了！</p>
<p>Enjoy~</p>
]]></content:encoded>
    </item>
    <item>
      <title>树莓派4打造旁路路由</title>
      <link>https://blog.chong-zeng.com/posts/2020-03-17_openwrt_pi/</link>
      <pubDate>Tue, 17 Mar 2020 00:00:00 +0000</pubDate>
      <guid>https://blog.chong-zeng.com/posts/2020-03-17_openwrt_pi/</guid>
      <description>相关仓库： iamNCJ/Openwrt-Pi4
最近尝试改造自己的路由器，无奈家里的路由器都比较老，而且没有USB插口，不是很好刷 OpenWrt ，于是想到直接将树莓派作为自己的旁路路由，在树莓派上运行 Openwrt 系统，来实现如全局代理等功能。
首先尝试官网的 snapshoot 版本，感觉效果一般，然后看网上有人说在 Docker 里运行 OpenWrt ，测试感觉能用，但是非常不稳定，于是索性自己编译一个。
使用的上游是 lede 大的固件，然后针对树莓派4，直接使用64位系统，榨干性能，开启了 Docker 支持，这样其他的功能基本还是不受影响（我已经将所有树莓派上自己用的的服务基本都容器化了），再加上现在的树莓派4已经有了千兆网口，整个体验效果是非常的好。
编译的时候本地编译，毕竟 9700K ，但是出于好玩尝试了网上的 GitHub Actions 编译脚本，感觉这个脚本马马虎虎，而且没有办法增量编译，所以只适合喜欢薅羊毛的人，有条件的话还是本地编译比较好。
现在家里的网络舒服多了，挂一张内网的测速，librespeed speedtest，千兆网还是很稳的。（librespeed 在树莓派上最好从源码 Dockerfile 自己build镜像，linuxserver 提供的 armv8 镜像非常不稳定）
本地互联网和境外代理也都很稳
最后本着开源精神，将树莓派4专用的 OpenWrt 固件的编译 .CONFIG 文件以及编译好的镜像开源，想使用可以点击这里查看配置或直接下载镜像安装，欢迎PR。</description>
      <content:encoded><![CDATA[<blockquote>
<p>相关仓库： <a href="https://github.com/iamNCJ">iamNCJ</a>/<strong><a href="https://github.com/iamNCJ/Openwrt-Pi4">Openwrt-Pi4</a></strong></p>
<p><a href="https://github.com/iamNCJ/Openwrt-Pi4/stargazers"><img loading="lazy" src="https://img.shields.io/github/stars/iamNCJ/Openwrt-Pi4.svg?label=Stars&amp;style=social" alt="Stars"  />
</a> <a href="https://github.com/iamNCJ/Openwrt-Pi4/network/members"><img loading="lazy" src="https://img.shields.io/github/forks/iamNCJ/Openwrt-Pi4.svg?label=Fork&amp;style=social" alt="Forks"  />
</a></p>
</blockquote>
<p>最近尝试改造自己的路由器，无奈家里的路由器都比较老，而且没有USB插口，不是很好刷 OpenWrt ，于是想到直接将树莓派作为自己的旁路路由，在树莓派上运行 Openwrt 系统，来实现如全局代理等功能。</p>
<p>首先尝试官网的 snapshoot 版本，感觉效果一般，然后看网上有人说在 Docker 里运行 OpenWrt ，测试感觉能用，但是非常不稳定，于是索性自己编译一个。</p>
<p>使用的上游是 <a href="https://github.com/coolsnowwolf/lede">lede 大的固件</a>，然后针对树莓派4，直接使用64位系统，榨干性能，开启了 Docker 支持，这样其他的功能基本还是不受影响（我已经将所有树莓派上自己用的的服务基本都容器化了），再加上现在的树莓派4已经有了千兆网口，整个体验效果是非常的好。</p>
<p>编译的时候本地编译，毕竟 9700K ，但是出于好玩尝试了网上的 <a href="https://github.com/P3TERX/Actions-OpenWrt">GitHub Actions 编译脚本</a>，感觉这个脚本马马虎虎，而且没有办法增量编译，所以只适合喜欢薅羊毛的人，有条件的话还是本地编译比较好。</p>
<p>现在家里的网络舒服多了，挂一张内网的测速，librespeed speedtest，千兆网还是很稳的。（librespeed 在树莓派上最好从源码 Dockerfile 自己build镜像，linuxserver 提供的 armv8 镜像非常不稳定）</p>
<p><img loading="lazy" src="/old-pics/illustrations/2020-03-17_Openwrt/1.png" alt=""  />
</p>
<p>本地互联网和境外代理也都很稳</p>
<p><img loading="lazy" src="/old-pics/illustrations/2020-03-17_Openwrt/3.png" alt="Local"  />
</p>
<p><img loading="lazy" src="/old-pics/illustrations/2020-03-17_Openwrt/2.png" alt="Proxy"  />
</p>
<p>最后本着开源精神，将树莓派4专用的 OpenWrt 固件的编译 <code>.CONFIG</code> 文件以及编译好的镜像开源，想使用可以<a href="https://github.com/iamNCJ/Openwrt-Pi4">点击这里</a>查看配置或直接下载镜像安装，欢迎PR。</p>
]]></content:encoded>
    </item>
    <item>
      <title>GitHub Actions无法上传到Release的问题</title>
      <link>https://blog.chong-zeng.com/posts/2020-03-16_github_actions/</link>
      <pubDate>Mon, 16 Mar 2020 00:00:00 +0000</pubDate>
      <guid>https://blog.chong-zeng.com/posts/2020-03-16_github_actions/</guid>
      <description>最近在尝试使用 Github Actions 自动编译、发布树莓派Openwrt固件的时候，遇到了 Release 发布失败的问题。
可以看到 Create Release 这一步发生了错误 Bad credentials ，这个错误一般是调用 GitHub Release API 的时候 TOKEN 错误导致的，但是在我们这里是 GitHub 自动生成的 TOKEN ，照说应该一点问题都没有才对啊。
后来查找资料得知是因为 GitHub 为 Actions 的每一个 Workflow 都会申请一个临时的 TOKEN ，但是这个TOKEN 只有一个小时的失效，而我们的编译持续了一个半小时，此时的 TOKEN 已经失效了， 因此不再有效。
GitHub给出了一个解决的办法，就是创建不同的 Workflow，先单独编译，编译完成之后再将固件传到一个第三方的位置（比如你的云盘），然后再单独一个 Workflow 进行发布。
另外一种办法就是使用永久的 TOKEN ，但是对于公开仓库这显然不安全，所以可以考虑创建一个 private repo 在里面编译然后通过永久 TOKEN 上传到公开仓库的 Release 里。</description>
      <content:encoded><![CDATA[<p>最近在尝试使用 Github Actions 自动编译、发布<a href="https://github.com/iamNCJ/Openwrt-Pi4">树莓派Openwrt固件</a>的时候，遇到了 Release 发布失败的问题。</p>
<p><img loading="lazy" src="/old-pics/illustrations/2020-03-16_GitHub_Actions/1.png" alt="Bad credentials"  />
</p>
<p>可以看到 Create Release 这一步发生了错误 <code>Bad credentials</code> ，这个错误一般是调用 GitHub Release API 的时候 TOKEN 错误导致的，但是在我们这里是 GitHub 自动生成的 TOKEN ，照说应该一点问题都没有才对啊。</p>
<p>后来查找资料得知是因为 GitHub 为 Actions 的每一个 Workflow 都会申请一个临时的 TOKEN ，但是这个TOKEN 只有一个小时的失效，而我们的编译持续了一个半小时，此时的 TOKEN 已经失效了， 因此不再有效。</p>
<p>GitHub给出了一个<a href="https://help.github.com/en/actions/configuring-and-managing-workflows/persisting-workflow-data-using-artifacts#sharing-data-between-workflow-runs">解决的办法</a>，就是创建不同的 Workflow，先单独编译，编译完成之后再将固件传到一个第三方的位置（比如你的云盘），然后再单独一个 Workflow 进行发布。</p>
<p>另外一种办法就是使用永久的 TOKEN ，但是对于公开仓库这显然不安全，所以可以考虑创建一个 private repo 在里面编译然后通过永久 TOKEN 上传到公开仓库的 Release 里。</p>
]]></content:encoded>
    </item>
    <item>
      <title>Running ROS on WSL</title>
      <link>https://blog.chong-zeng.com/posts/2020-02-20_ros_wsl/</link>
      <pubDate>Thu, 20 Feb 2020 00:00:00 +0000</pubDate>
      <guid>https://blog.chong-zeng.com/posts/2020-02-20_ros_wsl/</guid>
      <description>简短版 如果根本没有出现图形界面，请禁用OpenGL的外部转发，全部在WSL内进行渲染：
export LIBGL_ALWAYS_INDIRECT=0 如果出现了图形界面，但是中间是黑屏，可以通过--verbose检查
如果是gazebo 7 (ROS Kinetic默认)，大概率是第一次模型没有下下来，自己手动下载模型放到/.gazebo/models/目录下即可
如果是gazebo 9 (ROS Melodic)，大概率是gazebo server的IP问题，在环境里设置一下gazebo server的IP即可：
export GAZEBO_IP=127.0.0.1 闲来无事玩ROS，配环境。一杯茶，一把琴，一个环境配一宿。（不是
言归正传，感觉周围好多人都开始玩ROS，我也玩玩，然而拦在很多人面前的第一道坎竟是安装。事实上ROS官方对于正常的使用者已经提供了清晰明了的安装指南，只要前往官网进行操作即可。
但是我显然不是正常人并没有安装Ubuntu，原因很多，之前还专门写文喷过Ubuntu，但是招架不住这次很多老师指定安装ROS Kinetic，ROS的上一个LTS版本，而这个版本只能安装在Ubuntu 16.04下，于是，我就动了WSL的邪念。
WSL好处很多，你可以直接在Windows下“无缝”使用一个Linux发行版（虽然跟内核有关的东西都被砍掉了），而且WSL的主题安装之后，你可以同时安装很多个发行版，甚至还能通过Raft WSL等工具管理不同发行版的不同快照，这次我就索性直接在WSL里同时安装了两个不同的Ubuntu发行版，分别来安装ROS Kinetic和Melodic版本。
WSL的安装在此略过，网上教程一搜一大把，我就不过多赘述，但是在WSL下，跑通gazebo，麻烦事还是很多的，下面开始排坑。
首先，你得再安装一个Ubuntu的发行版，直接去商店下载就好。
然后安装一下ROS，视网络情况而定，大概10~30分钟的样子。
中间有一步sudo rosdep init可能会因为网络原因很慢，解决办法就是开proxy
export https_proxy=xxx sudo -E rosdep init -E的意义就是将你现在设置好的proxy环境带入sudo中
然后你需要准备一个X Server，我使用的是Xming，其他的X Server不保证兼容性。
通过XLaunch启动X Server，注意要关闭Native opengl，不然WSL会试图讲渲染工作交给外部的X Server，但是我试验了一下似乎不太行，干脆就强制使用软OpenGL算了。（再次尝试发现不关也行，主要不在WSL里面指定外部OpenGL就行
划红线的这项要取消勾选
测试一下
roslaunch turtle_tf turtle_tf_demo.launch # on another terminal rosrun rviz rviz -d `rospack find turtle_tf`/rviz/turtle_rviz.rviz 发现可视化工具rviz是可以正常使用的
但是故事没有结束，事实上ROS里面还有一个重要的仿真环境gazebo
我们来测试一下
gazebo 然后发现
中间的仿真是黑的？？？
很多人就会就此得出结论——WSL不能运行gazebo，我以前也这么以为，直到最近……
Gazebo 7 我们来试图寻找一下错误的原因</description>
      <content:encoded><![CDATA[<blockquote>
<h2 id="简短版">简短版</h2>
<ul>
<li>
<p>如果根本没有出现图形界面，请禁用OpenGL的外部转发，全部在WSL内进行渲染：</p>
<ul>
<li><code>export LIBGL_ALWAYS_INDIRECT=0</code></li>
</ul>
</li>
<li>
<p>如果出现了图形界面，但是中间是黑屏，可以通过<code>--verbose</code>检查</p>
<ul>
<li>
<p>如果是gazebo 7 (ROS Kinetic默认)，大概率是第一次模型没有下下来，自己<a href="https://bitbucket.org/osrf/gazebo_models/downloads/">手动下载模型</a>放到<code>/.gazebo/models/</code>目录下即可</p>
</li>
<li>
<p>如果是gazebo 9 (ROS Melodic)，大概率是gazebo server的IP问题，在环境里设置一下gazebo server的IP即可：</p>
<ul>
<li><code>export GAZEBO_IP=127.0.0.1</code></li>
</ul>
</li>
</ul>
</li>
</ul>
</blockquote>
<hr>
<p>闲来无事玩ROS，配环境。一杯茶，一把琴，一个环境配一宿。（<del>不是</del></p>
<p>言归正传，感觉周围好多人都开始玩ROS，我也玩玩，然而拦在很多人面前的第一道坎竟是安装。事实上ROS官方对于正常的使用者已经提供了清晰明了的安装指南，只要前往<a href="https://www.ros.org/">官网</a>进行操作即可。</p>
<p>但是我<del>显然不是正常人</del>并没有安装Ubuntu，原因很多，之前还专门写文喷过Ubuntu，但是招架不住这次很多老师指定安装ROS Kinetic，ROS的上一个LTS版本，而这个版本只能安装在Ubuntu 16.04下，于是，我就动了WSL的邪念。</p>
<p>WSL好处很多，你可以直接在Windows下“无缝”使用一个Linux发行版（虽然跟内核有关的东西都被砍掉了），而且WSL的主题安装之后，你可以同时安装很多个发行版，甚至还能通过Raft WSL等工具管理不同发行版的不同快照，这次我就索性直接在WSL里同时安装了两个不同的Ubuntu发行版，分别来安装ROS Kinetic和Melodic版本。</p>
<p>WSL的安装在此略过，网上教程一搜一大把，我就不过多赘述，但是在WSL下，跑通gazebo，麻烦事还是很多的，下面开始排坑。</p>
<hr>
<p>首先，你得再安装一个Ubuntu的发行版，直接去商店下载就好。</p>
<p>然后安装一下ROS，视网络情况而定，大概10~30分钟的样子。</p>
<p>中间有一步<code>sudo rosdep init</code>可能会因为网络原因很慢，解决办法就是开proxy</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">export</span> <span class="nv">https_proxy</span><span class="o">=</span>xxx
</span></span><span class="line"><span class="cl">sudo -E rosdep init
</span></span></code></pre></div><blockquote>
<p><code>-E</code>的意义就是将你现在设置好的proxy环境带入sudo中</p>
</blockquote>
<p>然后你需要准备一个X Server，我使用的是Xming，其他的X Server不保证兼容性。</p>
<p>通过XLaunch启动X Server，<del>注意要关闭<code>Native opengl</code>，不然WSL会试图讲渲染工作交给外部的X Server，但是我试验了一下似乎不太行，干脆就强制使用软OpenGL算了。</del>（再次尝试发现不关也行，主要不在WSL里面指定外部OpenGL就行</p>
<p><img loading="lazy" src="/old-pics/illustrations/2020-02-20_ROS_WSL/image-20200220225718834.png" alt="XLaunch"  />
</p>
<blockquote>
<p><del>划红线的这项要取消勾选</del></p>
</blockquote>
<p>测试一下</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">roslaunch turtle_tf turtle_tf_demo.launch
</span></span><span class="line"><span class="cl"><span class="c1"># on another terminal</span>
</span></span><span class="line"><span class="cl">rosrun rviz rviz -d <span class="sb">`</span>rospack find turtle_tf<span class="sb">`</span>/rviz/turtle_rviz.rviz
</span></span></code></pre></div><p>发现可视化工具rviz是可以正常使用的</p>
<p><img loading="lazy" src="/old-pics/illustrations/2020-02-20_ROS_WSL/image-20200220230758278.png" alt="turtle_tf_demo"  />
</p>
<p>但是故事没有结束，事实上ROS里面还有一个重要的仿真环境gazebo</p>
<p>我们来测试一下</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">gazebo
</span></span></code></pre></div><p>然后发现</p>
<p><img loading="lazy" src="/old-pics/illustrations/2020-02-20_ROS_WSL/image-20200221101621314.png" alt="gazebo"  />
</p>
<p>中间的仿真是黑的？？？</p>
<p>很多人就会就此得出结论——WSL不能运行gazebo，我以前也这么以为，直到最近……</p>
<h2 id="gazebo-7">Gazebo 7</h2>
<p>我们来试图寻找一下错误的原因</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">gazebo --verbose
</span></span></code></pre></div><p><img loading="lazy" src="/old-pics/illustrations/2020-02-20_ROS_WSL/image-20200221101842784.png" alt="gazebo &amp;ndash;verbose"  />
</p>
<p>看到那句warning，发现gazebo 7 在第一次启动的时候会尝试从官网下载所有的模型，而这一过程是非常漫长的，因此直接自己从<a href="https://bitbucket.org/osrf/gazebo_models/downloads/">BitBucket</a>手动下载，解压到<code>~/.gazebo/models</code>目录下即可。</p>
<p>这次即可正常打开</p>
<p><img loading="lazy" src="/old-pics/illustrations/2020-02-20_ROS_WSL/image-20200221103207172.png" alt="gazebo"  />
</p>
<p>输出：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">Gazebo multi-robot simulator, version 7.0.0
</span></span><span class="line"><span class="cl">Copyright <span class="o">(</span>C<span class="o">)</span> 2012-2016 Open Source Robotics Foundation.
</span></span><span class="line"><span class="cl">Released under the Apache <span class="m">2</span> License.
</span></span><span class="line"><span class="cl">http://gazebosim.org
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="o">[</span>Msg<span class="o">]</span> Waiting <span class="k">for</span> master.
</span></span><span class="line"><span class="cl"><span class="o">[</span>Msg<span class="o">]</span> Connected to gazebo master @ http://127.0.0.1:11345
</span></span><span class="line"><span class="cl"><span class="o">[</span>Msg<span class="o">]</span> Publicized address: 192.168.0.190
</span></span><span class="line"><span class="cl">Gazebo multi-robot simulator, version 7.0.0
</span></span><span class="line"><span class="cl">Copyright <span class="o">(</span>C<span class="o">)</span> 2012-2016 Open Source Robotics Foundation.
</span></span><span class="line"><span class="cl">Released under the Apache <span class="m">2</span> License.
</span></span><span class="line"><span class="cl">http://gazebosim.org
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="o">[</span>Msg<span class="o">]</span> Waiting <span class="k">for</span> master.
</span></span><span class="line"><span class="cl"><span class="o">[</span>Msg<span class="o">]</span> Connected to gazebo master @ http://127.0.0.1:11345
</span></span><span class="line"><span class="cl"><span class="o">[</span>Msg<span class="o">]</span> Publicized address: 192.168.0.190
</span></span><span class="line"><span class="cl"><span class="o">[</span>Wrn<span class="o">]</span> <span class="o">[</span>Time.cc:437<span class="o">]</span> Sleep <span class="nb">time</span> is larger than clock resolution, skipping sleep
</span></span></code></pre></div><blockquote>
<p>gazebo7正常运行后的输出放在这儿是有目的的，在此先卖个关子</p>
</blockquote>
<h2 id="gazebo-9">Gazebo 9</h2>
<p>现在我们来试试ROS最新的LTS版本Melodic附带的Gazebo 9</p>
<p>再安装一个新的Ubuntu 18.04发行版</p>
<p>装好ROS Melodic</p>
<p>然后运行gazebo</p>
<p>又是黑屏</p>
<p>不慌，看看输出</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">gazebo --verbose
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">Gazebo multi-robot simulator, version 9.0.0
</span></span><span class="line"><span class="cl">Copyright <span class="o">(</span>C<span class="o">)</span> <span class="m">2012</span> Open Source Robotics Foundation.
</span></span><span class="line"><span class="cl">Released under the Apache <span class="m">2</span> License.
</span></span><span class="line"><span class="cl">http://gazebosim.org
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="o">[</span>Msg<span class="o">]</span> Waiting <span class="k">for</span> master.
</span></span><span class="line"><span class="cl"><span class="o">[</span>Msg<span class="o">]</span> Connected to gazebo master @ http://127.0.0.1:11345
</span></span><span class="line"><span class="cl"><span class="o">[</span>Msg<span class="o">]</span> Publicized address: 169.254.245.8
</span></span><span class="line"><span class="cl">Gazebo multi-robot simulator, version 9.0.0
</span></span><span class="line"><span class="cl">Copyright <span class="o">(</span>C<span class="o">)</span> <span class="m">2012</span> Open Source Robotics Foundation.
</span></span><span class="line"><span class="cl">Released under the Apache <span class="m">2</span> License.
</span></span><span class="line"><span class="cl">http://gazebosim.org
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="o">[</span>Msg<span class="o">]</span> Waiting <span class="k">for</span> master.
</span></span><span class="line"><span class="cl"><span class="o">[</span>Msg<span class="o">]</span> Connected to gazebo master @ http://127.0.0.1:11345
</span></span><span class="line"><span class="cl"><span class="o">[</span>Msg<span class="o">]</span> Publicized address: 169.254.245.8
</span></span><span class="line"><span class="cl"><span class="o">[</span>Wrn<span class="o">]</span> <span class="o">[</span>GuiIface.cc:120<span class="o">]</span> QStandardPaths: 
</span></span></code></pre></div><p>注意，与gazebo 7运行时的报错相对比，发现倒数第二行的<code>Publicized address</code>是<code>169.254.245.8</code>——一个无效的IP。gazebo运行需要后端的gazebo server与前端进行通信，而这个无效的IP地址导致了通信的失败。</p>
<p>解决方法也很简单，设置一下gazebo的地址即可：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">export</span> <span class="nv">GAZEBO_IP</span><span class="o">=</span>127.0.0.1
</span></span></code></pre></div><p>再次启动gazebo，就发现已经能够正常使用。</p>
<hr>
<p>睡了一觉起来，发现又不能用了……</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">~$ gazebo --verbose
</span></span><span class="line"><span class="cl">Gazebo multi-robot simulator, version 9.0.0
</span></span><span class="line"><span class="cl">Copyright <span class="o">(</span>C<span class="o">)</span> <span class="m">2012</span> Open Source Robotics Foundation.
</span></span><span class="line"><span class="cl">Released under the Apache <span class="m">2</span> License.
</span></span><span class="line"><span class="cl">http://gazebosim.org
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="o">[</span>Msg<span class="o">]</span> Waiting <span class="k">for</span> master.
</span></span><span class="line"><span class="cl"><span class="o">[</span>Msg<span class="o">]</span> Connected to gazebo master @ http://127.0.0.1:11345
</span></span><span class="line"><span class="cl"><span class="o">[</span>Msg<span class="o">]</span> Publicized address: 192.168.0.190
</span></span><span class="line"><span class="cl">Gazebo multi-robot simulator, version 9.0.0
</span></span><span class="line"><span class="cl">Copyright <span class="o">(</span>C<span class="o">)</span> <span class="m">2012</span> Open Source Robotics Foundation.
</span></span><span class="line"><span class="cl">Released under the Apache <span class="m">2</span> License.
</span></span><span class="line"><span class="cl">http://gazebosim.org
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="o">[</span>Msg<span class="o">]</span> Waiting <span class="k">for</span> master.
</span></span><span class="line"><span class="cl"><span class="o">[</span>Msg<span class="o">]</span> Connected to gazebo master @ http://127.0.0.1:11345
</span></span><span class="line"><span class="cl"><span class="o">[</span>Msg<span class="o">]</span> Publicized address: 127.0.0.1
</span></span><span class="line"><span class="cl">~$
</span></span></code></pre></div><p>就没了？？？图形界面都没出来</p>
<p>然后一想，图形界面都没有那八成是OpenGL的锅</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">export</span> <span class="nv">LIBGL_ALWAYS_INDIRECT</span><span class="o">=</span><span class="m">0</span>
</span></span></code></pre></div><p>done</p>
<hr>
<h2 id="一点对比">一点对比</h2>
<p>对比了一下发现gazebo 7的空场景帧率在24FPS左右，gazebo 9则可达到接近60FPS，看来新的gazebo还是有优化的，所以即使是使用ROS Kinetic的同学也可以尝试换到gazebo 9，API应该是通用的，不通用就自己对着文档改改好了。</p>
<p>踩坑结束。</p>
]]></content:encoded>
    </item>
    <item>
      <title>OOP with Java</title>
      <link>https://blog.chong-zeng.com/posts/2020-02-06_oop_java/</link>
      <pubDate>Thu, 06 Feb 2020 00:00:00 +0000</pubDate>
      <guid>https://blog.chong-zeng.com/posts/2020-02-06_oop_java/</guid>
      <description>1 IO 打印
System.out.println()
输入
import java.util.Scanner; Scanner in = new Scanner(System.in); int a = in.nextInt(); in.close(); public static void main(String[] args)是程序的入口
2 类与包 类 构造函数与C++一样
成员访问权限默认都是friendly，同一个包内可以自由访问
public class必须单独一个文件
包 包是java对于类的一种管理机制，包的结构与文件目录的结构一致
文件第一行package xxx声明包，同时目录结构也要变为xxx/xyz.java
包下还可以有包，Display.led，文件结构Display/led
访问其他包里的对象需要import &amp;lt;package_name&amp;gt;.&amp;lt;class_name&amp;gt;或者每次都在前面加&amp;lt;package_name&amp;gt;. (有点类似namespace)
import &amp;lt;package_name&amp;gt;.*也是允许的，但是不推荐
类变量&amp;amp;类函数 static static 一个类共用一个
与C++里的static不太一样
类函数 static 里没有this指针（与C++一样），可以单独调用，也可以通过对象调用
3 容器 import java.util.xxx
ArrayList类似vector
对象数组中每一个元素都是对象的管理者而非对象本身，也就是说你在创建数组之后还需要再创建每一个对象。
“对象管理者”的概念 （类似指针）
有序容器的迭代遍历
for ( X x : List ) {...} HashSet 类似 Set
HashMap 类似 map 注意不能放int，必须放对象（包裹类型）Integer</description>
      <content:encoded><![CDATA[<h1 id="1-io">1 IO</h1>
<p>打印</p>
<p><code>System.out.println()</code></p>
<p>输入</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">java.util.Scanner</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="n">Scanner</span><span class="w"> </span><span class="n">in</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">Scanner</span><span class="p">(</span><span class="n">System</span><span class="p">.</span><span class="na">in</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="kt">int</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">in</span><span class="p">.</span><span class="na">nextInt</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="n">in</span><span class="p">.</span><span class="na">close</span><span class="p">();</span><span class="w">
</span></span></span></code></pre></div><p><code>public static void main(String[] args)</code>是程序的入口</p>
<h1 id="2-类与包">2 类与包</h1>
<h2 id="类">类</h2>
<p>构造函数与C++一样</p>
<p>成员访问权限默认都是<code>friendly</code>，同一个包内可以自由访问</p>
<p><code>public class</code>必须单独一个文件</p>
<h2 id="包">包</h2>
<p>包是java对于类的一种管理机制，包的结构与文件目录的结构一致</p>
<p>文件第一行<code>package xxx</code>声明包，同时目录结构也要变为<code>xxx/xyz.java</code></p>
<p>包下还可以有包，<code>Display.led</code>，文件结构<code>Display/led</code></p>
<p>访问其他包里的对象需要<code>import &lt;package_name&gt;.&lt;class_name&gt;</code>或者每次都在前面加<code>&lt;package_name&gt;.</code> (有点类似namespace)</p>
<p><code>import &lt;package_name&gt;.*</code>也是允许的，但是不推荐</p>
<h2 id="类变量类函数-static">类变量&amp;类函数 static</h2>
<p>static 一个类共用一个</p>
<p>与C++里的static不太一样</p>
<p>类函数 static 里没有this指针（与C++一样），可以单独调用，也可以通过对象调用</p>
<h1 id="3-容器">3 容器</h1>
<p><code>import java.util.xxx</code></p>
<p>ArrayList类似vector</p>
<p>对象数组中每一个元素都是对象的管理者而非对象本身，也就是说你在创建数组之后还需要再创建每一个对象。</p>
<p>“对象管理者”的概念 （类似指针）</p>
<p>有序容器的迭代遍历</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="w"> </span><span class="n">X</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="n">List</span><span class="w"> </span><span class="p">)</span><span class="w"> </span><span class="p">{...}</span><span class="w">
</span></span></span></code></pre></div><p>HashSet 类似 Set</p>
<p>HashMap 类似 map 注意不能放<code>int</code>，必须放对象（包裹类型）<code>Integer</code></p>
<h1 id="4-继承多态">4 继承&amp;多态</h1>
<p><code>extends</code></p>
<h2 id="super">super</h2>
<p><code>super()</code>用于传递参数给父类构造器</p>
<p>执行顺序：父类构造、子类成员初始化、子类构造器</p>
<p><code>Constructor call must be the first statement in a constructor</code></p>
<p>super()必须写在构造器的第一行</p>
<p>不可以用多个super()，因为一个子类只能继承一个父类</p>
<h2 id="同名成员">同名成员</h2>
<h3 id="同名成员对象">同名成员对象</h3>
<p>对于同名对象，父子类没有任何联系，在父类的方法中操作的就是父类的哪个，在子类的方法中操作的就是子类的哪个。</p>
<h3 id="同名成员函数">同名成员函数</h3>
<p>同名成员函数，子类使用的永远是自己的，但是通过<code>super.f()</code>使用到父类的函数</p>
<h2 id="多态">多态</h2>
<p><code>@override</code>最好写上</p>
<p>Object类 （root类）</p>
<ul>
<li>
<p><code>toString()</code></p>
<ul>
<li>
<p>不重写直接输出AAA.XXX@xxxxxx</p>
</li>
<li>
<p>前面是类名（AAA是包名，XXX是类名），后面是地址</p>
</li>
<li>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nn">AAA</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="kd">public</span><span class="w"> </span><span class="kd">class</span> <span class="nc">Main4</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="kd">public</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">main</span><span class="p">(</span><span class="n">String</span><span class="o">[]</span><span class="w"> </span><span class="n">args</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">A</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">A</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">B</span><span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">B</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">System</span><span class="p">.</span><span class="na">out</span><span class="p">.</span><span class="na">println</span><span class="p">(</span><span class="n">a</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">System</span><span class="p">.</span><span class="na">out</span><span class="p">.</span><span class="na">println</span><span class="p">(</span><span class="n">b</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">b</span><span class="p">.</span><span class="na">f</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="kd">class</span> <span class="nc">A</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="kt">int</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">0</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="kt">int</span><span class="w"> </span><span class="n">aa</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">1</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="kd">class</span> <span class="nc">B</span><span class="w"> </span><span class="kd">extends</span><span class="w"> </span><span class="n">A</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="kt">int</span><span class="w"> </span><span class="n">aa</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="kt">void</span><span class="w"> </span><span class="nf">f</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">a</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">1</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">aa</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">2</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="kd">super</span><span class="p">.</span><span class="na">aa</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">3</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">A</span><span class="w"> </span><span class="n">aaa</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">A</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">System</span><span class="p">.</span><span class="na">out</span><span class="p">.</span><span class="na">println</span><span class="p">(</span><span class="n">aaa</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">}</span><span class="w">
</span></span></span></code></pre></div></li>
</ul>
</li>
<li>
<p><code>equals()</code></p>
</li>
</ul>
<p>使用<code>StringBuffer</code>来降低开销</p>
<h1 id="5-抽象接口">5 抽象&amp;接口</h1>
<h2 id="抽象">抽象</h2>
<p><code>abstract</code></p>
<p>类似<code>virtual</code></p>
<p>抽象类 &ndash;&gt;  纯虚类</p>
<p>也不能产生对象</p>
<h2 id="接口">接口</h2>
<p><code>interface</code></p>
<p>纯抽象类</p>
<ul>
<li>所有成员函数都是抽象函数</li>
<li>所有成员变量都是<code>public static final</code></li>
</ul>
<p><code>implement</code></p>
<p>与class不同：</p>
<ul>
<li>类可以实现很多接口</li>
<li>接口可以继承接口，但不能继承类</li>
<li>接口不能实现接口</li>
</ul>
<h2 id="内部类">内部类</h2>
<p>定义在类/函数的内部</p>
<p>内部类能自由访问包括私有成员在内的外部的全部资源</p>
<p>外部为函数时，只能访问函数中final的变量</p>
<h2 id="匿名类">匿名类</h2>
<p>new的时候给出类的定义</p>
<p>可以继承某类，也可以实现某接口</p>
<p>（好处：不用起名字</p>
<h1 id="6-异常">6 异常</h1>
<p>函数若想抛出自定义异常（系统自带的比比如数组越界不需要，因为它们太容易被触发）需要声明<code>throws</code></p>
<p>一旦声明调用时就必须加上<code>try</code></p>
<p>当覆盖一个函数的时候，子类不能声明比父类更多的异常</p>
<p>子类的构造函数函数中，必须声明父类可能抛出的全部异常</p>
<h1 id="7-流">7 流</h1>
<p>对象 串行化 输入到流</p>
<p>流 反串行化 读入到内存</p>
]]></content:encoded>
    </item>
    <item>
      <title>[吐槽向] Ubuntu Server 安装指南</title>
      <link>https://blog.chong-zeng.com/posts/2020-01-27_ubuntu_server/</link>
      <pubDate>Mon, 27 Jan 2020 00:00:00 +0000</pubDate>
      <guid>https://blog.chong-zeng.com/posts/2020-01-27_ubuntu_server/</guid>
      <description>吃饱了撑的，非要在台式机上安装Ubuntu Server
好吧，主要是之后可能要玩ROS，ML的环境也是Ubuntu相对来说容易配置一些，所以还是Ubuntu方便一点。但是最近Ubuntu的一次内核更新引入了一个bug（具体参考https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1860306），导致我的Ubuntu在启动后图形界面会处于卡死状态，无法进行操作。虽然通过ssh将启动目标改为了terminal，勉强能够使用，但是显卡的驱动坏了，一时半会也没修好，一气之下索性想重装一个Ubuntu Server，告别Linux桌面环境。
然后就发现Ubuntu Server的安装脚本就是一坨屎，首先是18.04版本的live iso不支持nvme硬盘，Stack Overflow上查了一圈发现要么换上古的16.04，要么换mini.iso纯网络安装，要么用19.10，想了想20.04应该快出来了，索性直接用非LTS版本到时候滚过去吧。然后安装19.10的时候，发现脚本居然不支持自定义修改分区，要么全盘，要么在进脚本之前自己改好分区表，绝了。（快快投奔Arch
然后自己改好分区表，进入脚本，标记好EFI分区和根目录，开始安装，duang，ERROR，垃圾脚本，上网搜了一下错误信息发现又是一个bug……
结论：Ubuntu Server的安装脚本设计的时候就没考虑作为第二个系统进行安装，各种异常处理做的也是极其不到位，如果你想Windows+Ubuntu Server，请先安装Ubuntu Server……
于是开始曲线救国，先安装Desktop，然后转为Server（不愧是我
网上各种奇葩方法……
sudo apt purge xorg-* sudo apt remove gnome-* &amp;amp;&amp;amp; sudo apt autoremove sudo apt remove ubuntu-desktop &amp;amp;&amp;amp; sudo apt autoremove ……
看着就不优雅
自然想到tasksel
取消勾选Desktop，选上Basic Server，跑完进度条就好了
重启
然后你就发现你上不了网了（狗头
试了一下/etc/network/interfaces发现不行，ip link set eno2 up也不行，然后知道了Ubuntu的网络是由Network Manager管理的，tasksel可能在卸载Desktop的时候给你卸掉了，但Server安装的时候又没给你装回来……
所以正确方法是：使用tasksel操作完之后，再安装Network Manager……
踩坑结束……</description>
      <content:encoded><![CDATA[<p><del>吃饱了撑的，非要在台式机上安装Ubuntu Server</del></p>
<p>好吧，主要是之后可能要玩ROS，ML的环境也是Ubuntu相对来说容易配置一些，所以还是Ubuntu方便一点。但是最近Ubuntu的一次内核更新引入了一个bug（具体参考<a href="https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1860306">https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1860306</a>），导致我的Ubuntu在启动后图形界面会处于卡死状态，无法进行操作。虽然通过ssh将启动目标改为了terminal，勉强能够使用，但是显卡的驱动坏了，一时半会也没修好，一气之下索性想重装一个Ubuntu Server，告别Linux桌面环境。</p>
<p>然后就发现Ubuntu Server的安装脚本就是一坨屎，首先是18.04版本的live iso不支持nvme硬盘，Stack Overflow上查了一圈发现要么换上古的16.04，要么换mini.iso纯网络安装，要么用19.10，想了想20.04应该快出来了，索性直接用非LTS版本到时候滚过去吧。然后安装19.10的时候，发现脚本居然不支持自定义修改分区，要么全盘，要么在进脚本之前自己改好分区表，绝了。（<del>快快投奔Arch</del></p>
<p>然后自己改好分区表，进入脚本，标记好EFI分区和根目录，开始安装，duang，ERROR，垃圾脚本，上网搜了一下错误信息发现又是一个bug……</p>
<blockquote>
<p>结论：Ubuntu Server的安装脚本设计的时候就没考虑作为第二个系统进行安装，各种异常处理做的也是极其不到位，如果你想Windows+Ubuntu Server，请先安装Ubuntu Server……</p>
</blockquote>
<hr>
<p>于是开始曲线救国，先安装Desktop，然后转为Server（<del>不愧是我</del></p>
<p>网上各种奇葩方法……</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo apt purge xorg-*
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo apt remove gnome-* <span class="o">&amp;&amp;</span> sudo apt autoremove
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo apt remove ubuntu-desktop <span class="o">&amp;&amp;</span> sudo apt autoremove
</span></span></code></pre></div><p>……</p>
<p>看着就不优雅</p>
<p>自然想到<code>tasksel</code></p>
<p>取消勾选<code>Desktop</code>，选上<code>Basic Server</code>，跑完进度条就好了</p>
<p>重启</p>
<p>然后你就发现你上不了网了（狗头</p>
<p>试了一下<code>/etc/network/interfaces</code>发现不行，<code>ip link set eno2 up</code>也不行，然后知道了Ubuntu的网络是由Network Manager管理的，tasksel可能在卸载Desktop的时候给你卸掉了，但Server安装的时候又没给你装回来……</p>
<p>所以正确方法是：使用<code>tasksel</code>操作完之后，再安装Network Manager……</p>
<hr>
<p>踩坑结束……</p>
]]></content:encoded>
    </item>
    <item>
      <title>小米Mix 2s多系统安装教程</title>
      <link>https://blog.chong-zeng.com/posts/2020-01-26_multirom_mix2s/</link>
      <pubDate>Sun, 26 Jan 2020 00:00:00 +0000</pubDate>
      <guid>https://blog.chong-zeng.com/posts/2020-01-26_multirom_mix2s/</guid>
      <description>折腾了两天，总算成功实现了安卓手机的多系统，在此记录一下，权且做一个教程，给其他热爱折腾的人做一点参考。
首先要说明的是安装双系统乃至多系统，尤其是在手机上，对于很多人来说绝对是非常鸡肋的，而且安装的过程肯定会造成原先数据的丢失等等，安装之后也不能保证所有功能的正常（比如视频），但是对于爱玩机的人来说，能够经常体验不同的ROM还是很重要的。我之所以想安装多系统，就是因为发现了两个都让我非常喜欢的ROM——Pixel Experience 和 Simplicity。这两个ROM可谓是两个极端，一个是纯原生安卓的体验，手感非常的好，吊打国内的各大ROM（这才是安卓啊），另一个则是浓厚的极客气息（自带Magisk、Busybox，以及各种底层破解……），在分别体验了两个ROM之后，我发现对它们都是爱不释手。小孩子才做选择，成年人全都要，多启动的想法自然而然地萌生了出来。
我的设备是Xiaomi Mix 2s (polaris) 国行6+64GB，其他设备的用户本教程可能并不适用，仅供参考
免责声明：本人不对任何教程中的操作造成的数据丢失以及设备损坏负责，请在操作前做好数据备份
一、常见方案 折腾前当然要看看有啥现成的轮子了，大致研究了一下界内的方案，基本都在XDA的这篇文章里讲到了，这里简单概括一下。
MultiROM 官方Wiki
作用于bootloader之后，可以用于引导不同的系统（含Linux），XDA称这是“已知的最好的多系统解决方案”。
https://forum.xda-developers.com/xiaomi-mi-mix-2s/how-to/multirom-multirom-polaris-t3957428
DualBoot Patcher 官网
非常有名的安卓引导工具，XDA高级成员，陈小龙大牛开发&amp;amp;&amp;amp;维护，但是在安卓10到来之后，开发者停止维护了。主要是由于新版安卓在架构上的一些调整造成了开发的困难。但是我想要安装Pixel Experience正是基于安卓10的，所以这个方案不行。
GRUB for Android GRUB是x86架构上知名的引导程序，那么GRUB4Android顾名思义也是一个原生bootloader的替代品。现在这个项目已经衍生为了EFIDroid，但是看了一下官网最后一次更新是2016年，现在貌似也没有对Mix 2s进行适配，所以就放弃了。
综合以上，我最后选择MultiROM作为多系统的解决方案。
二、安装MultiROM版TWRP 在安装ROM之前，我们首先需要对引导程序进行一些处理。
1. 解锁BootLoader BootLoader是嵌入式设备在操作系统内核运行之前运行的一段程序，它相当于控制了整个启动的大方向，厂商往往会在BootLoader里加入一些检查代码，限制非官方的系统的启动。因此如果想要进行刷机、root等操作，必须将厂商的限制解除。
由于BootLoader与硬件强绑定，因此必须通过厂商的官方途径（或者万能的淘宝）进行解锁。小米官方提供了解锁方式，傻瓜操作，在此略过。
2. 刷入Recovery 安卓刷机一般使用TWRP，这是一个开源的第三方Recovery，可以用于替换官方的Recovery，从而更方便地进行刷机等操作。
刷入的过程非常简单，重启手机进入fastboot模式之后，连接手机与电脑，使用ADB进行以下操作：
fastboot devices # 检查设备连接状态 fastboot flash recovery your-TWRP.img # 将TWRP烧入Recovery 现在，TWRP已经在你的手机的Recovery分区下了。
3. 安装MultiROM补丁 但是原版的TWRP并不支持多系统，因此我们需要安装TWRP之后打补丁，并替换MultiROM专用的TWRP版本。
而且因为嵌入式的强硬件相关性，我们需要根据自己的设备选择专用的MultiROM补丁，很幸运的是Mix 2s已经有人进行了适配，所以我们直接用轮子就好了。
我们打开相关页面，下载multirom_14-08-19.zip和recovery_3.3.1_17-08-19.img两个文件，储存在手机根目录或者U盘里，然后重启手机进入Recovery模式。
使用TWRP先刷入MultiROM补丁到原始ROM（操作与刷入Magisk类似，使用Install ZIP），再将recovery分区替换为MultiROM专用TWRP（使用Install Image）。
完成后再次重启手机，即可看到MultiROM已经安装完毕，此时理论上就可以使用MultiROM安装第二个ROM了。
三、安装第二个ROM 此时进入Recovery分区，也能通过点击右上角的菜单进入MultiROM的配置菜单
点击Add ROM，ROM类型选择Android，安装地点选择内置储存Internal Storage
选择你想要安装的ROM即可。
教程结束。显然不会这么简单，如果你安装的两个ROM都是安卓9及以下，而且是比较轻量化的ROM或者官方系统，那么以上应该就够了。但是如果你是安装安卓10或者含有root或者大量魔改的ROM，那么你的工作，才刚刚开始……
四、安装Pixel Experience 根据XDA论坛上提供MultiROM的大神的介绍，安卓10需要作为主ROM进行安装，具体可能与安卓10的加密机制有关。（具体原因尚不清楚，但是在安装完基于安卓10的系统后，文件系统是被加密的，需要安装MultiROM的补丁才能禁用掉加密）。</description>
      <content:encoded><![CDATA[<blockquote>
<p>折腾了两天，总算成功实现了安卓手机的多系统，在此记录一下，权且做一个教程，给其他热爱折腾的人做一点参考。</p>
</blockquote>
<p>首先要说明的是安装双系统乃至多系统，尤其是在手机上，对于很多人来说绝对是非常鸡肋的，而且安装的过程肯定会造成原先数据的丢失等等，安装之后也不能保证所有功能的正常（比如视频），但是对于爱玩机的人来说，能够经常体验不同的ROM还是很重要的。我之所以想安装多系统，就是因为发现了两个都让我非常喜欢的ROM——<a href="https://download.pixelexperience.org/">Pixel Experience</a> 和 <a href="https://www.lt2333.com/">Simplicity</a>。这两个ROM可谓是两个极端，一个是纯原生安卓的体验，手感非常的好，吊打国内的各大ROM（这才是安卓啊），另一个则是浓厚的极客气息（自带Magisk、Busybox，以及各种底层破解……），在分别体验了两个ROM之后，我发现对它们都是爱不释手。小孩子才做选择，成年人全都要，多启动的想法自然而然地萌生了出来。</p>
<blockquote>
<p>我的设备是Xiaomi Mix 2s (polaris) 国行6+64GB，其他设备的用户本教程可能并不适用，仅供参考</p>
</blockquote>
<blockquote>
<p><strong>免责声明：本人不对任何教程中的操作造成的数据丢失以及设备损坏负责，请在操作前做好数据备份</strong></p>
</blockquote>
<h1 id="一常见方案">一、常见方案</h1>
<p>折腾前当然要看看有啥现成的轮子了，大致研究了一下界内的方案，基本都在<a href="https://www.xda-developers.com/dual-boot-on-android-a-power-users-holy-grail/">XDA的这篇文章</a>里讲到了，这里简单概括一下。</p>
<h2 id="multirom">MultiROM</h2>
<p><img loading="lazy" src="/old-pics/illustrations/2020.01.26.MultiROM/01.png" alt=""  />
</p>
<p><a href="https://github.com/Tasssadar/multirom/wiki">官方Wiki</a></p>
<p>作用于bootloader之后，可以用于引导不同的系统（含Linux），XDA称这是“已知的最好的多系统解决方案”。</p>
<p><a href="https://forum.xda-developers.com/xiaomi-mi-mix-2s/how-to/multirom-multirom-polaris-t3957428">https://forum.xda-developers.com/xiaomi-mi-mix-2s/how-to/multirom-multirom-polaris-t3957428</a></p>
<h2 id="dualboot-patcher">DualBoot Patcher</h2>
<!-- raw HTML omitted -->
<p><a href="https://dbp.noobdev.io/">官网</a></p>
<p>非常有名的安卓引导工具，XDA高级成员，陈小龙大牛开发&amp;&amp;维护，但是在安卓10到来之后，开发者停止维护了。主要是由于新版安卓在架构上的一些调整造成了开发的困难。但是我想要安装Pixel Experience正是基于安卓10的，所以这个方案不行。</p>
<h2 id="grub-for-android">GRUB for Android</h2>
<!-- raw HTML omitted -->
<p>GRUB是x86架构上知名的引导程序，那么GRUB4Android顾名思义也是一个原生bootloader的替代品。现在这个项目已经衍生为了<a href="http://efidroid.org/">EFIDroid</a>，但是看了一下官网最后一次更新是2016年，现在貌似也没有对Mix 2s进行适配，所以就放弃了。</p>
<p>综合以上，我最后选择MultiROM作为多系统的解决方案。</p>
<h1 id="二安装multirom版twrp">二、安装MultiROM版TWRP</h1>
<p>在安装ROM之前，我们首先需要对引导程序进行一些处理。</p>
<h2 id="1-解锁bootloader">1. 解锁BootLoader</h2>
<p>BootLoader是嵌入式设备在操作系统内核运行之前运行的一段程序，它相当于控制了整个启动的大方向，厂商往往会在BootLoader里加入一些检查代码，限制非官方的系统的启动。因此如果想要进行刷机、root等操作，必须将厂商的限制解除。</p>
<p>由于BootLoader与硬件强绑定，因此必须通过厂商的官方途径（<del>或者万能的淘宝</del>）进行解锁。小米官方提供了解锁方式，傻瓜操作，在此略过。</p>
<h2 id="2-刷入recovery">2. 刷入Recovery</h2>
<p>安卓刷机一般使用<a href="https://twrp.me/">TWRP</a>，这是一个开源的第三方Recovery，可以用于替换官方的Recovery，从而更方便地进行刷机等操作。</p>
<p>刷入的过程非常简单，重启手机进入fastboot模式之后，连接手机与电脑，使用ADB进行以下操作：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">fastboot devices
</span></span><span class="line"><span class="cl"><span class="c1"># 检查设备连接状态</span>
</span></span><span class="line"><span class="cl">fastboot flash recovery your-TWRP.img
</span></span><span class="line"><span class="cl"><span class="c1"># 将TWRP烧入Recovery</span>
</span></span></code></pre></div><p>现在，TWRP已经在你的手机的Recovery分区下了。</p>
<h2 id="3-安装multirom补丁">3. 安装MultiROM补丁</h2>
<p>但是原版的TWRP并不支持多系统，因此我们需要安装TWRP之后打补丁，并替换MultiROM专用的TWRP版本。</p>
<p>而且因为嵌入式的强硬件相关性，我们需要根据自己的设备选择专用的MultiROM补丁，很幸运的是Mix 2s已经有人进行了适配，所以我们直接用轮子就好了。</p>
<p>我们打开<a href="https://forum.xda-developers.com/xiaomi-mi-mix-2s/how-to/multirom-multirom-polaris-t3957428">相关页面</a>，下载<code>multirom_14-08-19.zip</code>和<code>recovery_3.3.1_17-08-19.img</code>两个文件，储存在手机根目录或者U盘里，然后重启手机进入Recovery模式。</p>
<!-- raw HTML omitted -->
<p>使用TWRP先刷入MultiROM补丁到原始ROM（操作与刷入Magisk类似，使用<code>Install ZIP</code>），再将recovery分区替换为MultiROM专用TWRP（使用<code>Install Image</code>）。</p>
<!-- raw HTML omitted -->
<p>完成后再次重启手机，即可看到MultiROM已经安装完毕，此时理论上就可以使用MultiROM安装第二个ROM了。</p>
<h1 id="三安装第二个rom">三、安装第二个ROM</h1>
<p>此时进入Recovery分区，也能通过点击右上角的菜单进入MultiROM的配置菜单</p>
<!-- raw HTML omitted -->
<p>点击<code>Add ROM</code>，ROM类型选择<code>Android</code>，安装地点选择内置储存<code>Internal Storage</code></p>
<!-- raw HTML omitted -->
<p>选择你想要安装的ROM即可。</p>
<!-- raw HTML omitted -->
<p><del>教程结束</del>。显然不会这么简单，如果你安装的两个ROM都是安卓9及以下，而且是比较轻量化的ROM或者官方系统，那么以上应该就够了。但是如果你是安装安卓10或者含有root或者大量魔改的ROM，那么你的工作，才刚刚开始……</p>
<h1 id="四安装pixel-experience">四、安装Pixel Experience</h1>
<p><del>根据XDA论坛上提供MultiROM的大神的介绍，安卓10需要作为主ROM进行安装，具体可能与安卓10的加密机制有关。（具体原因尚不清楚，但是在安装完基于安卓10的系统后，文件系统是被加密的，需要安装MultiROM的补丁才能禁用掉加密）。</del></p>
<p>后来测试发现安卓10测试版也是可以直接刷入的……，可能只是Pixel Experience必须作为主ROM安装，或者安卓10正式版不能作为次ROM安装。</p>
<p>总之安卓10（在我这儿我选择的是Pixel Experience）必须在一开始就安装，然后在重启手机完成初始化之后再打补丁（不然可能会再初始化时卡住）。</p>
<p>在检查安卓10可以正常启动，MultiROM工作正常后，我们就可以继续安装其他的ROM了。</p>
<h1 id="五魔改并安装其他rom">五、魔改并安装其他ROM</h1>
<h2 id="1-miui10">1. MIUI10</h2>
<p>MIUI是基于安卓9的（虽然小米修改安卓版本号为10.0.0，但是实际上还是9的底层）。</p>
<p>使用MIUI10开发版（版本号9.8.22），可以正常作为Secondary ROM安装，没有遇到大问题。</p>
<h2 id="2-simplicity">2. Simplicity</h2>
<p>首先尝试安装最新版的基于安卓10的Simpilicty，直接安装会触发<code>E1001: Failed to update system image.</code>的报错。</p>
<!-- raw HTML omitted -->
<p>然后尝试安装基于安卓9的旧版Simplicity，发现仍然会触发这个报错。考虑到Simplicity本质上就是对MIUI的破解，开始对旧版Simplicity的ROM进行魔改。</p>
<p>因为安卓的ROM安装过程是由<code>updater-script</code>脚本控制的，它位于<code>your-ROM.zip\META-INF\com\google\android</code>目录下。打开后发现官方能够直接作为第二系统刷入的ROM是按照<code>boot</code>、<code>system</code>、<code>vendor</code>、<code>firmware</code>的顺序进行patch的，而Simplicity是按照<code>boot</code>、<code>firmware</code>、<code>system</code>、<code>vendor</code>的顺序进行patch的，于是修改<code>updater-script</code>，将patch顺序进行调换。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1">## BEFORE</span>
</span></span><span class="line"><span class="cl">ui_print<span class="o">(</span><span class="s2">&#34;Patching boot image unconditionally...&#34;</span><span class="o">)</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">package_extract_file<span class="o">(</span><span class="s2">&#34;boot.img&#34;</span>, <span class="s2">&#34;/dev/block/bootdevice/by-name/boot&#34;</span><span class="o">)</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">ui_print<span class="o">(</span><span class="s2">&#34;Patching firmware images...&#34;</span><span class="o">)</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">package_extract_file<span class="o">(</span><span class="s2">&#34;firmware-update/dsp.img&#34;</span>, <span class="s2">&#34;/dev/block/bootdevice/by-name/dsp&#34;</span><span class="o">)</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">... <span class="c1"># details omitted</span>
</span></span><span class="line"><span class="cl">package_extract_file<span class="o">(</span><span class="s2">&#34;firmware-update/hyp.img&#34;</span>, <span class="s2">&#34;/dev/block/bootdevice/by-name/hyp_b&#34;</span><span class="o">)</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">show_progress<span class="o">(</span>0.600000, 250<span class="o">)</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">ui_print<span class="o">(</span><span class="s2">&#34;Patching system image unconditionally...&#34;</span><span class="o">)</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">block_image_update<span class="o">(</span><span class="s2">&#34;/dev/block/bootdevice/by-name/system&#34;</span>, package_extract_file<span class="o">(</span><span class="s2">&#34;system.transfer.list&#34;</span><span class="o">)</span>, <span class="s2">&#34;system.new.dat&#34;</span>, <span class="s2">&#34;system.patch.dat&#34;</span><span class="o">)</span> <span class="o">||</span>
</span></span><span class="line"><span class="cl">  abort<span class="o">(</span><span class="s2">&#34;E1001: Failed to update system image.&#34;</span><span class="o">)</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">ui_print<span class="o">(</span><span class="s2">&#34;Patching vendor image unconditionally...&#34;</span><span class="o">)</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">block_image_update<span class="o">(</span><span class="s2">&#34;/dev/block/bootdevice/by-name/vendor&#34;</span>, package_extract_file<span class="o">(</span><span class="s2">&#34;vendor.transfer.list&#34;</span><span class="o">)</span>, <span class="s2">&#34;vendor.new.dat&#34;</span>, <span class="s2">&#34;vendor.patch.dat&#34;</span><span class="o">)</span> <span class="o">||</span>
</span></span><span class="line"><span class="cl">  abort<span class="o">(</span><span class="s2">&#34;E2001: Failed to update vendor image.&#34;</span><span class="o">)</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">ui_print<span class="o">(</span><span class="s2">&#34; &#34;</span><span class="o">)</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">## AFTER</span>
</span></span><span class="line"><span class="cl"><span class="c1"># Patch boot first</span>
</span></span><span class="line"><span class="cl">ui_print<span class="o">(</span><span class="s2">&#34;Patching boot image unconditionally...&#34;</span><span class="o">)</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">package_extract_file<span class="o">(</span><span class="s2">&#34;boot.img&#34;</span>, <span class="s2">&#34;/dev/block/bootdevice/by-name/boot&#34;</span><span class="o">)</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Patch system and vendor before firmware</span>
</span></span><span class="line"><span class="cl">ui_print<span class="o">(</span><span class="s2">&#34;Patching system image unconditionally...&#34;</span><span class="o">)</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">block_image_update<span class="o">(</span><span class="s2">&#34;/dev/block/bootdevice/by-name/system&#34;</span>, package_extract_file<span class="o">(</span><span class="s2">&#34;system.transfer.list&#34;</span><span class="o">)</span>, <span class="s2">&#34;system.new.dat&#34;</span>, <span class="s2">&#34;system.patch.dat&#34;</span><span class="o">)</span> <span class="o">||</span>
</span></span><span class="line"><span class="cl">  abort<span class="o">(</span><span class="s2">&#34;E1001: Failed to update system image.&#34;</span><span class="o">)</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">ui_print<span class="o">(</span><span class="s2">&#34;Patching vendor image unconditionally...&#34;</span><span class="o">)</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">block_image_update<span class="o">(</span><span class="s2">&#34;/dev/block/bootdevice/by-name/vendor&#34;</span>, package_extract_file<span class="o">(</span><span class="s2">&#34;vendor.transfer.list&#34;</span><span class="o">)</span>, <span class="s2">&#34;vendor.new.dat&#34;</span>, <span class="s2">&#34;vendor.patch.dat&#34;</span><span class="o">)</span> <span class="o">||</span>
</span></span><span class="line"><span class="cl">  abort<span class="o">(</span><span class="s2">&#34;E2001: Failed to update vendor image.&#34;</span><span class="o">)</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">ui_print<span class="o">(</span><span class="s2">&#34; &#34;</span><span class="o">)</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Patch firmware at last</span>
</span></span><span class="line"><span class="cl">ui_print<span class="o">(</span><span class="s2">&#34;Patching firmware images...&#34;</span><span class="o">)</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">package_extract_file<span class="o">(</span><span class="s2">&#34;firmware-update/dsp.img&#34;</span>, <span class="s2">&#34;/dev/block/bootdevice/by-name/dsp&#34;</span><span class="o">)</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">... <span class="c1"># details omitted</span>
</span></span><span class="line"><span class="cl">package_extract_file<span class="o">(</span><span class="s2">&#34;firmware-update/hyp.img&#34;</span>, <span class="s2">&#34;/dev/block/bootdevice/by-name/hyp_b&#34;</span><span class="o">)</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">show_progress<span class="o">(</span>0.600000, 250<span class="o">)</span><span class="p">;</span>
</span></span></code></pre></div><p>修改之后，即可正常安装，重启后能够进入系统，root等功能正常，安装成功。</p>
<h1 id="六体验与缺陷">六、体验与缺陷</h1>
<p>整体来讲，双系统的切换还算流畅，切换的成本不是很高。</p>
<p>作为主系统的Pixel Experience手感非常好，功能基本正常，但是每次启动的时候都要重新设置时间，双摄不能正常使用（未适配）。</p>
<p>作为次系统的Simplicity有各种极客功能，主题也被破解了，可以免费换自己喜欢的使用，内置的迅雷下载加速也被破解为付费模式，可以把家里带宽跑满。但是估计是由于MulitROM启动次系统的时候只切换部分挂载的原因，GPU或者DSP驱动似乎有些问题，导致视频解码有问题，视频无法正常播放（作为次系统的MIUI也有这个问题）。</p>
<p>整体来说，还是实现了一开始的目的，反正小米也不是日用主力机，Pixel主要是用手感和Google的全家桶（手动狗头），Simplicity主要就是为了下载奇怪的资源和一些ROOT功能（比如虚拟定位，再次狗头）。</p>
<p>当然折腾的过程也大致了解了一些安卓底层的东西，但是所知还是甚少，看来还是要多读书，多学习（狗头.jpg</p>
<hr>
<p>踩坑完毕</p>
]]></content:encoded>
    </item>
    <item>
      <title>校网环境下的私人服务器解决方案</title>
      <link>https://blog.chong-zeng.com/posts/2019-07-10_dorm_server/</link>
      <pubDate>Wed, 10 Jul 2019 00:00:00 +0000</pubDate>
      <guid>https://blog.chong-zeng.com/posts/2019-07-10_dorm_server/</guid>
      <description>CS狗一枚，几乎每天都需要携带电脑。最近感觉轻薄本性能不太够用，但是游戏本又太厚太重、散热续航也不太行，于是想到在寝室部署一台台式机，然后远程访问计算资源的方案。考虑到校网拓扑的复杂以及供电等原因，最近先进行了一些理论验证，并成功组建了一个个人网络以及一些个人网络服务。以下是过程的简单记录。
一、路由器的必要性与选购 在ZJU，寝室要想访问外网，只有两个方案——学校的WiFi或者有线网VPN拨号。考虑到ZJUWLAN严重的丢包问题，以及时不时被踢下需要重新验证的问题，我毫不犹豫地选择了有线网。
但是由于学校的另一条规定——每个VPN账号只能在一台电脑上登录，而我手上的需要联网的设备远不止两台，因此路由器的出现就很有必要了。
使用路由器的另一个好处是如果VPN掉线会自动重新拨号，在之后的服务搭建中，虚拟服务器功能也起到了极大的作用。因此路由器是非常必要的。
至于选购的话，其实只要支持L2TP即可，不过最近很多家用路由器都取消了这个功能，所以采购的时候还是留点心为好，至少不要以为所有路由器都支持这玩意。
二、网络拓扑的设计以及IP地址的获取 1. 有线连接与无线连接的选择 寝室需要一直联网的设备：
Windows电脑一台 树莓派3b+ 这两个设备均采用有线连接，特别是Windows电脑，因为RDP需要传输图像，并且出于鲁棒性考虑同时也连接了无线网，以免出现有线网卡莫名出故障导致无法访问的意外
树莓派连有线是因为需要高带宽，毕竟作为下载机（校内P2P下载）
当我回到寝室时，可能iPhone和小米都要联网，以及我的kindle和Ubuntu笔记本
这些设备直接使用无线网连接好了，毕竟连接外网的带宽也就12Mbps，有线网带宽可谓是绰绰有余
2. 不使用DMZ的原因 不安全，直接把某一台电脑的所有端口直接暴露在外网中是一件极其危险的事情 DMZ只能转发请求到一台设备，但是我的Windows和Pi都需要跑服务，各自有不同的端口需要转发，这是DMZ不支持的 因此，我选择使用虚拟服务器进行配置
3. 虚拟服务器实现端口转发 目前需要的服务：
服务 端口号 Windows上的RDP 3389 Windows上WSL中的Jupyter Lab 8080 Windows上WSL的SSH 22 Pi上的FTP 21 Pi上的BT下载监控 9091 Pi上的Web服务 8080 Pi上的SSH 22 将相应端口进行分别转发即可
对于Windows上Lab和Pi上Web等端口相同的问题，直接在外网设置不同的端口，再分别转发即可，甚至出于安全考虑，更加推荐避免内外端口一致，以防闲的没事的人（暗指某室友）突然访问你的各种服务……（当然他要是知道了我的IP还是可以一个端口一个端口逐个扫描……）
好在他并不知道我的IP，甚至如果我在外面的话，自己都不太方便知道自己的IP……
这就引出了下面的重磅话题——
4. 查看IP地址的方法 不要问我为什么不申请固定IP……（手慢无 被申请完了……)
另外申请的固定IP其实是比公网IP低一级的，而对于我这种直接通过VPN拨号访问外网的用户，即使申请到了固定IP也是没法用到L2TP拨号中的，因为我是直接连到学校总对外网关上的，跳过了宿舍网关这一层（这也导致直接通过宿舍有线网是无法ping通我的）
同时，每次路由器掉线重拨后，IP地址都会变。这就令人十分窒息，因为有时候就算早上出门前瞅一眼路由器的IP，中午的时候它可能就又变了……
于是就有了以下几种可能的方案：
1. 在大致的网段范围内逐个扫描 效率多低、多慢就不用说吧……
2. 定时推送最新IP 推送的方式有无数种，如QQ、微信、邮件等，此处不赘述
对于推送的时间，之前设想的是每天早上上电之后推送，但是现在发现IP居然可以一日多变……
半小时一推的话，如果IP变化恰好处在了06:30:19之类的时间，那就干等半小时吧
5min一推怕是跟骚扰信息一样……
比较好的方案应该是5min获取一次IP，然后跟上次的比对，如果不同再推送
但是
如何获取IP呢？
不要以为这个问题很简单，如果你试着ifconfig的话，会发现得到的是自己小网络里面的ip……
如果用网上给出的方法，用爬虫爬一些IP查询网站，会发现给你的是公网IP，而不是学校网关分配给你的那个……
哦豁！
我目前的想法是，直接爬虫登录路由器管理页面，然后找出里面的IP信息……
如果有更好的方案，请让我知道，谢谢
3. 内网穿透 域名我是有的，构建的流程也基本上清楚，但是如果内网的IP总是在变的话，也没法穿透……</description>
      <content:encoded><![CDATA[<p>CS狗一枚，几乎每天都需要携带电脑。最近感觉轻薄本性能不太够用，但是游戏本又太厚太重、散热续航也不太行，于是想到在寝室部署一台台式机，然后远程访问计算资源的方案。考虑到校网拓扑的复杂以及供电等原因，最近先进行了一些理论验证，并成功组建了一个个人网络以及一些个人网络服务。以下是过程的简单记录。</p>
<hr>
<h1 id="一路由器的必要性与选购">一、路由器的必要性与选购</h1>
<p>在ZJU，寝室要想访问外网，只有两个方案——学校的WiFi或者有线网VPN拨号。考虑到ZJUWLAN严重的丢包问题，以及时不时被踢下需要重新验证的问题，我毫不犹豫地选择了有线网。</p>
<p>但是由于学校的另一条规定——每个VPN账号只能在一台电脑上登录，而我手上的需要联网的设备远不止两台，因此路由器的出现就很有必要了。</p>
<p>使用路由器的另一个好处是如果VPN掉线会自动重新拨号，在之后的服务搭建中，虚拟服务器功能也起到了极大的作用。因此路由器是非常必要的。</p>
<p>至于选购的话，其实只要支持L2TP即可，不过最近很多家用路由器都取消了这个功能，所以采购的时候还是留点心为好，至少不要以为所有路由器都支持这玩意。</p>
<h1 id="二网络拓扑的设计以及ip地址的获取">二、网络拓扑的设计以及IP地址的获取</h1>
<h2 id="1-有线连接与无线连接的选择">1. 有线连接与无线连接的选择</h2>
<p>寝室需要一直联网的设备：</p>
<ul>
<li>Windows电脑一台</li>
<li>树莓派3b+</li>
</ul>
<p>这两个设备均采用有线连接，特别是Windows电脑，因为RDP需要传输图像，并且出于鲁棒性考虑同时也连接了无线网，以免出现有线网卡莫名出故障导致无法访问的意外</p>
<p>树莓派连有线是因为需要高带宽，毕竟作为下载机（校内P2P下载）</p>
<p>当我回到寝室时，可能iPhone和小米都要联网，以及我的kindle和Ubuntu笔记本</p>
<p>这些设备直接使用无线网连接好了，毕竟连接外网的带宽也就12Mbps，有线网带宽可谓是绰绰有余</p>
<h2 id="2-不使用dmz的原因">2. 不使用DMZ的原因</h2>
<ol>
<li>不安全，直接把某一台电脑的所有端口直接暴露在外网中是一件极其危险的事情</li>
<li>DMZ只能转发请求到一台设备，但是我的Windows和Pi都需要跑服务，各自有不同的端口需要转发，这是DMZ不支持的</li>
</ol>
<p>因此，我选择使用虚拟服务器进行配置</p>
<h2 id="3-虚拟服务器实现端口转发">3. 虚拟服务器实现端口转发</h2>
<p>目前需要的服务：</p>
<table>
<thead>
<tr>
<th>服务</th>
<th>端口号</th>
</tr>
</thead>
<tbody>
<tr>
<td>Windows上的RDP</td>
<td>3389</td>
</tr>
<tr>
<td>Windows上WSL中的Jupyter Lab</td>
<td>8080</td>
</tr>
<tr>
<td>Windows上WSL的SSH</td>
<td>22</td>
</tr>
<tr>
<td>Pi上的FTP</td>
<td>21</td>
</tr>
<tr>
<td>Pi上的BT下载监控</td>
<td>9091</td>
</tr>
<tr>
<td>Pi上的Web服务</td>
<td>8080</td>
</tr>
<tr>
<td>Pi上的SSH</td>
<td>22</td>
</tr>
</tbody>
</table>
<p>将相应端口进行分别转发即可</p>
<p>对于Windows上Lab和Pi上Web等端口相同的问题，直接在外网设置不同的端口，再分别转发即可，甚至出于安全考虑，更加推荐避免内外端口一致，以防闲的没事的人（<del>暗指某室友</del>）突然访问你的各种服务……（当然他要是知道了我的IP还是可以一个端口一个端口逐个扫描……）</p>
<p>好在他并不知道我的IP，甚至如果我在外面的话，自己都不太方便知道自己的IP……</p>
<p>这就引出了下面的重磅话题——</p>
<h2 id="4-查看ip地址的方法">4. 查看IP地址的方法</h2>
<p>不要问我为什么不申请固定IP……（<del>手慢无</del> 被申请完了……)</p>
<p>另外申请的固定IP其实是比公网IP低一级的，而对于我这种直接通过VPN拨号访问外网的用户，即使申请到了固定IP也是没法用到L2TP拨号中的，因为我是直接连到学校总对外网关上的，跳过了宿舍网关这一层（这也导致直接通过宿舍有线网是无法ping通我的）</p>
<p>同时，每次路由器掉线重拨后，IP地址都会变。这就令人十分窒息，因为有时候就算早上出门前瞅一眼路由器的IP，中午的时候它可能就又变了……</p>
<p>于是就有了以下几种可能的方案：</p>
<h3 id="1-在大致的网段范围内逐个扫描">1. 在大致的网段范围内逐个扫描</h3>
<p>效率多低、多慢就不用说吧……</p>
<h3 id="2-定时推送最新ip">2. 定时推送最新IP</h3>
<p>推送的方式有无数种，如QQ、微信、邮件等，此处不赘述</p>
<p>对于推送的时间，之前设想的是每天早上上电之后推送，但是现在发现IP居然可以一日多变……</p>
<p>半小时一推的话，如果IP变化恰好处在了06:30:19之类的时间，那就干等半小时吧</p>
<p>5min一推怕是跟骚扰信息一样……</p>
<p>比较好的方案应该是5min获取一次IP，然后跟上次的比对，如果不同再推送</p>
<p><strong>但是</strong></p>
<p>如何获取IP呢？</p>
<p>不要以为这个问题很简单，如果你试着ifconfig的话，会发现得到的是自己小网络里面的ip……</p>
<p>如果用网上给出的方法，用爬虫爬一些IP查询网站，会发现给你的是公网IP，而不是学校网关分配给你的那个……</p>
<p>哦豁！</p>
<p>我目前的想法是，直接爬虫登录路由器管理页面，然后找出里面的IP信息……</p>
<blockquote>
<p>如果有更好的方案，请让我知道，谢谢</p>
</blockquote>
<h3 id="3-内网穿透">3. 内网穿透</h3>
<p>域名我是有的，构建的流程也基本上清楚，但是如果内网的IP总是在变的话，也没法穿透……</p>
<h3 id="3-直接使用路由器厂商的外网管理服务">3. 直接使用路由器厂商的外网管理服务</h3>
<p>最简单粗暴，但是最有效</p>
<p>于是我就选了这个最没有技术含量的方案……（<del>太菜了没办法</del>……）</p>
<p>能找到寝室路由器（或者叫网关更贴切）后，就可以开始下面的各项工作了</p>
<h1 id="三远程桌面服务的配置">三、远程桌面服务的配置</h1>
<p>Win10专业版可以直接开启RDP</p>
<p>Win10家庭版可以通过GItHub上的开源工具(<a href="https://github.com/stascorp/rdpwrap">https://github.com/stascorp/rdpwrap</a> )开启RDP，但是不太稳定（每次连接前需要使用工具手动开启一下）</p>
<blockquote>
<p>server机的缩放最好设为100%，不然client机连接之后可能会出现菜单显示很奇怪的问题</p>
</blockquote>
<h1 id="四jupyter-lab的配置">四、Jupyter Lab的配置</h1>
<p>跑在Windows主机下的WSL中，因为Windows下开发环境实在是太难配置了</p>
<p>当然，如果之后的使用中发现WSL有明显的性能损失的话，不排除还是会回归纯Linux</p>
<h1 id="四基于树莓派的下载机">四、基于树莓派的下载机</h1>
<h2 id="1-aria2">1. Aria2</h2>
<p>主要用于普通链接的下载</p>
<h2 id="2-transmission-bt下载机">2. Transmission BT下载机</h2>
<p>主要用于HND上面的校内BT资源下载</p>
<hr>
<p>目前这套方案运作良好，如果之后有改进会在后续文章中介绍</p>
]]></content:encoded>
    </item>
    <item>
      <title>记一次奇葩的爬虫踩坑经历</title>
      <link>https://blog.chong-zeng.com/posts/2019-04-04_crawl_notes/</link>
      <pubDate>Thu, 04 Apr 2019 00:00:00 +0000</pubDate>
      <guid>https://blog.chong-zeng.com/posts/2019-04-04_crawl_notes/</guid>
      <description>2020.05.31更新：发现自己以前好菜啊……（
慢慢来吧……
摘要：
想利用爬虫实现半夜自动抢图书馆座位的功能，这样晚上就可以多睡一会了……
但是提交申请时发现有一个参数很诡异……
下面就是研究这个参数的生成方式，过程很奇葩 主要还是因为我是新手
研究过程曲折但是很有趣，因此记录一下
如果你是大佬或者懒得往下慢慢看，那我直接告诉你结论好了——就是网站自己的js代码没有生成这个参数，这个参数只能是jQuery本身在提交GET请求时额外添加的，后来发现这参数其实就是时间戳……
登陆已经解决，是一个POST，抓对包之后几乎没什么门槛
提交预约申请使用了Ajax异步技术，因此只需要模拟js脚本提交GET请求即可
抓包分析看到&amp;quot;act&amp;quot;:&amp;quot;set_resv&amp;quot;，&amp;amp;act=set_resv
在源码VM310中搜索set_resv，看到第537行有对于fRsv()的调用
pro.j.rsv.fRsv(&amp;#34;set_resv&amp;#34;, $(&amp;#34;form:first&amp;#34;, dlg), function () { if (uni_calendar_dft_opt.submitSuc) { uni_calendar_dft_opt.submitSuc(dlg, obj); } else { var msg = &amp;#39;申请提交成功，是否跳转查看预约信息?&amp;#39;; if (parseInt(obj.minUser) &amp;gt; 1) { msg += &amp;#34;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;div style=&amp;#39;font-weight:bold;&amp;#39;&amp;gt;&amp;#34; + uni.translate(&amp;#34;注意！生效后需至少&amp;#34;) + &amp;#34;&amp;lt;span style=&amp;#39;color:red;font-size:bold;&amp;#39;&amp;gt;&amp;#34; + obj.minUser + &amp;#34;&amp;lt;/span&amp;gt;&amp;#34; + uni.translate(&amp;#34;人刷卡，否则将记为违约！&amp;#34;) + &amp;#34;&amp;lt;/div&amp;gt;&amp;#34;; } uni.confirm(msg, function () { $(&amp;#34;#user_center&amp;#34;).trigger(&amp;#34;click&amp;#34;); }, function () { uni.reload(); }); $(&amp;#34;.group_id&amp;#34;, dlg).val(&amp;#34;&amp;#34;); $(&amp;#34;.group_name&amp;#34;, dlg).html(&amp;#34;小组未创建&amp;#34;); dlg.</description>
      <content:encoded><![CDATA[<blockquote>
<p>2020.05.31更新：发现自己以前好菜啊……（</p>
<p>慢慢来吧……</p>
</blockquote>
<hr>
<blockquote>
<p>摘要：</p>
<p>想利用爬虫实现半夜自动抢图书馆座位的功能，这样晚上就可以多睡一会了……</p>
<p>但是提交申请时发现有一个参数很诡异……</p>
<p>下面就是研究这个参数的生成方式，过程很奇葩 <del>主要还是因为我是新手</del></p>
<p>研究过程曲折但是很有趣，因此记录一下</p>
</blockquote>
<p>如果你是大佬或者懒得往下慢慢看，那我直接告诉你结论好了——就是网站自己的js代码没有生成这个参数，这个参数只能是jQuery本身在提交GET请求时额外添加的，后来发现这参数其实就是时间戳……</p>
<hr>
<p>登陆已经解决，是一个POST，抓对包之后几乎没什么门槛</p>
<p>提交预约申请使用了Ajax异步技术，因此只需要模拟js脚本提交GET请求即可</p>
<p>抓包分析看到<code>&quot;act&quot;:&quot;set_resv&quot;</code>，<code>&amp;act=set_resv</code></p>
<p>在源码<code>VM310</code>中搜索<code>set_resv</code>，看到第537行有对于<code>fRsv()</code>的调用</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="nx">pro</span><span class="p">.</span><span class="nx">j</span><span class="p">.</span><span class="nx">rsv</span><span class="p">.</span><span class="nx">fRsv</span><span class="p">(</span><span class="s2">&#34;set_resv&#34;</span><span class="p">,</span> <span class="nx">$</span><span class="p">(</span><span class="s2">&#34;form:first&#34;</span><span class="p">,</span> <span class="nx">dlg</span><span class="p">),</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                <span class="k">if</span> <span class="p">(</span><span class="nx">uni_calendar_dft_opt</span><span class="p">.</span><span class="nx">submitSuc</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                    <span class="nx">uni_calendar_dft_opt</span><span class="p">.</span><span class="nx">submitSuc</span><span class="p">(</span><span class="nx">dlg</span><span class="p">,</span> <span class="nx">obj</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">                <span class="p">}</span>
</span></span><span class="line"><span class="cl">                <span class="k">else</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                    <span class="kd">var</span> <span class="nx">msg</span> <span class="o">=</span> <span class="s1">&#39;申请提交成功，是否跳转查看预约信息?&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">                    <span class="k">if</span> <span class="p">(</span><span class="nb">parseInt</span><span class="p">(</span><span class="nx">obj</span><span class="p">.</span><span class="nx">minUser</span><span class="p">)</span> <span class="o">&gt;</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                        <span class="nx">msg</span> <span class="o">+=</span> <span class="s2">&#34;&lt;br/&gt;&lt;br/&gt;&lt;div style=&#39;font-weight:bold;&#39;&gt;&#34;</span> <span class="o">+</span> <span class="nx">uni</span><span class="p">.</span><span class="nx">translate</span><span class="p">(</span><span class="s2">&#34;注意！生效后需至少&#34;</span><span class="p">)</span> <span class="o">+</span> <span class="s2">&#34;&lt;span style=&#39;color:red;font-size:bold;&#39;&gt;&#34;</span> <span class="o">+</span> <span class="nx">obj</span><span class="p">.</span><span class="nx">minUser</span> <span class="o">+</span> <span class="s2">&#34;&lt;/span&gt;&#34;</span> <span class="o">+</span> <span class="nx">uni</span><span class="p">.</span><span class="nx">translate</span><span class="p">(</span><span class="s2">&#34;人刷卡，否则将记为违约！&#34;</span><span class="p">)</span> <span class="o">+</span> <span class="s2">&#34;&lt;/div&gt;&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">                    <span class="p">}</span>
</span></span><span class="line"><span class="cl">                    <span class="nx">uni</span><span class="p">.</span><span class="nx">confirm</span><span class="p">(</span><span class="nx">msg</span><span class="p">,</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                        <span class="nx">$</span><span class="p">(</span><span class="s2">&#34;#user_center&#34;</span><span class="p">).</span><span class="nx">trigger</span><span class="p">(</span><span class="s2">&#34;click&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">                    <span class="p">},</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                        <span class="nx">uni</span><span class="p">.</span><span class="nx">reload</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">                    <span class="p">});</span>
</span></span><span class="line"><span class="cl">                    <span class="nx">$</span><span class="p">(</span><span class="s2">&#34;.group_id&#34;</span><span class="p">,</span> <span class="nx">dlg</span><span class="p">).</span><span class="nx">val</span><span class="p">(</span><span class="s2">&#34;&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">                    <span class="nx">$</span><span class="p">(</span><span class="s2">&#34;.group_name&#34;</span><span class="p">,</span> <span class="nx">dlg</span><span class="p">).</span><span class="nx">html</span><span class="p">(</span><span class="s2">&#34;小组未创建&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">                    <span class="nx">dlg</span><span class="p">.</span><span class="nx">dialog</span><span class="p">(</span><span class="s2">&#34;close&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">                <span class="p">}</span>
</span></span><span class="line"><span class="cl">                <span class="c1">//btn.removeAttr(&#34;disabled&#34;);
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>            <span class="p">},</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">rlt</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                
</span></span><span class="line"><span class="cl">                <span class="nx">uni</span><span class="p">.</span><span class="nx">msgBox</span><span class="p">(</span><span class="nx">pro</span><span class="p">.</span><span class="nx">translate</span><span class="p">(</span><span class="nx">rlt</span><span class="p">.</span><span class="nx">msg</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">                <span class="c1">//btn.removeAttr(&#34;disabled&#34;);
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>            <span class="p">},</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                <span class="nx">uni</span><span class="p">.</span><span class="nx">msgBox</span><span class="p">(</span><span class="nx">uni</span><span class="p">.</span><span class="nx">translate</span><span class="p">(</span><span class="s2">&#34;异步连接出现异常！&#34;</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">                <span class="c1">//btn.removeAttr(&#34;disabled&#34;);
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>            <span class="p">});</span>
</span></span></code></pre></div><p>其中传入的实参有一个就是我们的<code>”set_resv”</code>，另外还有一个实参是一个回调函数，用于申请成功后更新页面信息（弹窗），这就是Ajax提交申请的流程。</p>
<p>因此猜测<code>fRsv()</code>完成了对于<code>url</code>的生成和提交</p>
<p>在<code>pro.js</code>中1056行找到了<code>fRsv()</code>的原型</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="nx">fRsv</span><span class="o">:</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">act</span><span class="p">,</span> <span class="nx">$f</span><span class="p">,</span> <span class="nx">suc</span><span class="p">,</span> <span class="nx">fail</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="nx">pro</span><span class="p">.</span><span class="nx">j</span><span class="p">.</span><span class="nx">fGetS</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">p</span><span class="p">,</span> <span class="nx">act</span><span class="p">,</span> <span class="nx">$f</span><span class="p">,</span> <span class="nx">suc</span><span class="p">,</span> <span class="nx">fail</span><span class="p">,</span> <span class="nx">err</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="p">},</span>
</span></span></code></pre></div><p>它又调用了<code>fGetS</code>: (:179)</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="c1">//get方式 form提交 拓展方法
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="nx">fGetS</span><span class="o">:</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">url</span><span class="p">,</span> <span class="nx">act</span><span class="p">,</span> <span class="nx">$f</span><span class="p">,</span> <span class="nx">suc</span><span class="p">,</span> <span class="nx">fail</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="kd">var</span> <span class="nx">data</span> <span class="o">=</span> <span class="p">{};</span>
</span></span><span class="line"><span class="cl">            <span class="nx">data</span><span class="p">.</span><span class="nx">act</span> <span class="o">=</span> <span class="nx">act</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">            <span class="nx">data</span><span class="p">.</span><span class="nx">$f</span> <span class="o">=</span> <span class="nx">$f</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">            <span class="nx">uni</span><span class="p">.</span><span class="nx">j</span><span class="p">.</span><span class="nx">fGet</span><span class="p">(</span><span class="nx">url</span><span class="p">,</span> <span class="nx">data</span><span class="p">,</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">rlt</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                <span class="nx">pro</span><span class="p">.</span><span class="nx">ckV</span><span class="p">(</span><span class="nx">rlt</span><span class="p">,</span> <span class="nx">suc</span><span class="p">,</span> <span class="nx">fail</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">            <span class="p">},</span> <span class="nx">err</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="p">},</span>
</span></span></code></pre></div><p>注意<code>url</code>与<code>this.p</code>对应，因此分析p很关键，因为我们很关心<code>url</code>中的一个诡异的参数<code>_</code>，一旦知道了这个参数就🆗了</p>
<p>类内的p出现在792行</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="nx">pro</span><span class="p">.</span><span class="nx">j</span><span class="p">.</span><span class="nx">rsv</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="c1">//路径
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>        <span class="nx">p</span><span class="o">:</span> <span class="nx">pro</span><span class="p">.</span><span class="nx">dir</span> <span class="o">+</span> <span class="s2">&#34;ajax/reserve.aspx&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="p">...</span>
</span></span></code></pre></div><p>果然见到了我们想要的ajax/reserve.aspx</p>
<p>但是线索有断了，因为p在之后就没有变化过了……</p>
<p>因此p内没有这个参数……</p>
<p>再次将焦点转向<code>fRsv()</code>，看看它如何被调用的</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="nx">pro</span><span class="p">.</span><span class="nx">j</span><span class="p">.</span><span class="nx">rsv</span><span class="p">.</span><span class="nx">fRsv</span><span class="p">(</span><span class="s2">&#34;set_resv&#34;</span><span class="p">,</span> <span class="nx">$</span><span class="p">(</span><span class="s2">&#34;form:first&#34;</span><span class="p">,</span> <span class="nx">dlg</span><span class="p">),</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span><span class="cm">/* 成功之后的提示*/</span><span class="p">},</span><span class="kd">function</span> <span class="p">(</span><span class="nx">rlt</span><span class="p">)</span> <span class="p">{</span><span class="nx">uni</span><span class="p">.</span><span class="nx">msgBox</span><span class="p">(</span><span class="nx">pro</span><span class="p">.</span><span class="nx">translate</span><span class="p">(</span><span class="nx">rlt</span><span class="p">.</span><span class="nx">msg</span><span class="p">));},</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span><span class="nx">uni</span><span class="p">.</span><span class="nx">msgBox</span><span class="p">(</span><span class="nx">uni</span><span class="p">.</span><span class="nx">translate</span><span class="p">(</span><span class="s2">&#34;异步连接出现异常！&#34;</span><span class="p">));});</span>
</span></span></code></pre></div><p>与原型对比分析</p>
<table>
<thead>
<tr>
<th>act</th>
<th>“set_resv”</th>
</tr>
</thead>
<tbody>
<tr>
<td>$f</td>
<td>$(&ldquo;form:first&rdquo;, dlg)</td>
</tr>
<tr>
<td>suc</td>
<td>function () {/* 成功之后的提示*/}</td>
</tr>
<tr>
<td>fail</td>
<td>function (rlt) {uni.msgBox(pro.translate(rlt.msg));}</td>
</tr>
<tr>
<td>err</td>
<td>function () {uni.msgBox(uni.translate(&ldquo;异步连接出现异常！&rdquo;));}</td>
</tr>
</tbody>
</table>
<p>猜测<code>$f</code>是关键</p>
<p><code>$(&quot;form:first&quot;, dlg)</code>是jQuery的多项选择器，匹配出来应该是在dlg中的第一个form</p>
<p>再看看调用</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="c1">// pro.j.fGetS(this.p, act, $f, suc, fail, err);
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="nx">fGets</span><span class="p">(</span><span class="s2">&#34;http://******/ClientWeb/ajax/reserve.aspx&#34;</span><span class="p">,</span> <span class="s2">&#34;set_resv&#34;</span><span class="p">,</span> <span class="nx">$f</span><span class="p">,</span> <span class="nx">suc</span><span class="p">,</span> <span class="nx">fail</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="c1">// http://******/ClientWeb/pro/ajax/reserve.aspx?dialogid=&amp;dev_id=685&amp;lab_id=&amp;kind_id=&amp;room_id=&amp;type=dev&amp;prop=&amp;test_id=&amp;term=&amp;number=&amp;test_name=&amp;start=2019-03-30+18%3A00&amp;end=2019-03-30+20%3A00&amp;start_time=1800&amp;end_time=2000&amp;up_file=&amp;memo=&amp;act=set_resv&amp;_=1553927422652
</span></span></span></code></pre></div><p><code>$f</code>应该对应的就是我们的申请表，也就是抓到的GET请求中的绝大多数参数的来源</p>
<p>果然在页面中找到了它</p>
<p><img loading="lazy" src="/old-pics/illustrations/2019-04-04_Crawl_Notes/1.png" alt=""  />
</p>
<p>完全吻合</p>
<p>看来WebForm就是这个Form+act(“set_resv”)+那个诡异的参数<code>_</code>……</p>
<p>然鹅<code>_</code>还是不知道如何生成的……</p>
<p>因此又猜测生成这个参数的位置就在于<code>fGets()</code></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="nx">fGetS</span><span class="o">:</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">url</span><span class="p">,</span> <span class="nx">act</span><span class="p">,</span> <span class="nx">$f</span><span class="p">,</span> <span class="nx">suc</span><span class="p">,</span> <span class="nx">fail</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="kd">var</span> <span class="nx">data</span> <span class="o">=</span> <span class="p">{};</span>
</span></span><span class="line"><span class="cl">            <span class="nx">data</span><span class="p">.</span><span class="nx">act</span> <span class="o">=</span> <span class="nx">act</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">            <span class="nx">data</span><span class="p">.</span><span class="nx">$f</span> <span class="o">=</span> <span class="nx">$f</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">            <span class="nx">uni</span><span class="p">.</span><span class="nx">j</span><span class="p">.</span><span class="nx">fGet</span><span class="p">(</span><span class="nx">url</span><span class="p">,</span> <span class="nx">data</span><span class="p">,</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">rlt</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                <span class="nx">pro</span><span class="p">.</span><span class="nx">ckV</span><span class="p">(</span><span class="nx">rlt</span><span class="p">,</span> <span class="nx">suc</span><span class="p">,</span> <span class="nx">fail</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">            <span class="p">},</span> <span class="nx">err</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="p">},</span>
</span></span></code></pre></div><p>果然它将act的参数以及form中的参数合并成了data，并传给<code>fGet()</code></p>
<p>其中调用到的<code>ckV()</code>位于<code>pro.js</code>的114行</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="c1">//检查返回值
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="nx">ckV</span><span class="o">:</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">rlt</span><span class="p">,</span> <span class="nx">suc</span><span class="p">,</span> <span class="nx">fail</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="k">if</span> <span class="p">(</span><span class="nx">rlt</span> <span class="o">==</span> <span class="kc">undefined</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                <span class="nx">uni</span><span class="p">.</span><span class="nx">msgBox</span><span class="p">(</span><span class="s2">&#34;返回了空值！&#34;</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="s2">&#34;error&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">                <span class="k">return</span> <span class="kc">false</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">            <span class="p">}</span>
</span></span><span class="line"><span class="cl">            <span class="k">else</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                <span class="k">if</span> <span class="p">(</span><span class="nx">rlt</span><span class="p">.</span><span class="nx">ret</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                    <span class="k">if</span> <span class="p">(</span><span class="nx">fail</span> <span class="o">==</span> <span class="kc">undefined</span><span class="p">)</span> <span class="p">{</span> <span class="nx">uni</span><span class="p">.</span><span class="nx">msgBox</span><span class="p">(</span><span class="nx">rlt</span><span class="p">.</span><span class="nx">msg</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="s2">&#34;warning&#34;</span><span class="p">);</span> <span class="nx">uni</span><span class="p">.</span><span class="nx">log</span><span class="p">.</span><span class="nx">set</span><span class="p">(</span><span class="s2">&#34;msg&#34;</span><span class="p">,</span> <span class="nx">rlt</span><span class="p">.</span><span class="nx">msg</span> <span class="o">+</span> <span class="s2">&#34;/&#34;</span> <span class="o">+</span> <span class="nx">rlt</span><span class="p">.</span><span class="nx">act</span><span class="p">);</span> <span class="p">}</span>
</span></span><span class="line"><span class="cl">                    <span class="k">else</span> <span class="nx">fail</span><span class="p">(</span><span class="nx">rlt</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">                <span class="p">}</span>
</span></span><span class="line"><span class="cl">                <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="nx">rlt</span><span class="p">.</span><span class="nx">ret</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                    <span class="k">if</span> <span class="p">(</span><span class="nx">suc</span> <span class="o">==</span> <span class="kc">undefined</span><span class="p">)</span> <span class="p">{</span> <span class="nx">uni</span><span class="p">.</span><span class="nx">msgBox</span><span class="p">(</span><span class="nx">rlt</span><span class="p">.</span><span class="nx">msg</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="s2">&#34;success&#34;</span><span class="p">);</span> <span class="nx">uni</span><span class="p">.</span><span class="nx">log</span><span class="p">.</span><span class="nx">set</span><span class="p">(</span><span class="s2">&#34;msg&#34;</span><span class="p">,</span> <span class="nx">rlt</span><span class="p">.</span><span class="nx">msg</span> <span class="o">+</span> <span class="s2">&#34;/&#34;</span> <span class="o">+</span> <span class="nx">rlt</span><span class="p">.</span><span class="nx">act</span><span class="p">);</span> <span class="p">}</span>
</span></span><span class="line"><span class="cl">                    <span class="k">else</span> <span class="nx">suc</span><span class="p">(</span><span class="nx">rlt</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">                <span class="p">}</span>
</span></span><span class="line"><span class="cl">                <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="nx">rlt</span><span class="p">.</span><span class="nx">ret</span> <span class="o">==</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="p">{</span><span class="c1">//登录超时
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>                    <span class="nx">uni</span><span class="p">.</span><span class="nx">msgBox</span><span class="p">(</span><span class="nx">rlt</span><span class="p">.</span><span class="nx">msg</span><span class="p">,</span> <span class="s2">&#34;&#34;</span><span class="p">,</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span> <span class="nx">location</span><span class="p">.</span><span class="nx">reload</span><span class="p">();</span> <span class="p">},</span> <span class="s2">&#34;warning&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">                    <span class="nx">uni</span><span class="p">.</span><span class="nx">log</span><span class="p">.</span><span class="nx">set</span><span class="p">(</span><span class="s2">&#34;msg&#34;</span><span class="p">,</span> <span class="nx">rlt</span><span class="p">.</span><span class="nx">msg</span> <span class="o">+</span> <span class="s2">&#34;/&#34;</span> <span class="o">+</span> <span class="nx">rlt</span><span class="p">.</span><span class="nx">act</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">                <span class="p">}</span>
</span></span><span class="line"><span class="cl">                <span class="k">return</span> <span class="kc">true</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">            <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span></code></pre></div><p>估摸着这个函数主要是用于处理服务器返回信息用的，先搁在一边……</p>
<p>回到网页源码，找到了<code>uni</code>的出处<code>uni.lib</code></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="c1">//-------------------------------------------------------------------jquery第三方 插件-----------------------------------
</span></span></span><span class="line"><span class="cl"><span class="c1">//异步上传
</span></span></span></code></pre></div><p>第三方插件可还行……</p>
<p>果然找到<code>fGet()</code></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="c1">//get方式 form提交(data.act 操作命令 data.$f 表单Jquery对象)
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="nx">fGet</span><span class="o">:</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">url</span><span class="p">,</span> <span class="nx">data</span><span class="p">,</span> <span class="nx">suc</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="kd">var</span> <span class="nx">e</span> <span class="o">=</span> <span class="nx">err</span> <span class="o">||</span> <span class="k">this</span><span class="p">.</span><span class="nx">_ajaxErr</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="k">this</span><span class="p">.</span><span class="nx">_get</span><span class="p">(</span><span class="nx">url</span><span class="p">,</span> <span class="nx">data</span><span class="p">,</span> <span class="nx">suc</span><span class="p">,</span> <span class="nx">e</span><span class="p">,</span> <span class="mi">2</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span></code></pre></div><p>进一步找到<code>_get()</code></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="c1">//基础ajax方法 get方式 flag=1 js对象转url参数 flag=2 form提交 flag=3 uri编码
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="nx">_get</span><span class="o">:</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">url</span><span class="p">,</span> <span class="nx">data</span><span class="p">,</span> <span class="nx">suc</span><span class="p">,</span> <span class="nx">err</span><span class="p">,</span> <span class="nx">flag</span><span class="p">,</span> <span class="nx">type</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="kd">var</span> <span class="nx">d</span> <span class="o">=</span> <span class="nx">data</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="p">(</span><span class="nx">flag</span> <span class="o">===</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="nx">d</span> <span class="o">=</span> <span class="nx">uni</span><span class="p">.</span><span class="nx">obj2Url</span><span class="p">(</span><span class="nx">data</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="nx">flag</span> <span class="o">===</span> <span class="mi">2</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="nx">d</span> <span class="o">=</span> <span class="nx">$</span><span class="p">(</span><span class="nx">data</span><span class="p">.</span><span class="nx">$f</span><span class="p">).</span><span class="nx">serialize</span><span class="p">()</span> <span class="o">+</span> <span class="s2">&#34;&amp;act=&#34;</span> <span class="o">+</span> <span class="nx">data</span><span class="p">.</span><span class="nx">act</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="nx">flag</span> <span class="o">===</span> <span class="mi">3</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="nx">d</span> <span class="o">=</span> <span class="nb">encodeURI</span><span class="p">(</span><span class="nx">data</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="p">(</span><span class="nx">d</span> <span class="o">!=</span> <span class="kc">null</span> <span class="o">&amp;&amp;</span> <span class="nx">d</span> <span class="o">!=</span> <span class="s2">&#34;&#34;</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="k">if</span> <span class="p">(</span><span class="nx">d</span><span class="p">.</span><span class="nx">length</span> <span class="o">&gt;</span> <span class="mi">2000</span><span class="p">)</span> <span class="p">{</span><span class="c1">//当参数超出url长度限制，转post方式
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>                <span class="k">this</span><span class="p">.</span><span class="nx">post</span><span class="p">(</span><span class="nx">url</span><span class="p">,</span> <span class="nx">uni</span><span class="p">.</span><span class="nx">url2Obj</span><span class="p">(</span><span class="nx">d</span><span class="p">),</span> <span class="nx">suc</span><span class="p">,</span> <span class="nx">err</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">                <span class="k">return</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">            <span class="p">}</span>
</span></span><span class="line"><span class="cl">            <span class="k">else</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                <span class="nx">url</span> <span class="o">=</span> <span class="nx">url</span> <span class="o">+</span> <span class="s2">&#34;?&#34;</span> <span class="o">+</span> <span class="nx">d</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">            <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="kd">var</span> <span class="nx">len</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">history</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="p">(</span><span class="nx">len</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="kd">var</span> <span class="nx">last</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">history</span><span class="p">[</span><span class="nx">len</span> <span class="o">-</span> <span class="mi">1</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">            <span class="k">if</span> <span class="p">(</span><span class="nx">last</span><span class="p">.</span><span class="nx">act</span> <span class="o">==</span> <span class="nx">url</span> <span class="o">&amp;&amp;</span> <span class="nx">last</span><span class="p">.</span><span class="nx">ajax_state</span> <span class="o">==</span> <span class="s2">&#34;sending&#34;</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                <span class="k">return</span><span class="p">;</span><span class="c1">//重复提交 丢弃
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>            <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="kd">var</span> <span class="nx">sta</span> <span class="o">=</span> <span class="p">{</span> <span class="nx">ajax_state</span><span class="o">:</span> <span class="s2">&#34;sending&#34;</span><span class="p">,</span> <span class="nx">act</span><span class="o">:</span> <span class="nx">url</span> <span class="p">};</span>
</span></span><span class="line"><span class="cl">        <span class="k">this</span><span class="p">.</span><span class="nx">history</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">sta</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="nx">$</span><span class="p">.</span><span class="nx">ajax</span><span class="p">({</span>
</span></span><span class="line"><span class="cl">            <span class="nx">type</span><span class="o">:</span> <span class="s2">&#34;GET&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="nx">cache</span><span class="o">:</span> <span class="kc">false</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="nx">timeout</span><span class="o">:</span> <span class="mi">150000</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="nx">buf</span><span class="o">:</span> <span class="nx">data</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="nx">url</span><span class="o">:</span> <span class="nx">url</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="nx">dataType</span><span class="o">:</span> <span class="nx">type</span> <span class="o">||</span> <span class="s2">&#34;json&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="nx">success</span><span class="o">:</span> <span class="nx">suc</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="nx">error</span><span class="o">:</span> <span class="nx">err</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="nx">beforeSend</span><span class="o">:</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                <span class="nx">uni</span><span class="p">.</span><span class="nx">j</span><span class="p">.</span><span class="nx">swit</span><span class="o">++</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">                <span class="nx">uni</span><span class="p">.</span><span class="nx">showWait</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">            <span class="p">},</span>
</span></span><span class="line"><span class="cl">            <span class="nx">complete</span><span class="o">:</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                <span class="nx">uni</span><span class="p">.</span><span class="nx">j</span><span class="p">.</span><span class="nx">swit</span><span class="o">--</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">                <span class="k">if</span> <span class="p">(</span><span class="nx">uni</span><span class="p">.</span><span class="nx">j</span><span class="p">.</span><span class="nx">swit</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="nx">uni</span><span class="p">.</span><span class="nx">hideWait</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">                <span class="nx">sta</span><span class="p">.</span><span class="nx">ajax_state</span> <span class="o">=</span> <span class="s2">&#34;complete&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">            <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="p">});</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span></code></pre></div><p>看了一遍，貌似url并没有发生改变，说明<code>_</code>不是这一步加上去的……</p>
<p><del>哭了</del>老哥加油</p>
<p>回归本质，把网页html源码下载下来本地分析……</p>
<p>还是没有找到<code>_</code>……</p>
<p>回到chrome进行调试</p>
<p><img loading="lazy" src="/old-pics/illustrations/2019-04-04_Crawl_Notes/2.png" alt=""  />
</p>
<p>意外发现第三方插件确实没有生成<code>_</code>，上面的<code>f</code>中的网址最后没有该参数！</p>
<p><img loading="lazy" src="/old-pics/illustrations/2019-04-04_Crawl_Notes/3.png" alt=""  />
</p>
<p>emmm，看来只能是jQuery搞的鬼，可是这代码被混淆了……</p>
<hr>
<p>突然发现</p>
<p><img loading="lazy" src="/old-pics/illustrations/2019-04-04_Crawl_Notes/4.png" alt=""  />
</p>
<p>typora也有这个标记……</p>
<p>原来是<strong>时间戳</strong>……</p>
<p>破案了！</p>
<hr>
<p>果然还是缺乏经验，不过这一通操作算是积累了不少阅读js源码的经验……</p>
]]></content:encoded>
    </item>
    <item>
      <title>在WSL上安装GNOME桌面方法的正解</title>
      <link>https://blog.chong-zeng.com/posts/2019-04-03_gnome/</link>
      <pubDate>Wed, 03 Apr 2019 00:00:00 +0000</pubDate>
      <guid>https://blog.chong-zeng.com/posts/2019-04-03_gnome/</guid>
      <description>网上的教程千篇一律安装的是Unity桌面，而Unity真心难用！自己折腾了一下成功了，简单记录一下方法，帮大家踩踩坑
Step1. 通过tasksel安装Ubuntu Desktop 通过任务的方式安装Ubuntu Desktop
tasksel有一个基于curses的GUI
用空格选择Ubuntu Desktop，回车安装即可
这样装下来的Ubuntu Desktop是Gnome版的，CSDN上流传的那些指令装下来的全是Unity环境
tasksel安装的好处是无需过多关心包依赖等问题，缺陷在于会安装很多我们不想要的包，比如libreoffice，但是这些多余的包可以日后卸载
Step2. 安装并启动Xming 启动完整桌面环境时用这个（其余的参数都不用改！包括Display number！）
如果你只是想用用单个程序的GUI界面，选Multiple windows就好了
Step3. 启动GNOME桌面 注意四点：
Gnome目前还不稳定，因此启动前最好确保dbus服务正在运行，最简单的方式就是start或者restart一下 需要指定桌面端口以及会话类型（X11） 要加sudo，因为Gnome启动时，dconf也会启动，而后者要在用户根目录下的.cache内创建一个文件夹dconf，估计是想存放一些配置参数之类的，不用sudo的话会在这一步进入死循环，如图 因为已经是超级用户了，所以进入gnome环境后你的身份就是root，不用多说了吧，干啥都悠着点好了…… 上命令：
sudo service dbus start sudo DISPLAY=:0 XDG_SESSION_TYPE=x11 gnome-session 好了，现在该怎么折腾就怎么折腾吧……（比如把libreoffice等用Ubuntu Software卸载掉）
Step4. 简化日后操作 为了日后简单起见，其实可以通过向.bashrc中写入export DISPLAY=:0.0的方式，让每次启动bash时都运行这句话。毕竟开gnome完整桌面环境的频率还是没有开单个GUI程序的频率高，因此加上这一步可以简化日后在Xming中启动单个GUI程序的指令
echo &amp;#34;export DISPLAY=:0.0&amp;#34; &amp;gt;&amp;gt; ~/.bashrc 此后我们再想启动gnome桌面时，直接输入以下命令就好
sudo service dbus restart sudo XDG_SESSION_TYPE=x11 gnome-session 而单个程序就更简单了，比如
gedit 展现一下“混合系统”的效果……
踩坑完毕</description>
      <content:encoded><![CDATA[<p>网上的教程千篇一律安装的是Unity桌面，而Unity真心难用！自己折腾了一下成功了，简单记录一下方法，帮大家踩踩坑</p>
<h1 id="step1-通过tasksel安装ubuntu-desktop">Step1. 通过tasksel安装Ubuntu Desktop</h1>
<p>通过任务的方式安装Ubuntu Desktop</p>
<p>tasksel有一个基于curses的GUI</p>
<p>用空格选择Ubuntu Desktop，回车安装即可</p>
<blockquote>
<p>这样装下来的Ubuntu Desktop是Gnome版的，CSDN上流传的那些指令装下来的全是Unity环境</p>
</blockquote>
<p><img loading="lazy" src="/old-pics/illustrations/2019-04-03_Gnome/1.png" alt=""  />
</p>
<p><img loading="lazy" src="/old-pics/illustrations/2019-04-03_Gnome/2.png" alt=""  />
</p>
<blockquote>
<p>tasksel安装的好处是无需过多关心包依赖等问题，缺陷在于会安装很多我们不想要的包，比如libreoffice，但是这些多余的包可以日后卸载</p>
</blockquote>
<h1 id="step2-安装并启动xming">Step2. 安装并启动Xming</h1>
<p><img loading="lazy" src="/old-pics/illustrations/2019-04-03_Gnome/3.png" alt=""  />
</p>
<p>启动完整桌面环境时用这个（其余的参数都不用改！包括Display number！）</p>
<p>如果你只是想用用单个程序的GUI界面，选Multiple windows就好了</p>
<h1 id="step3-启动gnome桌面">Step3. 启动GNOME桌面</h1>
<p>注意四点：</p>
<ol>
<li>Gnome目前还不稳定，因此启动前最好确保dbus服务正在运行，最简单的方式就是start或者restart一下</li>
<li>需要指定桌面端口以及会话类型（X11）</li>
<li>要加<code>sudo</code>，因为Gnome启动时，<code>dconf</code>也会启动，而后者要在用户根目录下的<code>.cache</code>内创建一个文件夹<code>dconf</code>，估计是想存放一些配置参数之类的，不用<code>sudo</code>的话会在这一步进入死循环，如图<img loading="lazy" src="/old-pics/illustrations/2019-04-03_Gnome/4.png" alt=""  />
</li>
<li>因为已经是超级用户了，所以进入gnome环境后你的身份就是<code>root</code>，不用多说了吧，干啥都悠着点好了……</li>
</ol>
<p>上命令：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo service dbus start
</span></span><span class="line"><span class="cl">sudo <span class="nv">DISPLAY</span><span class="o">=</span>:0 <span class="nv">XDG_SESSION_TYPE</span><span class="o">=</span>x11 gnome-session
</span></span></code></pre></div><p><img loading="lazy" src="/old-pics/illustrations/2019-04-03_Gnome/5.png" alt=""  />
</p>
<p>好了，现在该怎么折腾就怎么折腾吧……（比如把libreoffice等用Ubuntu Software卸载掉）</p>
<p><img loading="lazy" src="/old-pics/illustrations/2019-04-03_Gnome/6.png" alt=""  />
</p>
<h1 id="step4-简化日后操作">Step4. 简化日后操作</h1>
<p>为了日后简单起见，其实可以通过向<code>.bashrc</code>中写入<code>export DISPLAY=:0.0</code>的方式，让每次启动bash时都运行这句话。毕竟开gnome完整桌面环境的频率还是没有开单个GUI程序的频率高，因此加上这一步可以简化日后在Xming中启动单个GUI程序的指令</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;export DISPLAY=:0.0&#34;</span> &gt;&gt; ~/.bashrc
</span></span></code></pre></div><p>此后我们再想启动gnome桌面时，直接输入以下命令就好</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo service dbus restart
</span></span><span class="line"><span class="cl">sudo <span class="nv">XDG_SESSION_TYPE</span><span class="o">=</span>x11 gnome-session
</span></span></code></pre></div><p>而单个程序就更简单了，比如</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">gedit
</span></span></code></pre></div><p>展现一下“混合系统”的效果……</p>
<p><img loading="lazy" src="/old-pics/illustrations/2019-04-03_Gnome/7.png" alt=""  />
</p>
<hr>
<p>踩坑完毕</p>
]]></content:encoded>
    </item>
    <item>
      <title>C语言的宏运算符</title>
      <link>https://blog.chong-zeng.com/posts/2019-02-19_macro/</link>
      <pubDate>Tue, 19 Feb 2019 00:00:00 +0000</pubDate>
      <guid>https://blog.chong-zeng.com/posts/2019-02-19_macro/</guid>
      <description>这题还是MSC决赛的一题，原题题干已经交代得很清楚了（我懒……），直接搬过来好了
宏&amp;amp;宏函数简介 宏是 C 语言中极为强大，也极具魅力的一个功能。宏为极其贴近机器语言的 C 提供了一定程度上的元编程能力。程序员们能够利用宏来减少代码中的重复，或是解决一些条件编译之类的问题。
宏、或者说 C 预处理器，实际上干的事情就是进行字符串拼接和处理，其中比较简单的就是普通的字符串替换：
#define abc efg #define one 1 #define INT int #define DENGYU INT abc DENGYU one; // -&amp;gt; int efg = 1; 为了防止替换的过程无法结束，通过这种方式定义的宏在它的(和它的递归)展开内容中是不会再对其本身进行替换
#define abc abc efg #define efg abc hij #define hij efg abc abc // (所有东西都可以被展开) -&amp;gt; abc efg // (abc 不会再被展开) -&amp;gt; abc abc hij // (abc efg 不会再被展开) -&amp;gt; abc abc efg abc 另一种则是宏函数，规则稍微复杂一些。宏函数首先会对它的参数进行宏展开，如果参数中存在 # 或者 ## (具体作用后面会提及)， 那么不再对这个参数进行递归展开，然后再按照宏的定义将参数进行拼接，得到这一次展开的结果；之后对结果进行下一次展开。这次展开和之前说的展开规则类似，不再会对生成的结果中相同的宏函数进行展开。</description>
      <content:encoded><![CDATA[<blockquote>
<p>这题还是MSC决赛的一题，原题题干已经交代得很清楚了（<del>我懒……</del>），直接搬过来好了</p>
</blockquote>
<h1 id="宏宏函数简介">宏&amp;宏函数简介</h1>
<p>宏是 C 语言中极为强大，也极具魅力的一个功能。宏为极其贴近机器语言的 C 提供了一定程度上的元编程能力。程序员们能够利用宏来减少代码中的重复，或是解决一些条件编译之类的问题。</p>
<p>宏、或者说 C 预处理器，实际上干的事情就是进行字符串拼接和处理，其中比较简单的就是普通的字符串替换：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#define abc efg
</span></span></span><span class="line"><span class="cl"><span class="cp">#define one 1
</span></span></span><span class="line"><span class="cl"><span class="cp">#define INT int
</span></span></span><span class="line"><span class="cl"><span class="cp">#define DENGYU
</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="n">INT</span> <span class="n">abc</span> <span class="n">DENGYU</span> <span class="n">one</span><span class="p">;</span> <span class="c1">// -&gt; int efg = 1;
</span></span></span></code></pre></div><p>为了防止替换的过程无法结束，通过这种方式定义的宏在它的(和它的递归)展开内容中是不会再对其本身进行替换</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#define abc abc efg
</span></span></span><span class="line"><span class="cl"><span class="cp">#define efg abc hij
</span></span></span><span class="line"><span class="cl"><span class="cp">#define hij efg abc
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>	<span class="n">abc</span> <span class="c1">// (所有东西都可以被展开)
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="o">-&gt;</span>  <span class="n">abc</span> <span class="n">efg</span> <span class="c1">// (abc 不会再被展开)
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="o">-&gt;</span>  <span class="n">abc</span> <span class="n">abc</span> <span class="n">hij</span> <span class="c1">// (abc efg 不会再被展开)
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="o">-&gt;</span>  <span class="n">abc</span> <span class="n">abc</span> <span class="n">efg</span> <span class="n">abc</span>
</span></span></code></pre></div><p>另一种则是<strong>宏函数</strong>，规则稍微复杂一些。宏函数首先会对它的参数进行宏展开，如果参数中存在 <code>#</code> 或者 <code>##</code> (具体作用后面会提及)， 那么不再对这个参数进行递归展开，然后再按照宏的定义将参数进行拼接，得到这一次展开的结果；之后对结果进行下一次展开。这次展开和之前说的展开规则类似，不再会对生成的结果中相同的宏函数进行展开。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#define foo(a, b) a b
</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="nf">foo</span><span class="p">(</span><span class="mi">1</span><span class="o">+</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span> <span class="c1">// -&gt; 1 + 2
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="cp">#define foo2(a, b) foo(a) foo(b)
</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="nf">foo2</span><span class="p">(</span><span class="mi">1</span><span class="o">+</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span> <span class="c1">// -&gt; foo(1+) foo(2) -&gt; 1+ 1+ 2 2
</span></span></span></code></pre></div><p>C 预处理器提供了一些方法来生成特殊的字符串，例如 <code>#</code> 和 <code>##</code>.</p>
<p><code>##</code> 能将它两边的内容直接连接起来，去除中间的空格，可以用来拼接新的宏或者标识符等</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#define CONCAT(X, Y) X ## Y
</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="n">a</span> <span class="o">=</span> <span class="nf">CONCAT</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span> <span class="c1">// -&gt; int a = x1;
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="cp">#define ADD_PREFIX_AND_SUFFIX(X) pre ## X ## suf
</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="n">b</span> <span class="o">=</span> <span class="nf">ADD_PREFIX_AND_SUFFIX</span><span class="p">(</span><span class="n">X</span><span class="p">);</span> <span class="c1">// int a = preXsuf;
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="cl"><span class="cp">#define IF(COND, PASS, FAIL) IF_ ## COND (PASS, FAIL)
</span></span></span><span class="line"><span class="cl"><span class="cp">#define IF_0(PASS, FAIL) FAIL
</span></span></span><span class="line"><span class="cl"><span class="cp">#define IF_1(PASS, FAIL) PASS
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl"><span class="nf">IF</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">A</span><span class="p">,</span> <span class="n">B</span><span class="p">)</span> <span class="c1">// -&gt; B
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="nf">IF</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">A</span><span class="p">,</span> <span class="n">B</span><span class="p">)</span> <span class="c1">// -&gt; A
</span></span></span></code></pre></div><p><code>#</code> 能作用于它右边的宏参数，把它转化为一个 C 语言字符串字面量。而 C 语言也提供了“自动拼接相邻两个字符串字面量”的语法糖，使得我们可以在 编译期完成拼接字符串字面量的操作</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#define TO_C_STR(X) #X
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl"><span class="cp">#define ADD_C_STR_SUFFIX(X, Y) X TO_C_STR(Y)
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl"><span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">c_str</span> <span class="o">=</span> <span class="nf">ADD_C_STR_SUFFIX</span><span class="p">(</span><span class="s">&#34;abc&#34;</span><span class="p">,</span> <span class="n">efg</span><span class="p">);</span> <span class="c1">// -&gt; const char* c_str = &#34;abc&#34; &#34;efg&#34;; === const char* c_str = &#34;abcefg&#34;;
</span></span></span></code></pre></div><p>宏也提供了可变参数的宏函数。简单的说，配合 <code>__VA_ARGS__</code> 它可以将传入的参数按原样替换到内容里。 相比与 C 语言的可变参数函数，宏函数不需要&quot;至少有一个固定参数&quot;。 在宏函数的替换内容中，可以使用 <code>__VA_ARGS__</code> 来代表它获得的可变参数. 可以使用 <code>, ##__VA_ARGS__</code>来实现对 0 个可变参数的适配。可变参数 <code>...</code> 只能在参数列表中出现一次。 下面是一些例子：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#define PRINT(...) printf(__VA_ARGS__)
</span></span></span><span class="line"><span class="cl"><span class="cp">#define PRINTF(FMT, ...) printf(FMT, ##__VA_ARGS__)
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl"><span class="nf">PRINT</span><span class="p">(</span><span class="s">&#34;123&#34;</span><span class="p">);</span> <span class="c1">// -&gt; printf(&#34;123&#34;);
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="nf">PRINT</span><span class="p">(</span><span class="s">&#34;%d&#34;</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span> <span class="c1">// -&gt; printf(&#34;%d&#34;, 1);
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="nf">PRINTF</span><span class="p">(</span><span class="s">&#34;123&#34;</span><span class="p">);</span> <span class="c1">// -&gt; printf(&#34;123&#34;);
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="nf">PRINTF</span><span class="p">(</span><span class="s">&#34;%d&#34;</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span> <span class="c1">// -&gt; printf(&#34;%d&#34;, 1);
</span></span></span></code></pre></div><h1 id="宏函数有什么用">宏函数有什么用？</h1>
<blockquote>
<p>偶读翁恺老师博客上的文章，看到<a href="http://wengkai.github.io/cmacro/cmacro.html">这样一篇</a></p>
</blockquote>
<p>在讲到编译预处理指令的宏运算符<code>##</code>时，同学们都不太理解这东西有什么用。今天恰好在Arduino的Ethernet库的头文件里看到了活的例子。在Arduino的Ethernet库的<code>w5100.cpp</code>里有这样的函数调用：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c++" data-lang="c++"><span class="line"><span class="cl"><span class="n">writeTMSR</span><span class="p">(</span><span class="mh">0x55</span><span class="p">);</span>
</span></span></code></pre></div><p>但是遍寻整个<code>.cpp</code>和对应的<code>w5100.h</code>也找不到这个<code>writeTMSR()</code>函数，即使把所有的源代码目录拿来搜索一遍都没有。但是，编译显然是通过了的，那么，这个函数在哪里呢？</p>
<p>在<code>w5100.h</code>，我们发现了这样的代码：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c++" data-lang="c++"><span class="line"><span class="cl"><span class="cp">#define __GP_REGISTER8(name, address)             \
</span></span></span><span class="line"><span class="cl"><span class="cp">  static inline void write##name(uint8_t _data) { \
</span></span></span><span class="line"><span class="cl"><span class="cp">    write(address, _data);                        \
</span></span></span><span class="line"><span class="cl"><span class="cp">  }                                               \
</span></span></span><span class="line"><span class="cl"><span class="cp">  static inline uint8_t read##name() {            \
</span></span></span><span class="line"><span class="cl"><span class="cp">    return read(address);                         \
</span></span></span><span class="line"><span class="cl"><span class="cp">  }
</span></span></span></code></pre></div><p>这个宏定义是说，如果你提供一个name和一个address，那么宏<code>__GP_REGISTER8</code>就会被展开为两个函数，一个的名字是write后面跟上name，另一个是read后面跟上name。</p>
<p>于是，在<code>w5100.h</code>里接下去的代码：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c++" data-lang="c++"><span class="line"><span class="cl"><span class="n">__GP_REGISTER8</span> <span class="p">(</span><span class="n">TMSR</span><span class="p">,</span>   <span class="mh">0x001B</span><span class="p">);</span>    <span class="c1">// Transmit memory size
</span></span></span></code></pre></div><p>在编译预处理后，就会被展开成为：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c++" data-lang="c++"><span class="line"><span class="cl">  <span class="k">static</span> <span class="kr">inline</span> <span class="kt">void</span> <span class="nf">writeTMSR</span><span class="p">(</span><span class="kt">uint8_t</span> <span class="n">_data</span><span class="p">)</span> <span class="p">{</span> 
</span></span><span class="line"><span class="cl">    <span class="n">write</span><span class="p">(</span><span class="mh">0x001B</span><span class="p">,</span> <span class="n">_data</span><span class="p">);</span>                        
</span></span><span class="line"><span class="cl">  <span class="p">}</span>                                               
</span></span><span class="line"><span class="cl">  <span class="k">static</span> <span class="kr">inline</span> <span class="kt">uint8_t</span> <span class="nf">readTMSR</span><span class="p">()</span> <span class="p">{</span>            
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">read</span><span class="p">(</span><span class="mh">0x001B</span><span class="p">);</span>                         
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span></code></pre></div><p>看，这就是活生生的宏运算符的例子。</p>
<h1 id="宏函数的技巧性使用">宏函数的技巧性使用</h1>
<h2 id="题目-max">题目-<code>MAX()</code></h2>
<blockquote>
<h2 id="题目描述">题目描述</h2>
<p>实现一个可以接受可变参数的宏函数 <code>MAX</code>, 它返回其中的最大值。</p>
<p>保证传入的参数为合法的 C 表达式，且类型为 <code>int</code>，个数在 1 ~ 5 之间，中间用逗号分隔</p>
<p>保证传入的表达式无副作用</p>
<h2 id="函数接口定义">函数接口定义</h2>
<p>虽然并不是函数</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#define MAX(...)
</span></span></span></code></pre></div><h2 id="裁判测试程序样例">裁判测试程序样例</h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl"><span class="c1">// your code here
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="n">data</span><span class="p">[</span><span class="mi">10</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="kt">int</span> <span class="n">n</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="nf">scanf</span><span class="p">(</span><span class="s">&#34;%d&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">n</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">  <span class="kt">int</span> <span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">z</span><span class="p">,</span> <span class="n">w</span><span class="p">,</span> <span class="n">u</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="k">switch</span><span class="p">(</span><span class="n">n</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">case</span> <span class="mi">1</span><span class="o">:</span> <span class="nf">scanf</span><span class="p">(</span><span class="s">&#34;%d&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">x</span><span class="p">);</span> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="nf">MAX</span><span class="p">(</span><span class="n">x</span><span class="p">));</span> <span class="k">break</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">case</span> <span class="mi">2</span><span class="o">:</span> <span class="nf">scanf</span><span class="p">(</span><span class="s">&#34;%d %d&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">x</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">y</span><span class="p">);</span> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="nf">MAX</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">));</span> <span class="k">break</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">case</span> <span class="mi">3</span><span class="o">:</span> <span class="nf">scanf</span><span class="p">(</span><span class="s">&#34;%d %d %d&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">x</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">y</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">z</span><span class="p">);</span> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="nf">MAX</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">z</span><span class="p">));</span> <span class="k">break</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">case</span> <span class="mi">4</span><span class="o">:</span> <span class="nf">scanf</span><span class="p">(</span><span class="s">&#34;%d %d %d %d&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">x</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">y</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">z</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">w</span><span class="p">);</span> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="nf">MAX</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">z</span><span class="p">,</span> <span class="n">w</span><span class="p">));</span> <span class="k">break</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">case</span> <span class="mi">5</span><span class="o">:</span> <span class="nf">scanf</span><span class="p">(</span><span class="s">&#34;%d %d %d %d %d&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">x</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">y</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">z</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">w</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">u</span><span class="p">);</span> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="nf">MAX</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">z</span><span class="p">,</span> <span class="n">w</span><span class="p">,</span> <span class="n">u</span><span class="p">));</span> <span class="k">break</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">default</span><span class="o">:</span> <span class="k">break</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl">  <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>样例仅供参考</p>
<h2 id="样例1">样例1</h2>
<h3 id="输入">输入</h3>
<pre tabindex="0"><code class="language-in" data-lang="in">4 1 3 2 1
</code></pre><h3 id="输出">输出</h3>
<pre tabindex="0"><code class="language-out" data-lang="out">3
</code></pre><h2 id="样例2">样例2</h2>
<h3 id="输入-1">输入</h3>
<pre tabindex="0"><code class="language-in" data-lang="in">1 0
</code></pre><h3 id="输出-1">输出</h3>
<pre tabindex="0"><code class="language-out" data-lang="out">0
</code></pre><h2 id="提示">提示</h2>
<ul>
<li>具体的规则最好自己实验一下， 使用 <code>gcc -E test.c</code> 可以打印出 <code>test.c</code> 经过预处理后的代码</li>
<li>宏函数的参数使用时在不影响语义的情况下尽量在两边加上 <code>()</code> ，一个常见的错误例子就是：</li>
</ul>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#define MUL(A, B) A * B
</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="nf">MUL</span><span class="p">(</span><span class="mi">1</span> <span class="o">+</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span> <span class="o">+</span> <span class="mi">4</span><span class="p">)</span> <span class="c1">// -&gt; 1 + 2 * 3 + 4 
</span></span></span></code></pre></div><ul>
<li>在预处理器进行处理的过程中, 可以产生一些临时参数，但它们很快就在下一次替换过程消失，而不会导致生成非法的表达式。</li>
<li>你可能需要一个形式类似于 <code>#define FOO(_USELESS_PARAMETER, ...) BLAHBLAH</code> 的宏</li>
</ul>
</blockquote>
<h2 id="思路题解">思路&amp;题解</h2>
<p>我曾经想过将宏函数里的参数全部传到另一个变参函数中（上一篇文章讲的就是变参函数），但是<code>MAX()</code>的实现需要知道参数的个数，而这一点又是变参函数无法实现的（原因见上一篇文章），因此此思路失败。</p>
<p>但是请注意，<strong><code>MAX()</code>的实现需要知道参数的个数</strong>，这句话其实提醒了我们，<strong>此题的突破口其实就是如何让程序知道参数的个数</strong>。</p>
<p>看到这里你要是还没有思路的话，其实太正常了——因为这题技巧性很强，解法也很漂亮。</p>
<p>直接放代码好了，看了代码一定会有豁然开朗的感觉。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#define MAX1(A) (A)
</span></span></span><span class="line"><span class="cl"><span class="cp">#define MAX2(A,B) (A)&gt;(B)?(A):(B)
</span></span></span><span class="line"><span class="cl"><span class="cp">#define MAX3(A,B,C) MAX2(MAX2(A,B),(C))
</span></span></span><span class="line"><span class="cl"><span class="cp">#define MAX4(A,B,C,D) MAX2(MAX3(A,B,C),(D))
</span></span></span><span class="line"><span class="cl"><span class="cp">#define MAX5(A,B,C,D,E) MAX2(MAX4(A,B,C,D),(E))
</span></span></span><span class="line"><span class="cl"><span class="cp">#define GETMAX(A,B,C,D,E,MAXNAME,...) MAXNAME
</span></span></span><span class="line"><span class="cl"><span class="cp">#define MAX(...) GETMAX(__VA_ARGS__,MAX5,MAX4,MAX3,MAX2,MAX1)(__VA_ARGS__)
</span></span></span></code></pre></div><p>这里其实就是利用参数个数的不同，<strong>使固定位置上获取的参数不同</strong>，从而实现基于参数个数的宏函数重载</p>
<p><del>这解法太骚了</del>不过其局限性在于依然只能处理一定数量以内的参数，这也是此题给出个数在1~5之间的限制的原因。</p>
<h1 id="启示">启示</h1>
<ol>
<li>
<p>存在即合理</p>
<p>C语言中有大量对于底层的奇怪操作，尽管看起来奇怪，但是其在特定场合依然有很大作用</p>
</li>
<li>
<p>多看源码可以学到很多</p>
<p><code>##</code>宏运算符的例子就是在Arduino的源码中发现的，由此可见阅读高质量源码的意义之大</p>
</li>
<li>
<p>阅读大牛的博客可以收获很多</p>
<p><code>##</code>宏运算符的例子就是在<a href="http://wengkai.github.io/">翁恺老师的博客</a>中发现的……</p>
</li>
</ol>
<p>MSC的语法题差不多说完了，本来计划把其他算法题也谈谈的，但是我最终放弃了，原因有二：</p>
<ol>
<li>寒假太忙了……</li>
<li>在接触了许多其他题目后，我意识到决赛时碰到的题目，只是万千算法题中微不足道的几题。算法是一个极其庞大的课题，需要慢慢修炼，因此计划转为系统地整理一套算法笔记。</li>
</ol>
<p>之后我遇到有意思的题目时，依然会分享在博客上的，敬请关注。</p>
]]></content:encoded>
    </item>
    <item>
      <title>Variadic Function in C</title>
      <link>https://blog.chong-zeng.com/posts/2019-01-20_variadic-function/</link>
      <pubDate>Sun, 20 Jan 2019 00:00:00 +0000</pubDate>
      <guid>https://blog.chong-zeng.com/posts/2019-01-20_variadic-function/</guid>
      <description>去年参加MSC的决赛的时候，遇到了关于变参函数的问题。其实这类函数很套路，但是考虑到之后想写的关于宏的一篇文章中有些东西跟变参函数有些类似，而且网上关于变参函数的教程都几乎是千篇一律、不中要害，因此先写一篇关于变参函数的文章，对其使用方法进行探讨。
〇、引言-常规的函数 在C语言中，函数在声明时往往就要指定参数的数量与类型，编译的时候，编译器也会替我们检查，看函数调用有无问题。
例如：
#include &amp;lt;stdio.h&amp;gt; int func(int i, int j) { } int main() { func(100); // 实参数目不对 return 0; } 此时编译器就会报错：
error: too few arguments to function &amp;#39;func&amp;#39; func(100); ^ 再如：
#include &amp;lt;stdio.h&amp;gt; int func(int i, int j) { } int main() { int* a; func(a, 100); return 0; } 此时编译器不会报错（at least for GCC），但是会给出一个Warning：
warning: passing argument 1 of &amp;#39;func&amp;#39; makes integer from pointer without a cast func(a, 100); ^ note: expected &amp;#39;int&amp;#39; but argument is of type &amp;#39;int *&amp;#39; int func(int i, int j) ^ 在这里我是故意用的一个指针，如果你用的是double或者char的话，连warning都不会出现，到时候一个强制类型转化塞给func()。</description>
      <content:encoded><![CDATA[<p>  去年参加MSC的决赛的时候，遇到了关于变参函数的问题。其实这类函数很套路，但是考虑到之后想写的关于宏的一篇文章中有些东西跟变参函数有些类似，而且网上关于变参函数的教程都几乎是千篇一律、不中要害，因此先写一篇关于变参函数的文章，对其使用方法进行探讨。</p>
<hr>
<h1 id="引言-常规的函数">〇、引言-常规的函数</h1>
<p>  在C语言中，函数在声明时往往就要指定参数的数量与类型，编译的时候，编译器也会替我们检查，看函数调用有无问题。</p>
<p>  例如：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">func</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span><span class="p">,</span> <span class="kt">int</span> <span class="n">j</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span> 
</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">	<span class="nf">func</span><span class="p">(</span><span class="mi">100</span><span class="p">);</span> <span class="c1">// 实参数目不对
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>	<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>  此时编译器就会报错：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cmd" data-lang="cmd"><span class="line"><span class="cl">error: too few arguments to function &#39;func&#39;
</span></span><span class="line"><span class="cl">func(100);
</span></span><span class="line"><span class="cl"><span class="se">^
</span></span></span></code></pre></div><p>  再如：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">func</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span><span class="p">,</span> <span class="kt">int</span> <span class="n">j</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">	<span class="kt">int</span><span class="o">*</span> <span class="n">a</span><span class="p">;</span> 
</span></span><span class="line"><span class="cl">	<span class="nf">func</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="mi">100</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">	<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>  此时编译器不会报错（at least for GCC），但是会给出一个Warning：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cmd" data-lang="cmd"><span class="line"><span class="cl">warning: passing argument 1 of &#39;func&#39; makes integer from pointer without a cast
</span></span><span class="line"><span class="cl">  func(a, 100);
</span></span><span class="line"><span class="cl">       <span class="se">^
</span></span></span><span class="line"><span class="cl"><span class="se">n</span>ote: expected &#39;int&#39; but argument is of type &#39;int *&#39;
</span></span><span class="line"><span class="cl"> int func(int i, int j)
</span></span><span class="line"><span class="cl">     <span class="se">^
</span></span></span></code></pre></div><p>  在这里我是故意用的一个指针，如果你用的是<code>double</code>或者<code>char</code>的话，连warning都不会出现，到时候一个强制类型转化塞给<code>func()</code>。</p>
<p>  于是，我们大部分时候接触到的函数就都是这种参数个数、类型都不可变的函数了。</p>
<p>  但其实有一个函数，我们从Hello World就开始用了，而且几乎目前的每个程序里都要用到，而它其实是一个变参函数。</p>
<h1 id="一printf-scanf-就是变参函数">一、<code>printf()</code> <code>scanf()</code> 就是变参函数！</h1>
<p>  没错，C 语言中最常用的可变参数函数例子其实就是<code>printf()</code>和 <code>scanf()</code>。仔细想想，每次你在调用这两个函数的时候，其后面的参数个数以及类型是不是的确在变化？</p>
<p>  为了进一步了解其实现的机制，我们来看看这两个函数的函数原型。（以TDM-GCC为例）</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="kr">__cdecl</span> <span class="nf">printf</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span> <span class="n">__restrict__</span> <span class="n">_Format</span><span class="p">,...);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="kr">__cdecl</span> <span class="nf">scanf</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span> <span class="n">__restrict__</span> <span class="n">_Format</span><span class="p">,...)</span> <span class="n">__MINGW_ATTRIB_DEPRECATED_SEC_WARN</span><span class="p">;</span>
</span></span></code></pre></div><p>  其中的<code>...</code>就是变参函数中可变参数部分的声明。</p>
<h1 id="二变参函数的特点">二、变参函数的特点</h1>
<p>  我们来就这两个经典的函数，简要分析一下变参函数的特点。</p>
<h2 id="1一定要有固定数量的强制参数mandatory-argument">1）一定要有固定数量的强制参数（mandatory argument）</h2>
<p>  <strong>变参函数必须至少有一个强制参数。</strong></p>
<p>  在这两个函数中，它体现为一个格式化字符串——<code>const char * __restrict__ _Format</code>。</p>
<h2 id="2省略号代表可选参数">2）省略号（&hellip;）代表可选参数</h2>
<p>  在格式化字符串之后，紧跟着的是一个逗号和三个点构成的省略号。这个省略号代表的就是可选参数。可选参数的类型可以变化。</p>
<h2 id="3参数列表的格式是强制性参数在前可选参数在后">3）参数列表的格式是强制性参数在前、可选参数在后</h2>
<p>  如果我强行在可选参数之后再添加一个强制参数，比如下面的一波操作：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">sumplus</span><span class="p">(</span><span class="kt">int</span> <span class="n">count</span><span class="p">,</span> <span class="p">...,</span> <span class="kt">int</span> <span class="n">m</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>  编译会报错：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cmd" data-lang="cmd"><span class="line"><span class="cl">error: expected &#39;)&#39; before &#39;,&#39; token
</span></span><span class="line"><span class="cl"> int sumplus(int count, ..., int m) 
</span></span><span class="line"><span class="cl">                           <span class="se">^
</span></span></span></code></pre></div><p>  一定会有人说，可选参数在最后不应该是天经地义的吗？但是到后面你就会发现我这番尝试并不是空穴来风。</p>
<h2 id="4编译器和函数并不知道可选参数有多少个">4）编译器和函数并不知道可选参数有多少个</h2>
<p>  肯定又会有人说，<code>printf()</code> <code>scanf()</code> 不是可以按照后面参数的要求输出、输入吗？确实可以，但是它们真的不知道自己后面有几个参数。</p>
<p>  实验为证：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">	<span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="mi">100</span><span class="p">,</span> <span class="mi">200</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">	<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>  编译通过：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cmd" data-lang="cmd"><span class="line"><span class="cl">Compilation results...
</span></span><span class="line"><span class="cl">--------
</span></span><span class="line"><span class="cl">- Errors: 0
</span></span><span class="line"><span class="cl">- Warnings: 0
</span></span></code></pre></div><p>  运行试试？</p>
<pre tabindex="0"><code class="language-out" data-lang="out">100
</code></pre><p>  杠精会说：嗯，那是<code>printf()</code>自动帮你把后面多的参数扔掉了。</p>
<p>  Really?</p>
<p>  依然以实验为证：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">	<span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d %d %d %d %d %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="mi">100</span><span class="p">,</span> <span class="mi">200</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">	<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>  依然编译通过：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cmd" data-lang="cmd"><span class="line"><span class="cl">Compilation results...
</span></span><span class="line"><span class="cl">--------
</span></span><span class="line"><span class="cl">- Errors: 0
</span></span><span class="line"><span class="cl">- Warnings: 0
</span></span></code></pre></div><p>  再运行试试？</p>
<pre tabindex="0"><code class="language-out" data-lang="out">100 200 17 42 4199400 0
</code></pre><p>  开始乱码了&hellip;&hellip;</p>
<p>  这就已经充分说明编译器和函数完全不知道你给它了多少给参数。它们完全不知道这些，只是按照一定的规则在试图读取这些可变的参数。那规则是什么呢？答案马上揭晓。</p>
<h1 id="三实现变参函数的方法">三、实现变参函数的方法</h1>
<h2 id="0搬运过来的题目背景介绍">0）搬运过来的题目背景介绍</h2>
<blockquote>
<p>  在 C 调用约定下我们可以使用 <code>va</code> 系列宏来轻松的实现一些变参函数，例如：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdarg.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">sum</span><span class="p">(</span><span class="kt">int</span> <span class="n">count</span><span class="p">,</span> <span class="p">...)</span> 
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">   	<span class="n">va_list</span> <span class="n">args</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">   	<span class="nf">va_start</span><span class="p">(</span><span class="n">args</span><span class="p">,</span> <span class="n">count</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">   	<span class="kt">int</span> <span class="n">res</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">   	<span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">count</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> 
</span></span><span class="line"><span class="cl">   	<span class="p">{</span>
</span></span><span class="line"><span class="cl">   		<span class="kt">int</span> <span class="n">val</span> <span class="o">=</span> <span class="nf">va_arg</span><span class="p">(</span><span class="n">args</span><span class="p">,</span> <span class="kt">int</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">   		<span class="n">res</span> <span class="o">+=</span> <span class="n">val</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">   	<span class="p">}</span>
</span></span><span class="line"><span class="cl">   	<span class="nf">va_end</span><span class="p">(</span><span class="n">args</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">   	<span class="k">return</span> <span class="n">res</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>  代码本身很简单，这里稍微解释。</p>
<p>  <code>va_list args;</code> 定义一个指向可变参数列表的指针</p>
<p>  <code>va_start(args, count);</code> 使参数列表指针指向函数参数 <code>count</code></p>
<p>  <code>va_arg(args, int)</code> 把参数列表指针当前所指位置以类型 <code>int</code> 读取出来并移动参数列表指针</p>
<p>  <code>va_end(args)</code> 清空参数列表。<code>va_start</code> 和 <code>va_end</code> 必须一一对应 。”每次调用<code>va_start()</code> / <code>va_copy()</code>后，必须得有相应的<code>va_end()</code>与之匹配。参数指针可以在参数列表中随意地来回移动，但必须在<code>va_start()</code> … <code>va_end()</code>之内</p>
<p>  当然大家可以发现这种形式的可变参数函数是非常危险的，<code>va_arg</code> 基本就是强制类型转换，而且读取的参数个数也只能通过用户输入来确认，很容易出现访问参数越界的情况。同时 <code>va_arg</code> <strong>取出的参数类型和实际传入的类型不一致，或是访问最后一个参数之后的参数</strong>是未定义行为，在不同平台、不同编译器实现下的结果可能不完全相同，所以在使用这些函数的时候也请大家务必注意参数的个数和类型问题。</p>
</blockquote>
<p>  这段话不是我写的。我是直接从决赛题的题目背景里搬过来的。其实它讲的已经比较清楚了，网上的各种教程基本上都是这段代码和解释。但是，有几点想与大家探讨一下。</p>
<h2 id="1关于可变参数的读取个数的问题">1）关于可变参数的读取个数的问题</h2>
<p>  最后一段话中其实解释了这个问题：<strong>读取的参数个数也只能通过用户输入来确认</strong>！</p>
<p>  这就是为什么前面<code>printf()</code>的例子中没有报错的原因了——编译器不会检查函数的参数个数。<code>printf()</code>完全是依赖格式化字符串中的种种要求来读取后面的可变参数的。而这又引发了另一个问题，何时停止读取？——依然依赖格式化字符串中的要求。因此，当格式化字符串中有要求输出、而后面的可变参数中并没有对应参数时，就出现了<strong>访问参数越界的情况</strong>——这也正是前面输出乱码的原因。</p>
<h2 id="2关于va_start">2）关于<code>va_start()</code></h2>
<blockquote>
<p><code>va_start(args, count);</code> 使参数列表指针指向函数参数 <code>count</code></p>
</blockquote>
<p>  这句话这么说其实不太合适。（刚刚还说这段话讲得比较清楚&hellip;&hellip;，就当是出题人美中不足吧）</p>
<p>  要解释清楚<code>va_start(args, count);</code>，我们还是来做实验为好。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdarg.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">sumplus</span><span class="p">(</span><span class="kt">int</span> <span class="n">count</span><span class="p">,</span> <span class="kt">int</span> <span class="n">m</span><span class="p">,</span> <span class="p">...)</span> 
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">va_list</span> <span class="n">args</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="nf">va_start</span><span class="p">(</span><span class="n">args</span><span class="p">,</span> <span class="n">count</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="kt">int</span> <span class="n">res</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">count</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> 
</span></span><span class="line"><span class="cl">    <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="kt">int</span> <span class="n">val</span> <span class="o">=</span> <span class="nf">va_arg</span><span class="p">(</span><span class="n">args</span><span class="p">,</span> <span class="kt">int</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="n">res</span> <span class="o">+=</span> <span class="n">val</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="nf">va_end</span><span class="p">(</span><span class="n">args</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">res</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">	<span class="kt">int</span> <span class="n">a</span> <span class="o">=</span> <span class="nf">sumplus</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">100</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">	<span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">a</span><span class="p">);</span> 
</span></span><span class="line"><span class="cl">	<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>  这段代码编译会有warning：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cmd" data-lang="cmd"><span class="line"><span class="cl">warning: second parameter of &#39;va_start&#39; not last named argument [-Wvarargs]
</span></span><span class="line"><span class="cl">     va_start(args, count);
</span></span><span class="line"><span class="cl">     <span class="se">^
</span></span></span></code></pre></div><p>  运行试试？</p>
<pre tabindex="0"><code class="language-out" data-lang="out">104
</code></pre><p>  这就说明编译之后，参数还是从 <code>...</code> 的位置开始读取的。（应该是编译器帮忙优化的，自动将指针挪到last named argument那里了）</p>
<p>  我们来看看GCC中<code>va_start()</code>的声明。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#define va_start(v,l)	__builtin_va_start(v,l)
</span></span></span></code></pre></div><p>  emmm，意义不大&hellip;&hellip;</p>
<p>  再看看VC6.0中的声明：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#define va_start(ap,v) ( ap = (va_list)&amp;v + _INTSIZEOF(v) )
</span></span></span></code></pre></div><p>  看来这是将第一个可选参数的地址赋值给<code>ap</code>。（至少在VC6.0里面是这样的）</p>
<p>  因此<code>va_start()</code>的作用是使参数列表指针指向第一个可选参数。</p>
<p>  引用一下<a href="http://www.cplusplus.com/reference/cstdarg/va_start/">cplusplus</a>对于<code>va_start()</code>的介绍来证明和完善这一观点。</p>
<blockquote>
<p><strong>va_start</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">va_start</span> <span class="p">(</span><span class="n">va_list</span> <span class="n">ap</span><span class="p">,</span> <span class="n">paramN</span><span class="p">);</span>
</span></span></code></pre></div><p>Initialize a variable argument list</p>
<p>Initializes ap to retrieve the additional arguments after parameter paramN.</p>
<p>A function that invokes <a href="http://www.cplusplus.com/va_start">va_start</a>, shall also invoke <a href="http://www.cplusplus.com/va_end">va_end</a> before it returns.</p>
<p><em>Parameters</em></p>
<ul>
<li>ap</li>
</ul>
<p>Uninitialized object of type <a href="http://www.cplusplus.com/va_list">va_list</a>. After the call, it carries the information needed to retrieve the additional arguments using <a href="http://www.cplusplus.com/va_arg">va_arg</a>. If ap has already been passed as first argument to a previous call to <a href="http://www.cplusplus.com/va_start">va_start</a> or <a href="http://www.cplusplus.com/va_copy">va_copy</a>, it shall be passed to <a href="http://www.cplusplus.com/va_end">va_end</a> before calling this function.</p>
<ul>
<li>paramN</li>
</ul>
<p>Name of the last named parameter in the function definition. The arguments extracted by subsequent calls to <a href="http://www.cplusplus.com/va_arg">va_arg</a> are those after paramN.</p>
</blockquote>
<h2 id="3关于va_arg">3）关于<code>va_arg()</code></h2>
<blockquote>
<p>C 语言参数传递时有自动类型提升，char 会被 cast 成 int 再传过去，所以在拿的时候也得拿一个 int</p>
</blockquote>
<p>  什么意思呢？一会看到实例就明白了。简单说，就是提取可变参数时，所提取的变量类型不一定与其实际类型一致，比如<code>char</code>就需要以<code>int</code>类型的方式读取。</p>
<h2 id="4关于va_end">4）关于<code>va_end()</code></h2>
<blockquote>
<p>参数指针可以在参数列表中随意地来回移动，但必须在<code>va_start()</code> … <code>va_end()</code>之内</p>
</blockquote>
<p>  还记得我在前面提到过的一个看似无用的实验吗？<code>int sumplus(int count, ..., int m)</code>并不能通过编译。但是我为什么会想到去尝试？理由很简单，既然 <code>va_start()</code> 和 <code>va_end()</code> 是成对出现的，那么是否会存在这么一种参数结构，先有几个强制参数，再是可变参数，最后又是几个强制参数，中间调用可变参数时使用 <code>va_start()</code> 和 <code>va_end()</code> ？实验证明这是不允许的，可变参数就是必须放在最后，这是规定与要求。</p>
<p>  可是既然如此，那<code>va_end()</code>意义何在？可以不调用吗？</p>
<p>  老规矩，先做个实验看看：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdarg.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">sumplus</span><span class="p">(</span><span class="kt">int</span> <span class="n">count</span><span class="p">,</span> <span class="p">...)</span> 
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">va_list</span> <span class="n">args</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="nf">va_start</span><span class="p">(</span><span class="n">args</span><span class="p">,</span> <span class="n">count</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="kt">int</span> <span class="n">res</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">count</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="kt">int</span> <span class="n">val</span> <span class="o">=</span> <span class="nf">va_arg</span><span class="p">(</span><span class="n">args</span><span class="p">,</span> <span class="kt">int</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="n">res</span> <span class="o">+=</span> <span class="n">val</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="c1">//    va_end(args);
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="k">return</span> <span class="n">res</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>  编译通过：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cmd" data-lang="cmd"><span class="line"><span class="cl">Compilation results...
</span></span><span class="line"><span class="cl">--------
</span></span><span class="line"><span class="cl">- Errors: 0
</span></span><span class="line"><span class="cl">- Warnings: 0
</span></span></code></pre></div><p>  运行也没毛病&hellip;&hellip;</p>
<p>  所以，真的可以省？</p>
<p>  几经周折，在网上找到这么一篇<a href="http://www.cppblog.com/ownwaterloo/archive/2009/04/21/is_va_end_necessary.html">文章</a>（这是原作者的文章，CSDN上面的是转载的，好在还注明了原文地址），建议大家去看看。我这里只引用其中的一部分。</p>
<h3 id="1不调用可能导致程序崩溃">1.不调用可能导致程序崩溃</h3>
<blockquote>
<p>  从一个使用过va_start()的函数中退出之前，<strong>必须</strong>调用一次va_end()。
  这是因为va_start<strong>可能</strong>以某种方式<strong>修改了堆栈</strong>，这种修改可能导致<strong>返回无法完成</strong>，va_end()能将有关的修改复原。
      ——《C++程序设计语言》 第3版、特别版， p139</p>
</blockquote>
<h3 id="2不调用可能导致内存泄漏">2.不调用可能导致内存泄漏</h3>
<blockquote>
<p>  我们务必记住，在使用完va_list变量后一定要调用宏va_end。
  v在<strong>大多数</strong>C实现上，调用va_end与<strong>否并无区别</strong>。
  但是，<strong>某些版本</strong>的va_start宏为了方便对va_list的遍历，就给参数列表<strong>动态分配内存</strong>。
  这样一种C实现很可能利用va_end宏来释放此前动态分配的内存；
  如果忘记调用宏va_end，最后得到的程序可能在某些机型上没有问题，而在另一些机型上则发生“<strong>内存泄露</strong>”。
      ——《C陷阱与缺陷》， p161</p>
</blockquote>
<h3 id="3还是不想调用">3.还是不想调用？&hellip;&hellip;</h3>
<blockquote>
<p>…… 最后，<strong>必须</strong>在函数返回之前<strong>调用</strong>va_end，以完成一些必要的<strong>清理</strong>工作。
      ——《C程序设计语言》 第2版， p137</p>
<p>……在所有参数处理完毕后， 且在<strong>退出函数f之前</strong>，<strong>必须调用宏va_end一次</strong> ……
      ——《C程序设计语言》 第2版， p232</p>
</blockquote>
<p>  插句题外话：**按照规矩办事，其实想得比你重要！**看看中国那稀烂的安卓生态吧，不多说了&hellip;&hellip;</p>
<h1 id="四自己实现printf决赛原题">四、自己实现<code>printf()</code>（决赛原题）</h1>
<h2 id="题目描述">题目描述</h2>
<blockquote>
<p>这道题需要你实现一个简单的 <code>printf</code> ，接受一个格式化字符串和若干参数，将结果打印至标准输出。</p>
<p>满足：</p>
<ol>
<li>使用 <code>'$'</code> 作为转义字符，在需要输出 <code>'$'</code> 字符的时候重复一次 <code>'$'</code> , 其它情况下视为输出对应类型的参数</li>
<li>支持 <code>$d</code> 输出 32 位整数(<code>int</code>)， <code>$s</code> 输出字符串(<code>char*</code>)直至 <code>'\0'</code> ，<code>$f</code> 输出双精度浮点数 (<code>double</code>), 保留 6 位小数 , <code>$c</code> 输出单个字符 (<code>char</code>)，保证输入合法</li>
<li>返回其中打印的字符个数</li>
<li>保证 <code>'$'</code> 后不会出现上述提及情况以外的字符</li>
</ol>
<h3 id="函数接口定义">函数接口定义</h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">simple_printf</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">fmt</span><span class="p">,</span> <span class="p">...);</span>
</span></span></code></pre></div><p>其中 <code>fmt</code> 为传入的格式化字符串，<code>...</code> 为传入的其它参数，返回输出的字符串长度</p>
<h3 id="裁判测试程序样例">裁判测试程序样例</h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdarg.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">simple_printf</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">fmt</span><span class="p">,</span> <span class="p">...);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="nf">simple_printf</span><span class="p">(</span><span class="s">&#34;123 &#34;</span><span class="p">));</span>
</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="nf">simple_printf</span><span class="p">(</span><span class="s">&#34;$$ &#34;</span><span class="p">));</span>
</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="nf">simple_printf</span><span class="p">(</span><span class="s">&#34;$d &#34;</span><span class="p">,</span> <span class="mi">123</span><span class="p">));</span>
</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="nf">simple_printf</span><span class="p">(</span><span class="s">&#34;$c &#34;</span><span class="p">,</span> <span class="sc">&#39;1&#39;</span><span class="p">));</span>
</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="nf">simple_printf</span><span class="p">(</span><span class="s">&#34;$s &#34;</span><span class="p">,</span> <span class="s">&#34;123&#34;</span><span class="p">));</span>
</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="nf">simple_printf</span><span class="p">(</span><span class="s">&#34;$f &#34;</span><span class="p">,</span> <span class="mf">123.4</span><span class="p">));</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="cm">/**
</span></span></span><span class="line"><span class="cl"><span class="cm">*	your code here
</span></span></span><span class="line"><span class="cl"><span class="cm">**/</span>
</span></span></code></pre></div><p>保证单次调用输出的长度小于 4096，输出的浮点数保留 6 位小数</p>
<h3 id="输入样例">输入样例</h3>
<p>没有输入</p>
<h3 id="输出样例">输出样例</h3>
<pre tabindex="0"><code class="language-out" data-lang="out">123 4
$ 2
123 4
1 2
123 4
123.400000 11
</code></pre></blockquote>
<p>  虽然我当时一遍就AC了，但是做复杂了（比赛时没有注意到<code>printf()</code>返回值就是打印的字符的个数，自己还单独实现了这个功能&hellip;），而且代码也只是能跑而已（比赛&hellip;时间很紧&hellip;&hellip;），可读性很差，所以借这个机会重新整理一下好了。</p>
<h2 id="ac代码标程改编">AC代码（标程改编）</h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">simple_printf</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">fmt</span><span class="p">,</span> <span class="p">...)</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">	<span class="n">va_list</span> <span class="n">args</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">	<span class="nf">va_start</span><span class="p">(</span><span class="n">args</span><span class="p">,</span> <span class="n">fmt</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">	<span class="kt">int</span> <span class="n">counter</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">	<span class="k">while</span> <span class="p">(</span><span class="o">*</span><span class="n">fmt</span> <span class="o">!=</span> <span class="sc">&#39;\0&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="p">{</span>
</span></span><span class="line"><span class="cl">		<span class="k">if</span> <span class="p">(</span><span class="o">*</span><span class="n">fmt</span> <span class="o">!=</span> <span class="sc">&#39;$&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">		<span class="p">{</span>
</span></span><span class="line"><span class="cl">			<span class="nf">putchar</span><span class="p">(</span><span class="o">*</span><span class="n">fmt</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">			<span class="n">fmt</span><span class="o">++</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">			<span class="n">counter</span><span class="o">++</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">			<span class="k">continue</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">		<span class="p">}</span>
</span></span><span class="line"><span class="cl">		<span class="n">fmt</span><span class="o">++</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">		<span class="k">if</span> <span class="p">(</span><span class="o">*</span><span class="n">fmt</span> <span class="o">==</span> <span class="sc">&#39;d&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">		<span class="p">{</span> <span class="c1">// integer
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>			<span class="kt">int</span> <span class="n">int_val</span> <span class="o">=</span> <span class="nf">va_arg</span><span class="p">(</span><span class="n">args</span><span class="p">,</span> <span class="kt">int</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">			<span class="n">counter</span> <span class="o">+=</span> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d&#34;</span><span class="p">,</span> <span class="n">int_val</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">			<span class="n">fmt</span><span class="o">++</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">		<span class="p">}</span>
</span></span><span class="line"><span class="cl">		<span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="o">*</span><span class="n">fmt</span> <span class="o">==</span> <span class="sc">&#39;f&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">		<span class="p">{</span> <span class="c1">// double
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>			<span class="kt">double</span> <span class="n">float_val</span> <span class="o">=</span> <span class="nf">va_arg</span><span class="p">(</span><span class="n">args</span><span class="p">,</span> <span class="kt">double</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">			<span class="n">counter</span> <span class="o">+=</span> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%lf&#34;</span><span class="p">,</span> <span class="n">float_val</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">			<span class="n">fmt</span><span class="o">++</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">		<span class="p">}</span>
</span></span><span class="line"><span class="cl">		<span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="o">*</span><span class="n">fmt</span> <span class="o">==</span> <span class="sc">&#39;s&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">		<span class="p">{</span> <span class="c1">// char*
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>			<span class="kt">char</span> <span class="o">*</span><span class="n">str</span> <span class="o">=</span> <span class="nf">va_arg</span><span class="p">(</span><span class="n">args</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">			<span class="n">counter</span> <span class="o">+=</span> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%s&#34;</span><span class="p">,</span> <span class="n">str</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">			<span class="n">fmt</span><span class="o">++</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">		<span class="p">}</span>
</span></span><span class="line"><span class="cl">		<span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="o">*</span><span class="n">fmt</span> <span class="o">==</span> <span class="sc">&#39;c&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">		<span class="p">{</span> <span class="c1">// char
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>			<span class="kt">char</span> <span class="n">cha_val</span> <span class="o">=</span> <span class="nf">va_arg</span><span class="p">(</span><span class="n">args</span><span class="p">,</span> <span class="kt">int</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">			<span class="n">counter</span> <span class="o">+=</span> <span class="mi">1</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">			<span class="nf">putchar</span><span class="p">(</span><span class="n">cha_val</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">			<span class="n">fmt</span><span class="o">++</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">		<span class="p">}</span>
</span></span><span class="line"><span class="cl">		<span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="o">*</span><span class="n">fmt</span> <span class="o">==</span> <span class="sc">&#39;$&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">		<span class="p">{</span>
</span></span><span class="line"><span class="cl">			<span class="n">fmt</span><span class="o">++</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">			<span class="nf">putchar</span><span class="p">(</span><span class="sc">&#39;$&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">			<span class="n">counter</span> <span class="o">+=</span> <span class="mi">1</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">		<span class="p">}</span>
</span></span><span class="line"><span class="cl">	<span class="p">}</span>
</span></span><span class="line"><span class="cl">	<span class="nf">va_end</span><span class="p">(</span><span class="n">args</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">	<span class="k">return</span> <span class="n">counter</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>  有两点需要注意:</p>
<p>  1. C 语言参数传递时有自动类型提升，char 会被 cast 成 int 再传过去，所以在拿的时候也得拿一个 int</p>
<p>  这就是刚才提到的关于<code>va_arg()</code>的实例。注意到这样一段代码：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="k">else</span> <span class="nf">if</span> <span class="p">(</span><span class="o">*</span><span class="n">fmt</span> <span class="o">==</span> <span class="sc">&#39;c&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span> <span class="c1">// char
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="kt">char</span> <span class="n">cha_val</span> <span class="o">=</span> <span class="nf">va_arg</span><span class="p">(</span><span class="n">args</span><span class="p">,</span> <span class="kt">int</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="n">counter</span> <span class="o">+=</span> <span class="mi">1</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="nf">putchar</span><span class="p">(</span><span class="n">cha_val</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="n">fmt</span><span class="o">++</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>  在这里，<code>char</code>需要用<code>int</code>来读取。（<code>char cha_val = va_arg(args, int)</code>)</p>
<p>  不过这个很容易发现，因为如果你用<code>char</code>来读取：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="k">else</span> <span class="nf">if</span> <span class="p">(</span><span class="o">*</span><span class="n">fmt</span> <span class="o">==</span> <span class="sc">&#39;c&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span> <span class="c1">// char
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="kt">char</span> <span class="n">cha_val</span> <span class="o">=</span> <span class="nf">va_arg</span><span class="p">(</span><span class="n">args</span><span class="p">,</span> <span class="kt">char</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="n">counter</span> <span class="o">+=</span> <span class="mi">1</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="nf">putchar</span><span class="p">(</span><span class="n">cha_val</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="n">fmt</span><span class="o">++</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>  编译会有warning&hellip;</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cmd" data-lang="cmd"><span class="line"><span class="cl">warning: &#39;char&#39; is promoted to &#39;int&#39; when passed through &#39;...&#39;
</span></span><span class="line"><span class="cl">    char cha_val = va_arg(args, char);
</span></span><span class="line"><span class="cl">                                <span class="se">^
</span></span></span><span class="line"><span class="cl"><span class="se">n</span>ote: (so you should pass &#39;int&#39; not &#39;char&#39; to &#39;va_arg&#39;)
</span></span><span class="line"><span class="cl">note: if this code is reached, the program will abort
</span></span></code></pre></div><p>  运行起来真的abort了&hellip;（不同编译器、不同编译选项可能结果不同）</p>
<pre tabindex="0"><code class="language-out" data-lang="out">123 4
$ 2
123 4
</code></pre><p>  2. 这基本上就是<code>printf()</code>的实现原理了，只不过<code>printf()</code>还可以支持更多的格式化字符串的要求。这也应证了我前面说的：编译器和函数完全不知道你给它了多少给参数。它们完全不知道这些，只是按照一定的规则在试图读取这些可变的参数。</p>
<p>  <code>printf()</code>依照的，就是格式化字符串。</p>
<hr>
<p>  关于C语言中变参函数的介绍差不多就这些了。自认为是网上最翔实的一篇了，主要还是将自己摸索的过程体现出来。过几天我会再写一篇关于C语言宏的文章，主要谈谈可变参数的宏函数以及宏运算符到底有什么用。希望这两篇文章能对读者有所帮助。</p>
]]></content:encoded>
    </item>
    <item>
      <title>Calculus Review</title>
      <link>https://blog.chong-zeng.com/posts/2019-01-15_calculus-review/</link>
      <pubDate>Tue, 15 Jan 2019 00:00:00 +0000</pubDate>
      <guid>https://blog.chong-zeng.com/posts/2019-01-15_calculus-review/</guid>
      <description>极限 函数&amp;amp;预备知识 参数方程 极坐标方程 二项式展开 和差化积公式 &amp;hellip; 数列极限 定义 $\xi - N$ （用于验证）
性质&amp;amp;四则运算 两大定理&amp;amp;$e$ 夹逼定理 单调有界定理 函数极限 定义 $\xi - \delta​$
$\xi - X$
归结原理、左右极限 性质&amp;amp;四则运算 两大定理？ 夹逼定理（仍然成立） 单调有界？（No Longer Exist） 两大重要极限 $\lim_{x \to 0}\frac{x}{sinx} = 1$ $\lim_{x \to \infty}(1 + \frac{1}{x})^x = e​$ 连续 定义 $\lim_{x \to x_0}f(x) = f(x_0)​$
有限闭区间上的连续函数的性质 有界性 最大最小值定理 零点存在定理 介值定理 （常用于证明$F(\xi) = 0​$ ) o()、O()、等价替换 $o(x) + o(x^2) = o(x)$
$o()$代表”一类“量，因此”=“不是传统意义上的”等于“
导数 定义 $\lim_{x \to x_0}\frac{f(x) - f(x_0)}{x - x_0} = A = f&amp;rsquo;(x_0)$ 切线 割线斜率的极限</description>
      <content:encoded><![CDATA[<p><img loading="lazy" src="/old-pics/illustrations/calculus_I.jpg" alt=""  />
</p>
<h1 id="极限">极限</h1>
<h2 id="函数预备知识">函数&amp;预备知识</h2>
<ol>
<li>参数方程</li>
<li>极坐标方程</li>
<li>二项式展开</li>
<li>和差化积公式</li>
<li>&hellip;</li>
</ol>
<h2 id="数列极限">数列极限</h2>
<h3 id="定义">定义</h3>
<p>$\xi - N$ （用于验证）</p>
<h3 id="性质四则运算">性质&amp;四则运算</h3>
<h3 id="两大定理e">两大定理&amp;$e$</h3>
<ol>
<li>夹逼定理</li>
<li>单调有界定理</li>
</ol>
<h2 id="函数极限">函数极限</h2>
<h3 id="定义-1">定义</h3>
<ol>
<li>
<p>$\xi - \delta​$</p>
</li>
<li>
<p>$\xi - X$</p>
</li>
</ol>
<h4 id="归结原理左右极限">归结原理、左右极限</h4>
<h3 id="性质四则运算-1">性质&amp;四则运算</h3>
<h3 id="两大定理">两大定理？</h3>
<ol>
<li>夹逼定理（仍然成立）</li>
<li>单调有界？（No Longer Exist）</li>
</ol>
<h3 id="两大重要极限">两大重要极限</h3>
<ol>
<li>$\lim_{x \to 0}\frac{x}{sinx} = 1$</li>
<li>$\lim_{x \to \infty}(1 + \frac{1}{x})^x = e​$</li>
</ol>
<h2 id="连续">连续</h2>
<h3 id="定义-2">定义</h3>
<p>$\lim_{x \to x_0}f(x) = f(x_0)​$</p>
<h3 id="有限闭区间上的连续函数的性质">有限闭区间上的连续函数的性质</h3>
<ol>
<li>有界性</li>
<li>最大最小值定理</li>
<li>零点存在定理</li>
<li><strong>介值定理</strong> （常用于证明$F(\xi) = 0​$ )</li>
</ol>
<h3 id="oo等价替换">o()、O()、等价替换</h3>
<p>$o(x) + o(x^2) = o(x)$</p>
<p>$o()$代表”一类“量，因此”=“不是传统意义上的”等于“</p>
<h1 id="导数">导数</h1>
<h2 id="定义-3">定义</h2>
<h3 id="lim_x-to-x_0fracfx---fx_0x---x_0--a--fx_0">$\lim_{x \to x_0}\frac{f(x) - f(x_0)}{x - x_0} = A = f&rsquo;(x_0)$</h3>
<h3 id="切线">切线</h3>
<p>割线斜率的极限</p>
<h3 id="fx_0--0-的意义">$f&rsquo;(x_0) &gt; 0$ 的意义</h3>
<p>在$x_0$右边的一小块邻域内，$f(x) &gt; f(x_0)$</p>
<h2 id="高阶导数">高阶导数</h2>
<ol>
<li>
<p>$\frac{ax + b}{cx + d}$</p>
</li>
<li>
<p>$x^nf(x)$</p>
</li>
<li>
<p>$arctan^{(100)}(0)$</p>
<p>$arcsin^{(100)}(0)$</p>
</li>
<li>
<p>泰勒</p>
<p>$x^2sinx$求100阶导</p>
</li>
</ol>
<h2 id="其他函数">其他函数</h2>
<h3 id="反函数">反函数</h3>
<p>到底对谁求导</p>
<h3 id="复合函数">复合函数</h3>
<h3 id="参数方程">参数方程</h3>
<h3 id="隐函数">隐函数</h3>
<h1 id="微分">微分</h1>
<h2 id="定义-4">定义</h2>
<p>一阶微分的形式不变性</p>
<h2 id="微商">微商</h2>
<p>{% raw %}
$\frac{{d}y}{{d}x}​$
{% endraw %}</p>
<h3 id="高阶">高阶</h3>
<p>{% raw %}
$\frac{{d^2}y}{{d}x^2} = \frac{{d}{(\frac{{d}y}{{d}x}})}{{d}x}$
{% endraw %}</p>
<h1 id="微分定理">微分定理</h1>
<h2 id="中值定理">中值定理</h2>
<h3 id="极值凹凸性">极值&amp;凹凸性</h3>
<ol>
<li>极值&amp;费马定理</li>
<li>罗尔定理</li>
<li>拉格朗日中值定理</li>
<li>柯西中值定理</li>
</ol>
<h3 id="主要用于证明fxi--0">主要用于证明$F&rsquo;(\xi) = 0$</h3>
<h2 id="泰勒定理">泰勒定理</h2>
<h3 id="展开">展开</h3>
<ol>
<li>展开点</li>
<li>带入点</li>
</ol>
<h4 id="复合函数展开">复合函数展开</h4>
<h4 id="主要用于证明fxi-fxi">主要用于证明$F&rsquo;&rsquo;(\xi)$ 、$F&rsquo;&rsquo;&rsquo;(\xi)$</h4>
<p>给出高阶导数值的点往往是展开点！</p>
<h2 id="洛必达法则">洛必达法则</h2>
<blockquote>
<p><strong>洛</strong>就完了！</p>
</blockquote>
<h1 id="不定积分">不定积分</h1>
<h2 id="第一积分换元法">第一积分换元法</h2>
<p>凑微分法</p>
<p><strong>调整$dx$</strong></p>
<h2 id="第二积分换元法">第二积分换元法</h2>
<h3 id="去根号">去根号</h3>
<ol>
<li>三角换元</li>
<li>整体换$t$</li>
</ol>
<h3 id="倒带换">倒带换</h3>
<h2 id="分部积分">分部积分</h2>
<ol>
<li>直接计算</li>
<li>构造循环</li>
<li>形成递推</li>
</ol>
<h2 id="特殊函数">特殊函数</h2>
<ol>
<li>有理函数 -&gt; 裂项</li>
<li>三角有理函数 -&gt; 万能公式</li>
<li>其他特殊 -&gt; 换元</li>
</ol>
<h1 id="定积分">定积分</h1>
<h2 id="定义黎曼和">定义（黎曼和）</h2>
<p>{% raw %}
$\int_{a}^{b} f(x)dx = \lim_{x \to 0^+} \sum_{i = 1}^{n} f(\xi_i) \Delta x_i​$
{% endraw %}</p>
<ol>
<li>分割</li>
<li>取点</li>
<li>求和</li>
<li>求极限</li>
</ol>
<h3 id="对称">对称</h3>
<h3 id="和式转化">和式转化</h3>
<h2 id="变上限函数的导数">变上限函数的导数</h2>
<ol>
<li>普通</li>
<li>$\int_{}^{\phi(x)}​$</li>
<li>$\int_{}^{x} f(x - y) dy$  -&gt;换元</li>
</ol>
<h2 id="微积分基本定理">微积分基本定理</h2>
<h3 id="不定积分-1">不定积分</h3>
<h3 id="特殊类型">特殊类型</h3>
<ol>
<li>奇偶函数 $\int_{-a}^{a} f(x) dx = \int_{0}^{a} [f(x) + f(- x)]dx$</li>
<li>$\int_{0}^{\frac{\pi}{2}}​$ 、 $\int_{0}^{\frac{\pi}{4}}​$ 、$\int_{0}^{\pi}​$  换元</li>
<li>其他</li>
</ol>
<h3 id="反常积分">反常积分</h3>
<ol>
<li>区间无限</li>
<li>函数无界</li>
</ol>
<h3 id="应用">应用</h3>
<ol>
<li>数学</li>
<li>物理</li>
</ol>
]]></content:encoded>
    </item>
    <item>
      <title>2018年终回顾</title>
      <link>https://blog.chong-zeng.com/posts/2018-12-31_2018/</link>
      <pubDate>Mon, 31 Dec 2018 00:00:00 +0000</pubDate>
      <guid>https://blog.chong-zeng.com/posts/2018-12-31_2018/</guid>
      <description>2018年过去了，感觉挺快的。到现在我还记得去年的今天，我正在准备元月调考，而现在，我正在大学的寝室里待着。刚好这两天放假，不妨抽个空，盘点一下我自己的2018年。
想必18年最重要的事情，就是高考了。其实真的感觉没那么紧张，也没有晚上睡不着觉的情况，真的感觉跟平常差不多。唯一的区别，就是这是高中最后一次考试了，而且考完要填志愿。本来一直想去北京的，结果误打误撞地来到了浙大。但是现在看来，也许选择浙大是一个明智的选择，毕竟最后进入到了自己最喜欢的专业，也见到了许许多多的大佬，紫金港条件也不错，不出意外的话，等大西区建好之后，我浙将是中国面积最大的大学之一。
其实我一直觉得，大学最重要的目的是拓宽视野。其实很多大学里学的知识到工作中并不能直接使用，但是在学习它们时，你学习能力的提升，你接触到的老师的视野，都是你受益终生的财富。看到周围还有人用高中的方式在学习，不听课、只刷题，除了学习什么都不干，不去与大佬接触，我只能笑而不语。
说起大佬，不得不说机器人协会是个很牛的协会。这应该是学校最硬核的协会之一，一直想玩的机器人、一直想学的Arduino，嗯，都玩到了。教学部很多大佬啊，真的是让人受益匪浅，第一次内训就推荐了一大堆资源，涵盖了方方面面，不得不说很牛！在协会，我还认识了不少竺可桢学院的大佬。哎，抱腿的感觉，真好。
学校的情况差不多就这些吧。总之，选择浙大，我不后悔。
2018年，还有很多要感谢的人。
首先，是家人。没有他们的支持，我不可能走到今天。无论是高考前的煎熬，还是填报志愿时的纠结，还是选择专业以及准备专业面试时，他们都给了我很大的支持。这里一起说一声，谢谢了，我爱你们。
其次，是老师。古人云：“为师一时，为父一生。”确实，从小学到高中，我遇到了不少好老师。时至今日，我觉得有必要对他们都说一声谢谢。
还有各位学长学姐。高考填报志愿时，问了不少学长学姐，而且还是在他们的考试周——我现在才明白考试周其实比高中忙的多。准备专业面试时，他们也为我提供了很大的帮助。在此一并致谢。
最后是我的朋友们。在我孤独之时，他们能陪陪我。感谢你们。
这是我成人后第一次跨年，学会感谢是人生的重要一课，因而特地在此，再次感谢所有在我成长过程中帮助过我的人。谢谢你们。
2018也有很多实现了的小目标：
进入心仪大学和专业
拿到第一门满绩
参加一次学术竞赛并取得一定名次
改掉高中时不良的睡眠习惯
搭建自己的个人网站/博客（就是这个了，哈哈！）
&amp;hellip;&amp;hellip;
当然2018 也有遗憾，但是不多，不妨把它们放到明年的目标里面。
最后，讲讲我为什么想建立这个网站，以及明年的规划（flag）吧。
建立网站当然不是空穴来风。这个想法的产生是因为我一天无聊，点开求是潮的“关于”页面，发现里面的开发人员（都是在校学生）每个人都有自己的个人网站，有的甚至还有自己的域名。具体看他们的文章，会发现确实技术含量很高。向大佬看齐，是建站的第一个原因。另外，一些刷到的题目中，有很多让我眼前一亮的想法，很难找到一个合适的地方来写这些东西。（我知道CSDN，但是那里盗版太严重，而且做project的经历让我发现上面的代码可以有多不靠谱。）再加上这种东西发到朋友圈、说说并不合适，也很容易淹没，我也不准备让很多人看到我的文章，因此自己建一个站点应该是个不错的选择。目前，它部署在GitHub上，没有被百度收录，而且GitHub是禁百度的spider的，因此百度是找不到这个网站的。我希望在浩瀚的互联网中，做一个淡定的隐士——志同道合者自然能找到我的网站，与我交流——这就足矣。
明年准备就一些简单的算法（高深的我也还没学&amp;hellip;&amp;hellip;.）谈谈自己的感受，可以理解为我的学习笔记。一些想法我也会放到这里来。另外，在MSC比赛中遇到了两个很有意思的语法问题，这个准备就在明年一月份写出来。（flag立在这里了&amp;hellip;&amp;hellip;.）另外，我在明年会参加中控杯，中间遇到的技术问题及其解决方案，我也会放在这里。敬请期待。
2018年的总结差不多就这些吧。期待2019年。
See U, 2018!</description>
      <content:encoded><![CDATA[<p>  2018年过去了，感觉挺快的。到现在我还记得去年的今天，我正在准备元月调考，而现在，我正在大学的寝室里待着。刚好这两天放假，不妨抽个空，盘点一下我自己的2018年。</p>
<p>  想必18年最重要的事情，就是高考了。其实真的感觉没那么紧张，也没有晚上睡不着觉的情况，真的感觉跟平常差不多。唯一的区别，就是这是高中最后一次考试了，而且考完要填志愿。本来一直想去北京的，结果误打误撞地来到了浙大。但是现在看来，也许选择浙大是一个明智的选择，毕竟最后进入到了自己最喜欢的专业，也见到了许许多多的大佬，紫金港条件也不错，不出意外的话，等大西区建好之后，我浙将是中国面积最大的大学之一。</p>
<p>  其实我一直觉得，大学最重要的目的是拓宽视野。其实很多大学里学的知识到工作中并不能直接使用，但是在学习它们时，你学习能力的提升，你接触到的老师的视野，都是你受益终生的财富。看到周围还有人用高中的方式在学习，不听课、只刷题，除了学习什么都不干，不去与大佬接触，我只能笑而不语。</p>
<p>  说起大佬，不得不说机器人协会是个很牛的协会。这应该是学校最硬核的协会之一，一直想玩的机器人、一直想学的Arduino，嗯，都玩到了。教学部很多大佬啊，真的是让人受益匪浅，第一次内训就推荐了一大堆资源，涵盖了方方面面，不得不说很牛！在协会，我还认识了不少竺可桢学院的大佬。哎，抱腿的感觉，真好。</p>
<p>  学校的情况差不多就这些吧。总之，选择浙大，我不后悔。</p>
<p>  2018年，还有很多要感谢的人。</p>
<p>  首先，是家人。没有他们的支持，我不可能走到今天。无论是高考前的煎熬，还是填报志愿时的纠结，还是选择专业以及准备专业面试时，他们都给了我很大的支持。这里一起说一声，谢谢了，我爱你们。</p>
<p>  其次，是老师。古人云：“为师一时，为父一生。”确实，从小学到高中，我遇到了不少好老师。时至今日，我觉得有必要对他们都说一声谢谢。</p>
<p>  还有各位学长学姐。高考填报志愿时，问了不少学长学姐，而且还是在他们的考试周——我现在才明白考试周其实比高中忙的多。准备专业面试时，他们也为我提供了很大的帮助。在此一并致谢。</p>
<p>  最后是我的朋友们。在我孤独之时，他们能陪陪我。感谢你们。</p>
<p>  这是我成人后第一次跨年，学会感谢是人生的重要一课，因而特地在此，再次感谢所有在我成长过程中帮助过我的人。谢谢你们。</p>
<p>  2018也有很多实现了的小目标：</p>
<ul>
<li>
<p>进入心仪大学和专业</p>
</li>
<li>
<p>拿到第一门满绩</p>
</li>
<li>
<p>参加一次学术竞赛并取得一定名次</p>
</li>
<li>
<p>改掉高中时不良的睡眠习惯</p>
</li>
<li>
<p>搭建自己的个人网站/博客（就是这个了，哈哈！）</p>
<p>&hellip;&hellip;</p>
</li>
</ul>
<p>  当然2018 也有遗憾，但是不多，不妨把它们放到明年的目标里面。</p>
<p>  最后，讲讲我为什么想建立这个网站，以及明年的规划（flag）吧。</p>
<p>  建立网站当然不是空穴来风。这个想法的产生是因为我一天无聊，点开求是潮的“关于”页面，发现里面的开发人员（都是在校学生）每个人都有自己的个人网站，有的甚至还有自己的域名。具体看他们的文章，会发现确实技术含量很高。向大佬看齐，是建站的第一个原因。另外，一些刷到的题目中，有很多让我眼前一亮的想法，很难找到一个合适的地方来写这些东西。（我知道CSDN，但是那里盗版太严重，而且做project的经历让我发现上面的代码可以有多不靠谱。）再加上这种东西发到朋友圈、说说并不合适，也很容易淹没，我也不准备让很多人看到我的文章，因此自己建一个站点应该是个不错的选择。目前，它部署在GitHub上，没有被百度收录，而且GitHub是禁百度的spider的，因此百度是找不到这个网站的。我希望在浩瀚的互联网中，做一个淡定的隐士——志同道合者自然能找到我的网站，与我交流——这就足矣。</p>
<p>  明年准备就一些简单的算法（高深的我也还没学&hellip;&hellip;.）谈谈自己的感受，可以理解为我的学习笔记。一些想法我也会放到这里来。另外，在MSC比赛中遇到了两个很有意思的语法问题，这个准备就在明年一月份写出来。（flag立在这里了&hellip;&hellip;.）另外，我在明年会参加中控杯，中间遇到的技术问题及其解决方案，我也会放在这里。敬请期待。</p>
<p>  2018年的总结差不多就这些吧。期待2019年。</p>
<p>  See U, 2018!</p>
]]></content:encoded>
    </item>
    <item>
      <title>Python3 Learning Notes</title>
      <link>https://blog.chong-zeng.com/posts/2018-12-31_python3/</link>
      <pubDate>Mon, 31 Dec 2018 00:00:00 +0000</pubDate>
      <guid>https://blog.chong-zeng.com/posts/2018-12-31_python3/</guid>
      <description>Chapter 1 Setup import this The Zen of Python, by Tim Peters
Beautiful is better than ugly. Explicit is better than implicit. Simple is better than complex. Complex is better than complicated. Flat is better than nested. Sparse is better than dense. Readability counts. Special cases aren&amp;rsquo;t special enough to break the rules. Although practicality beats purity. Errors should never pass silently. Unless explicitly silenced. In the face of ambiguity, refuse the temptation to guess.</description>
      <content:encoded><![CDATA[<!-- raw HTML omitted -->
<h1 id="chapter-1-setup">Chapter 1 Setup</h1>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">this</span>
</span></span></code></pre></div><blockquote>
<p>The Zen of Python, by Tim Peters</p>
<p>Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren&rsquo;t special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one&ndash; and preferably only one &ndash;obvious way to do it.
Although that way may not be obvious at first unless you&rsquo;re Dutch.
Now is better than never.
Although never is often better than <em>right</em> now.
If the implementation is hard to explain, it&rsquo;s a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea &ndash; let&rsquo;s do more of those!</p>
</blockquote>
<hr>
<!-- raw HTML omitted -->
<h1 id="chapter-2-data-types">Chapter 2 Data Types</h1>
<h2 id="001-variables">001 variables</h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">msg</span> <span class="o">=</span> <span class="s2">&#34;hello&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">msg</span><span class="p">)</span>
</span></span></code></pre></div><blockquote>
<p>hello</p>
</blockquote>
<h2 id="002-string-operations">002 string operations</h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">name</span> <span class="o">=</span> <span class="s2">&#34;ada lovelace&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">name</span><span class="o">.</span><span class="n">title</span><span class="p">())</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">name</span><span class="o">.</span><span class="n">upper</span><span class="p">())</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">name</span><span class="o">.</span><span class="n">lower</span><span class="p">())</span>
</span></span></code></pre></div><blockquote>
<p>Ada Lovelace
ADA LOVELACE
ada lovelace</p>
</blockquote>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">new_msg</span> <span class="o">=</span> <span class="n">msg</span> <span class="o">+</span> <span class="s2">&#34; &#34;</span> <span class="o">+</span> <span class="n">name</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span> <span class="p">(</span><span class="s1">&#39;</span><span class="se">\t</span><span class="s1">&#39;</span> <span class="o">+</span> <span class="n">new_msg</span> <span class="o">+</span> <span class="s1">&#39;</span><span class="se">\n</span><span class="s1">&#39;</span><span class="p">)</span>
</span></span></code></pre></div><blockquote>
<p>hello ada lovelace</p>
</blockquote>
<p>​</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">msg_1</span> <span class="o">=</span> <span class="s1">&#39;     hiuf yeb   w hviu ywe r         &#39;</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">msg_1</span><span class="o">.</span><span class="n">rstrip</span><span class="p">())</span>
</span></span></code></pre></div><blockquote>
<pre><code> hiuf yeb   w hviu ywe r
</code></pre>
</blockquote>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">msg_1</span> <span class="o">=</span> <span class="n">msg_1</span><span class="o">.</span><span class="n">rstrip</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">msg_1</span><span class="o">.</span><span class="n">lstrip</span><span class="p">())</span>
</span></span></code></pre></div><blockquote>
<p>hiuf yeb   w hviu ywe r</p>
</blockquote>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">msg_1</span> <span class="o">=</span> <span class="s1">&#39;</span><span class="se">\t</span><span class="s1">&#39;</span> <span class="o">+</span> <span class="n">msg_1</span> <span class="o">+</span> <span class="s1">&#39;</span><span class="se">\n</span><span class="s1">&#39;</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">msg_1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">msg_1</span> <span class="o">=</span> <span class="n">msg_1</span><span class="o">.</span><span class="n">rstrip</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">msg_1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">msg_1</span> <span class="o">=</span> <span class="n">msg_1</span><span class="o">.</span><span class="n">lstrip</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">msg_1</span><span class="p">)</span>
</span></span></code></pre></div><pre><code>	     hiuf yeb   w hviu ywe r

	     hiuf yeb   w hviu ywe r
hiuf yeb   w hviu ywe r
</code></pre>
<h2 id="003-number-operations">003 number operations</h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="mi">10</span><span class="o">**</span><span class="mi">6</span>
</span></span></code></pre></div><pre><code>1000000
</code></pre>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="mi">3</span><span class="o">/</span><span class="mi">2</span>
</span></span></code></pre></div><pre><code>1.5
</code></pre>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="mi">3</span><span class="o">//</span><span class="mi">2</span>
</span></span></code></pre></div><pre><code>1
</code></pre>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="mf">0.1</span><span class="o">*</span><span class="mi">3</span>
</span></span></code></pre></div><pre><code>0.30000000000000004
</code></pre>
<p><em>floats&rsquo; problems still exists in python3, but it&rsquo;s common in any language due to how computers save these floats</em></p>
<h2 id="004-numberstring">004 number&amp;string</h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">num_test_1</span> <span class="o">=</span> <span class="mi">666</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">num_test_1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># print(&#39;huvife&#39; + num_test_1 + &#39;gbtehgbe&#39;)</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># error version</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="s1">&#39;huvife&#39;</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">num_test_1</span><span class="p">)</span> <span class="o">+</span> <span class="s1">&#39;gbtehgbe&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># or</span>
</span></span><span class="line"><span class="cl"><span class="n">num_test_1</span> <span class="o">=</span> <span class="s1">&#39;666&#39;</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="s1">&#39;huvife&#39;</span> <span class="o">+</span> <span class="n">num_test_1</span> <span class="o">+</span> <span class="s1">&#39;gbtehgbe&#39;</span><span class="p">)</span>
</span></span></code></pre></div><pre><code>666
huvife666gbtehgbe
huvife666gbtehgbe
</code></pre>
<hr>
<!-- raw HTML omitted -->
<h1 id="chapter-3-list">Chapter 3 List</h1>
<p><em>There is no array in Python!!!</em></p>
<h2 id="001-introduction-to-lists">001 Introduction to Lists</h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">arr</span> <span class="o">=</span> <span class="p">[</span><span class="s1">&#39;vfervewr&#39;</span><span class="p">,</span><span class="s1">&#39;gftewgwter&#39;</span><span class="p">,</span><span class="s1">&#39;gtewgewwe&#39;</span><span class="p">,</span><span class="s1">&#39;gtwgw&#39;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">arr</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">arr</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">title</span><span class="p">())</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">arr</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">])</span> <span class="c1">#see? minus is not only available, but useful!</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">arr</span><span class="p">[</span><span class="o">-</span><span class="mi">3</span><span class="p">])</span>
</span></span><span class="line"><span class="cl"><span class="n">message</span> <span class="o">=</span> <span class="s2">&#34;vfsvegeerwsgetrw &#34;</span> <span class="o">+</span> <span class="n">arr</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="s2">&#34; vbgfdbgfrdsbg&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">message</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># message = &#34;vfsvegeerwsgetrw &#34; + arr + &#34; vbgfdbgfrdsbg&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># print(message)</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># error version</span>
</span></span></code></pre></div><pre><code>['vfervewr', 'gftewgwter', 'gtewgewwe', 'gtwgw']
Vfervewr
gtwgw
gftewgwter
vfsvegeerwsgetrw vfervewr vbgfdbgfrdsbg
</code></pre>
<p>  <em>Again, thers is no array in Python! So don&rsquo;t follow my mistake! (I used &lsquo;arr&rsquo; to name a list, because I thought they were the same!)</em></p>
<h2 id="002-modifying-lists">002 Modifying Lists</h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">arr</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="s1">&#39;cool&#39;</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">arr</span><span class="p">)</span>
</span></span></code></pre></div><pre><code>['cool', 'gftewgwter', 'gtewgewwe', 'gtwgw', 'new one', 666]
</code></pre>
<h2 id="003-add-elements">003 Add Elements</h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">arr</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s1">&#39;new one&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">arr</span><span class="p">)</span>
</span></span></code></pre></div><pre><code>['cool', 'gftewgwter', 'gtewgewwe', 'gtwgw', 'new one', 666, 'new one']
</code></pre>
<p>  You can even create an empty list and add elements to it later!</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">motor</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">motor</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s1">&#39;honda&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">motor</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s1">&#39;yamaha&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">motor</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s1">&#39;suzuki&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">motor</span><span class="p">)</span>
</span></span></code></pre></div><pre><code>['honda', 'yamaha', 'suzuki']
</code></pre>
<h2 id="004-insert-elements">004 Insert Elements</h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">motor</span><span class="o">.</span><span class="n">insert</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="s1">&#39;ducati&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">motor</span><span class="p">)</span>
</span></span></code></pre></div><pre><code>['ducati', 'honda', 'yamaha', 'suzuki']
</code></pre>
<h2 id="005-delete-elements">005 Delete Elements</h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">motor</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">del</span> <span class="n">motor</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">motor</span><span class="p">)</span>
</span></span></code></pre></div><pre><code>['ducati', 'honda', 'yamaha', 'suzuki']
['ducati', 'yamaha', 'suzuki']
</code></pre>
<h2 id="006-pop-elements">006 Pop Elements</h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">motor</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">poped_motor</span> <span class="o">=</span> <span class="n">motor</span><span class="o">.</span><span class="n">pop</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">motor</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">poped_motor</span><span class="p">)</span>
</span></span></code></pre></div><pre><code>['ducati', 'yamaha', 'suzuki']
['ducati', 'yamaha']
suzuki
</code></pre>
<p>  This way, you can still use the element you want to delete for the last time.<br>
  This is useful! Watch this example!</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">motor</span> <span class="o">=</span> <span class="p">[</span><span class="s1">&#39;ducati&#39;</span><span class="p">,</span> <span class="s1">&#39;honda&#39;</span><span class="p">,</span> <span class="s1">&#39;yamaha&#39;</span><span class="p">,</span> <span class="s1">&#39;suzuki&#39;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">last_owned</span> <span class="o">=</span> <span class="n">motor</span><span class="o">.</span><span class="n">pop</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="s2">&#34;The last motorcycle I owned was a &#34;</span> <span class="o">+</span> <span class="n">last_owned</span><span class="o">.</span><span class="n">title</span><span class="p">()</span> <span class="o">+</span> <span class="s2">&#34;.&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">motor</span><span class="p">)</span>
</span></span></code></pre></div><pre><code>The last motorcycle I owned was a Suzuki.
['ducati', 'honda', 'yamaha']
</code></pre>
<p>  And pop can be used to pop any element!</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">motor</span> <span class="o">=</span> <span class="p">[</span><span class="s1">&#39;ducati&#39;</span><span class="p">,</span> <span class="s1">&#39;honda&#39;</span><span class="p">,</span> <span class="s1">&#39;yamaha&#39;</span><span class="p">,</span> <span class="s1">&#39;suzuki&#39;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">first_owned</span> <span class="o">=</span> <span class="n">motor</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="s2">&#34;The first motorcycle I owned was a &#34;</span> <span class="o">+</span> <span class="n">first_owned</span><span class="o">.</span><span class="n">title</span><span class="p">()</span> <span class="o">+</span> <span class="s2">&#34;.&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">motor</span><span class="p">)</span>
</span></span></code></pre></div><pre><code>The first motorcycle I owned was a Ducati.
['honda', 'yamaha', 'suzuki']
</code></pre>
<h2 id="007-remove-elements-according-to-its-value">007 Remove Elements According to Its Value</h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">motor</span> <span class="o">=</span> <span class="p">[</span><span class="s1">&#39;ducati&#39;</span><span class="p">,</span> <span class="s1">&#39;honda&#39;</span><span class="p">,</span> <span class="s1">&#39;yamaha&#39;</span><span class="p">,</span> <span class="s1">&#39;suzuki&#39;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">motor</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="s1">&#39;ducati&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">motor</span><span class="p">)</span>
</span></span></code></pre></div><pre><code>['honda', 'yamaha', 'suzuki']
</code></pre>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">motor</span> <span class="o">=</span> <span class="p">[</span><span class="s1">&#39;ducati&#39;</span><span class="p">,</span> <span class="s1">&#39;honda&#39;</span><span class="p">,</span> <span class="s1">&#39;yamaha&#39;</span><span class="p">,</span> <span class="s1">&#39;suzuki&#39;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">too_expensive</span> <span class="o">=</span> <span class="s1">&#39;ducati&#39;</span>
</span></span><span class="line"><span class="cl"><span class="n">motor</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">too_expensive</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">motor</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="s2">&#34;</span><span class="se">\n</span><span class="s2">A &#34;</span> <span class="o">+</span> <span class="n">too_expensive</span><span class="o">.</span><span class="n">title</span><span class="p">()</span> <span class="o">+</span> <span class="s2">&#34; is too expensive for me.&#34;</span><span class="p">)</span>
</span></span></code></pre></div><pre><code>['honda', 'yamaha', 'suzuki']

A Ducati is too expensive for me.
</code></pre>
<h2 id="008-arrange-lists">008 Arrange Lists</h2>
<p>  <em>To Sort Permanently</em></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">cars</span> <span class="o">=</span> <span class="p">[</span><span class="s1">&#39;bmw&#39;</span><span class="p">,</span> <span class="s1">&#39;audi&#39;</span><span class="p">,</span> <span class="s1">&#39;toyota&#39;</span><span class="p">,</span> <span class="s1">&#39;subaru&#39;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="n">cars</span><span class="o">.</span><span class="n">sort</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">cars</span><span class="p">)</span>
</span></span></code></pre></div><pre><code>['audi', 'bmw', 'subaru', 'toyota']
</code></pre>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">cars</span> <span class="o">=</span> <span class="p">[</span><span class="s1">&#39;bmw&#39;</span><span class="p">,</span> <span class="s1">&#39;audi&#39;</span><span class="p">,</span> <span class="s1">&#39;toyota&#39;</span><span class="p">,</span> <span class="s1">&#39;subaru&#39;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="n">cars</span><span class="o">.</span><span class="n">sort</span><span class="p">(</span><span class="n">reverse</span> <span class="o">=</span> <span class="kc">True</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">cars</span><span class="p">)</span>
</span></span></code></pre></div><pre><code>['toyota', 'subaru', 'bmw', 'audi']
</code></pre>
<p>  <em>To Sort Temporarily</em></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">cars</span> <span class="o">=</span> <span class="p">[</span><span class="s1">&#39;bmw&#39;</span><span class="p">,</span> <span class="s1">&#39;audi&#39;</span><span class="p">,</span> <span class="s1">&#39;toyota&#39;</span><span class="p">,</span> <span class="s1">&#39;subaru&#39;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">cars</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="nb">sorted</span><span class="p">(</span><span class="n">cars</span><span class="p">))</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">cars</span><span class="p">)</span>
</span></span></code></pre></div><pre><code>['bmw', 'audi', 'toyota', 'subaru']
['audi', 'bmw', 'subaru', 'toyota']
['bmw', 'audi', 'toyota', 'subaru']
</code></pre>
<p>  <em>To Reverse</em></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">cars</span> <span class="o">=</span> <span class="p">[</span><span class="s1">&#39;bmw&#39;</span><span class="p">,</span> <span class="s1">&#39;audi&#39;</span><span class="p">,</span> <span class="s1">&#39;toyota&#39;</span><span class="p">,</span> <span class="s1">&#39;subaru&#39;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">cars</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">cars</span><span class="o">.</span><span class="n">reverse</span><span class="p">()</span> <span class="c1">#don&#39;t forget the &#34;()&#34;!</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">cars</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">cars</span><span class="o">.</span><span class="n">reverse</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">cars</span><span class="p">)</span>
</span></span></code></pre></div><pre><code>['bmw', 'audi', 'toyota', 'subaru']
['subaru', 'toyota', 'audi', 'bmw']
['bmw', 'audi', 'toyota', 'subaru']
</code></pre>
<p>  <em>To Confirm the Length</em></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">cars</span> <span class="o">=</span> <span class="p">[</span><span class="s1">&#39;bmw&#39;</span><span class="p">,</span> <span class="s1">&#39;audi&#39;</span><span class="p">,</span> <span class="s1">&#39;toyota&#39;</span><span class="p">,</span> <span class="s1">&#39;subaru&#39;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="nb">len</span><span class="p">(</span><span class="n">cars</span><span class="p">)</span>
</span></span></code></pre></div><pre><code>4
</code></pre>
<hr>
<!-- raw HTML omitted -->
<h1 id="chapter-4-operate-the-list">Chapter 4 Operate the List</h1>
<h2 id="001-for-loop">001 For: Loop</h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">magicians</span> <span class="o">=</span> <span class="p">[</span><span class="s1">&#39;alice&#39;</span><span class="p">,</span> <span class="s1">&#39;david&#39;</span><span class="p">,</span> <span class="s1">&#39;carolina&#39;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="k">for</span> <span class="n">magician</span> <span class="ow">in</span> <span class="n">magicians</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="n">magician</span><span class="o">.</span><span class="n">title</span><span class="p">()</span> <span class="o">+</span> <span class="s2">&#34;, that was a great trick!&#34;</span><span class="p">)</span>
</span></span></code></pre></div><pre><code>Alice, that was a great trick!
David, that was a great trick!
Carolina, that was a great trick!
</code></pre>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">magicians</span> <span class="o">=</span> <span class="p">[</span><span class="s1">&#39;alice&#39;</span><span class="p">,</span> <span class="s1">&#39;david&#39;</span><span class="p">,</span> <span class="s1">&#39;carolina&#39;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="k">for</span> <span class="n">magician</span> <span class="ow">in</span> <span class="n">magicians</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="n">magician</span><span class="o">.</span><span class="n">title</span><span class="p">()</span> <span class="o">+</span> <span class="s2">&#34;, that was a great trick!&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;I can&#39;t wait to see your next trick, &#34;</span> <span class="o">+</span> <span class="n">magician</span><span class="o">.</span><span class="n">title</span><span class="p">()</span> <span class="o">+</span> <span class="s2">&#34;.</span><span class="se">\n</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span></code></pre></div><pre><code>Alice, that was a great trick!
I can't wait to see your next trick, Alice.

David, that was a great trick!
I can't wait to see your next trick, David.

Carolina, that was a great trick!
I can't wait to see your next trick, Carolina.
</code></pre>
<p>​</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">magicians</span> <span class="o">=</span> <span class="p">[</span><span class="s1">&#39;alice&#39;</span><span class="p">,</span> <span class="s1">&#39;david&#39;</span><span class="p">,</span> <span class="s1">&#39;carolina&#39;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="k">for</span> <span class="n">magician</span> <span class="ow">in</span> <span class="n">magicians</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="n">magician</span><span class="o">.</span><span class="n">title</span><span class="p">()</span> <span class="o">+</span> <span class="s2">&#34;, that was a great trick!&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;I can&#39;t wait to see your next trick, &#34;</span> <span class="o">+</span> <span class="n">magician</span><span class="o">.</span><span class="n">title</span><span class="p">()</span> <span class="o">+</span> <span class="s2">&#34;.</span><span class="se">\n</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="s2">&#34;Thank you, all!&#34;</span><span class="p">)</span>
</span></span></code></pre></div><pre><code>Alice, that was a great trick!
I can't wait to see your next trick, Alice.

David, that was a great trick!
I can't wait to see your next trick, David.

Carolina, that was a great trick!
I can't wait to see your next trick, Carolina.

Thank you, all!
</code></pre>
<p>  As you can see, <strong>indent</strong> is very important in Python. It can decide whether your program will be running properly.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">magicians</span> <span class="o">=</span> <span class="p">[</span><span class="s1">&#39;alice&#39;</span><span class="p">,</span> <span class="s1">&#39;david&#39;</span><span class="p">,</span> <span class="s1">&#39;carolina&#39;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="k">for</span> <span class="n">magician</span> <span class="ow">in</span> <span class="n">magicians</span><span class="p">:</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">magician</span><span class="o">.</span><span class="n">title</span><span class="p">()</span> <span class="o">+</span> <span class="s2">&#34;, that was a great trick!&#34;</span><span class="p">)</span>
</span></span></code></pre></div><pre><code>  File &quot;&lt;ipython-input-32-f0b382b2b777&gt;&quot;, line 3
    print(magician.title() + &quot;, that was a great trick!&quot;)
        ^
IndentationError: expected an indented block
</code></pre>
<p>  <em>See? An error occured when you don&rsquo;t indent the code!</em></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">msg</span> <span class="o">=</span> <span class="s2">&#34;hello&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="n">msg</span><span class="p">)</span>
</span></span></code></pre></div><p>  <em>Errors also occur when there&rsquo;s an unnecessary indent!</em></p>
<!-- raw HTML omitted -->
<h2 id="002-use-a-number-as-the-loop-control-variable">002 Use A Number As the Loop Control Variable</h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">for</span> <span class="n">value</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="mi">6</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="n">value</span><span class="p">)</span>
</span></span></code></pre></div><p>  <em><code>range()</code> stops when <code>value</code> reaches 6, which means after 5 is printed and <code>value</code> has been 6, the program will stop.</em></p>
<p>  And <code>range()</code> has other ways to use.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">numbers</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="mi">6</span><span class="p">))</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">numbers</span><span class="p">)</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">odd_numbers</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="mi">11</span><span class="p">,</span><span class="mi">2</span><span class="p">))</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">odd_numbers</span><span class="p">)</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">squares</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="cl"><span class="k">for</span> <span class="n">value</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="mi">11</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="n">squares</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">value</span><span class="o">**</span><span class="mi">2</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">squares</span><span class="p">)</span>
</span></span></code></pre></div><!-- raw HTML omitted -->
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">digits</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="nb">range</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">10</span><span class="p">))</span>
</span></span><span class="line"><span class="cl"><span class="nb">min</span><span class="p">(</span><span class="n">digits</span><span class="p">)</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="nb">max</span><span class="p">(</span><span class="n">digits</span><span class="p">)</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="nb">sum</span><span class="p">(</span><span class="n">digits</span><span class="p">)</span>
</span></span></code></pre></div><!-- raw HTML omitted -->
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">squares</span> <span class="o">=</span> <span class="p">[</span><span class="n">value</span><span class="o">**</span><span class="mi">2</span> <span class="k">for</span> <span class="n">value</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="mi">11</span><span class="p">)]</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">squares</span><span class="p">)</span>
</span></span></code></pre></div><!-- raw HTML omitted -->
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">players</span> <span class="o">=</span> <span class="p">[</span><span class="s1">&#39;charles&#39;</span><span class="p">,</span> <span class="s1">&#39;martina&#39;</span><span class="p">,</span> <span class="s1">&#39;micheal&#39;</span><span class="p">,</span> <span class="s1">&#39;florence&#39;</span><span class="p">,</span> <span class="s1">&#39;eli&#39;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">players</span><span class="p">[</span><span class="mi">0</span><span class="p">:</span><span class="mi">3</span><span class="p">])</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">players</span> <span class="o">=</span> <span class="p">[</span><span class="s1">&#39;charles&#39;</span><span class="p">,</span> <span class="s1">&#39;martina&#39;</span><span class="p">,</span> <span class="s1">&#39;micheal&#39;</span><span class="p">,</span> <span class="s1">&#39;florence&#39;</span><span class="p">,</span> <span class="s1">&#39;eli&#39;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">players</span><span class="p">[</span><span class="mi">1</span><span class="p">:</span><span class="mi">4</span><span class="p">])</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">players</span> <span class="o">=</span> <span class="p">[</span><span class="s1">&#39;charles&#39;</span><span class="p">,</span> <span class="s1">&#39;martina&#39;</span><span class="p">,</span> <span class="s1">&#39;micheal&#39;</span><span class="p">,</span> <span class="s1">&#39;florence&#39;</span><span class="p">,</span> <span class="s1">&#39;eli&#39;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">players</span><span class="p">[:</span><span class="mi">4</span><span class="p">])</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">players</span> <span class="o">=</span> <span class="p">[</span><span class="s1">&#39;charles&#39;</span><span class="p">,</span> <span class="s1">&#39;martina&#39;</span><span class="p">,</span> <span class="s1">&#39;micheal&#39;</span><span class="p">,</span> <span class="s1">&#39;florence&#39;</span><span class="p">,</span> <span class="s1">&#39;eli&#39;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">players</span><span class="p">[</span><span class="mi">2</span><span class="p">:])</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">players</span> <span class="o">=</span> <span class="p">[</span><span class="s1">&#39;charles&#39;</span><span class="p">,</span> <span class="s1">&#39;martina&#39;</span><span class="p">,</span> <span class="s1">&#39;micheal&#39;</span><span class="p">,</span> <span class="s1">&#39;florence&#39;</span><span class="p">,</span> <span class="s1">&#39;eli&#39;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">players</span><span class="p">[</span><span class="o">-</span><span class="mi">3</span><span class="p">:])</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">players</span> <span class="o">=</span> <span class="p">[</span><span class="s1">&#39;charles&#39;</span><span class="p">,</span> <span class="s1">&#39;martina&#39;</span><span class="p">,</span> <span class="s1">&#39;micheal&#39;</span><span class="p">,</span> <span class="s1">&#39;florence&#39;</span><span class="p">,</span> <span class="s1">&#39;eli&#39;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="s2">&#34;Here are the first three players on my team:&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="k">for</span> <span class="n">player</span> <span class="ow">in</span> <span class="n">players</span><span class="p">[:</span><span class="mi">3</span><span class="p">]:</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="n">player</span><span class="o">.</span><span class="n">title</span><span class="p">())</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">my_foods</span> <span class="o">=</span> <span class="p">[</span><span class="s1">&#39;pizza&#39;</span><span class="p">,</span> <span class="s1">&#39;falafel&#39;</span><span class="p">,</span> <span class="s1">&#39;carrot cake&#39;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="n">friend_foods</span> <span class="o">=</span> <span class="n">my_foods</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="s2">&#34;My favorite foods are:&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">my_foods</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="s2">&#34;</span><span class="se">\n</span><span class="s2">Myfriend&#39;s favorite foods are:&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">friend_foods</span><span class="p">)</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">my_foods</span> <span class="o">=</span> <span class="p">[</span><span class="s1">&#39;pizza&#39;</span><span class="p">,</span> <span class="s1">&#39;falafel&#39;</span><span class="p">,</span> <span class="s1">&#39;carrot cake&#39;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="n">friend_foods</span> <span class="o">=</span> <span class="n">my_foods</span><span class="p">[:]</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="s2">&#34;My favorite foods are:&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">my_foods</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="s2">&#34;</span><span class="se">\n</span><span class="s2">Myfriend&#39;s favorite foods are:&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">friend_foods</span><span class="p">)</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">my_foods</span> <span class="o">=</span> <span class="p">[</span><span class="s1">&#39;pizza&#39;</span><span class="p">,</span> <span class="s1">&#39;falafel&#39;</span><span class="p">,</span> <span class="s1">&#39;carrot cake&#39;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="n">friend_foods</span> <span class="o">=</span> <span class="n">my_foods</span><span class="p">[:]</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">my_foods</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s1">&#39;cannoli&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">friend_foods</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s1">&#39;ice cream&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="s2">&#34;My favorite foods are:&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">my_foods</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="s2">&#34;</span><span class="se">\n</span><span class="s2">Myfriend&#39;s favorite foods are:&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">friend_foods</span><span class="p">)</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">my_foods</span> <span class="o">=</span> <span class="p">[</span><span class="s1">&#39;pizza&#39;</span><span class="p">,</span> <span class="s1">&#39;falafel&#39;</span><span class="p">,</span> <span class="s1">&#39;carrot cake&#39;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="n">friend_foods</span> <span class="o">=</span> <span class="n">my_foods</span>
</span></span><span class="line"><span class="cl"><span class="c1"># Not Workable</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">my_foods</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s1">&#39;cannoli&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">friend_foods</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s1">&#39;ice cream&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="s2">&#34;My favorite foods are:&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">my_foods</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="s2">&#34;</span><span class="se">\n</span><span class="s2">Myfriend&#39;s favorite foods are:&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">friend_foods</span><span class="p">)</span>
</span></span></code></pre></div><p>  <em>Mind the tiny difference between the two codes.</em>
<!-- raw HTML omitted -->  <em>Though they look similar, the results are totally different!</em></p>
<!-- raw HTML omitted -->
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">dimensions</span> <span class="o">=</span> <span class="p">(</span><span class="mi">200</span><span class="p">,</span> <span class="mi">50</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">dimensions</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">dimensions</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span>
</span></span></code></pre></div><p>  <em>Edting the elements in a tuple is illegal!</em></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">dimensions</span> <span class="o">=</span> <span class="p">(</span><span class="mi">200</span><span class="p">,</span> <span class="mi">50</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">dimensions</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="mi">250</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">dimensions</span> <span class="o">=</span> <span class="p">(</span><span class="mi">200</span><span class="p">,</span> <span class="mi">50</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="k">for</span> <span class="n">dimension</span> <span class="ow">in</span> <span class="n">dimensions</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="n">dimension</span><span class="p">)</span>
</span></span></code></pre></div><pre><code>200
50
</code></pre>
<p>  <em>However, assigning <strong>the whole tuple</strong> is allowed!</em></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">dimensions</span> <span class="o">=</span> <span class="p">(</span><span class="mi">200</span><span class="p">,</span> <span class="mi">50</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="s2">&#34;origin:&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">dimensions</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">dimensions</span> <span class="o">=</span> <span class="p">(</span><span class="mi">400</span><span class="p">,</span> <span class="mi">100</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="s2">&#34;modified:&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">dimensions</span><span class="p">)</span>
</span></span></code></pre></div><pre><code>origin:
(200, 50)
modified:
(400, 100)
</code></pre>
<h2 id="005-pep-8">005 PEP 8</h2>
<p>  Check <a href="https://www.python.org/dev/peps/pep-0008/">Here</a> for more details.
<!-- raw HTML omitted -->  https://www.python.org/dev/peps/pep-0008/</p>
<hr>
<h1 id="chapter-5-if-statement">Chapter 5 If Statement</h1>
<h2 id="001-simple-example">001 Simple Example</h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">cars</span> <span class="o">=</span> <span class="p">[</span><span class="s1">&#39;audi&#39;</span><span class="p">,</span> <span class="s1">&#39;bmw&#39;</span><span class="p">,</span> <span class="s1">&#39;subaru&#39;</span><span class="p">,</span> <span class="s1">&#39;toyota&#39;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">for</span> <span class="n">car</span> <span class="ow">in</span> <span class="n">cars</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="n">car</span> <span class="o">==</span> <span class="s1">&#39;bmw&#39;</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="n">car</span><span class="o">.</span><span class="n">upper</span><span class="p">())</span>
</span></span><span class="line"><span class="cl">    <span class="k">else</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="n">car</span><span class="o">.</span><span class="n">title</span><span class="p">())</span>
</span></span></code></pre></div><pre><code>Audi
BMW
Subaru
Toyota
</code></pre>
<h2 id="002-condition-testing">002 Condition Testing</h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">car</span> <span class="o">=</span> <span class="s1">&#39;bmw&#39;</span>
</span></span><span class="line"><span class="cl"><span class="n">car</span> <span class="o">==</span> <span class="s1">&#39;bmw&#39;</span>
</span></span></code></pre></div><pre><code>True
</code></pre>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">car</span> <span class="o">=</span> <span class="s1">&#39;bmw&#39;</span>
</span></span><span class="line"><span class="cl"><span class="n">car</span> <span class="o">==</span> <span class="s1">&#39;audi&#39;</span>
</span></span></code></pre></div><pre><code>False
</code></pre>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">car</span> <span class="o">=</span> <span class="s1">&#39;Audi&#39;</span>
</span></span><span class="line"><span class="cl"><span class="n">car</span> <span class="o">==</span> <span class="s1">&#39;audi&#39;</span>
</span></span></code></pre></div><pre><code>False
</code></pre>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">car</span> <span class="o">=</span> <span class="s1">&#39;Audi&#39;</span>
</span></span><span class="line"><span class="cl"><span class="n">car</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span> <span class="o">==</span> <span class="s1">&#39;audi&#39;</span>
</span></span></code></pre></div><pre><code>True
</code></pre>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">car</span> <span class="o">=</span> <span class="s1">&#39;Audi&#39;</span>
</span></span><span class="line"><span class="cl"><span class="n">car</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span> <span class="o">==</span> <span class="s1">&#39;audi&#39;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">car</span>
</span></span></code></pre></div><pre><code>'Audi'
</code></pre>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">car</span> <span class="o">=</span> <span class="s1">&#39;Audi&#39;</span>
</span></span><span class="line"><span class="cl"><span class="n">car</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span> <span class="o">==</span> <span class="s1">&#39;auDi&#39;</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span>
</span></span></code></pre></div><pre><code>True
</code></pre>
<p>  <em><code>!=</code> is availiable, too!</em></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">str1</span> <span class="o">=</span> <span class="s1">&#39;hello&#39;</span>
</span></span><span class="line"><span class="cl"><span class="n">str2</span> <span class="o">=</span> <span class="s1">&#39;hel&#39;</span>
</span></span><span class="line"><span class="cl"><span class="n">str1</span> <span class="o">!=</span> <span class="n">str2</span>
</span></span></code></pre></div><pre><code>True
</code></pre>
<p>  <em>Numbers are workable, too!</em></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">age</span> <span class="o">=</span> <span class="mi">18</span>
</span></span><span class="line"><span class="cl"><span class="n">age</span> <span class="o">==</span> <span class="mi">18</span>
</span></span></code></pre></div><pre><code>True
</code></pre>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">age</span> <span class="o">&gt;=</span> <span class="mi">18</span>
</span></span></code></pre></div><pre><code>True
</code></pre>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">age</span> <span class="o">&gt;</span> <span class="mi">17</span>
</span></span></code></pre></div><pre><code>True
</code></pre>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">age</span> <span class="o">&gt;</span> <span class="mi">16</span> <span class="ow">and</span> <span class="n">age</span> <span class="o">&lt;</span> <span class="mi">19</span>
</span></span></code></pre></div><pre><code>True
</code></pre>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="p">(</span><span class="n">age</span> <span class="o">&gt;</span> <span class="mi">16</span><span class="p">)</span> <span class="ow">and</span> <span class="p">(</span><span class="n">age</span> <span class="o">&lt;</span> <span class="mi">19</span><span class="p">)</span>
</span></span></code></pre></div><pre><code>True
</code></pre>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="p">(</span><span class="n">age</span> <span class="o">&lt;</span> <span class="mi">16</span><span class="p">)</span> <span class="ow">or</span> <span class="p">(</span><span class="n">age</span> <span class="o">!=</span> <span class="mi">17</span><span class="p">)</span>
</span></span></code></pre></div><pre><code>True
</code></pre>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">requested_toppings</span> <span class="o">=</span> <span class="p">[</span><span class="s1">&#39;mushrooms&#39;</span><span class="p">,</span> <span class="s1">&#39;onions&#39;</span><span class="p">,</span> <span class="s1">&#39;pineapple&#39;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="s1">&#39;mushrooms&#39;</span> <span class="ow">in</span> <span class="n">requested_toppings</span>
</span></span></code></pre></div><pre><code>True
</code></pre>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="s1">&#39;apple&#39;</span> <span class="ow">in</span> <span class="n">requested_toppings</span>
</span></span></code></pre></div><pre><code>False
</code></pre>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">bool1</span> <span class="o">=</span> <span class="kc">True</span>
</span></span><span class="line"><span class="cl"><span class="n">bool2</span> <span class="o">=</span> <span class="kc">False</span>
</span></span><span class="line"><span class="cl"><span class="n">bool1</span> <span class="ow">and</span> <span class="n">bool2</span>
</span></span></code></pre></div><pre><code>False
</code></pre>
<h2 id="003-if-statement">003 If Statement</h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">age</span> <span class="o">=</span> <span class="mi">12</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="n">age</span> <span class="o">&lt;</span> <span class="mi">4</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="k">elif</span> <span class="n">age</span> <span class="o">&lt;</span> <span class="mi">18</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="k">elif</span> <span class="n">age</span> <span class="o">&gt;</span> <span class="mi">65</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="mi">3</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="k">else</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="mi">4</span><span class="p">)</span>
</span></span></code></pre></div><pre><code>2
</code></pre>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">age</span> <span class="o">=</span> <span class="mi">1</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="n">age</span> <span class="o">&lt;</span> <span class="mi">4</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="k">elif</span> <span class="n">age</span> <span class="o">&lt;</span> <span class="mi">18</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="k">elif</span> <span class="n">age</span> <span class="o">&gt;</span> <span class="mi">65</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="mi">3</span><span class="p">)</span>
</span></span></code></pre></div><pre><code>1
</code></pre>
<h2 id="004-combination">004 Combination</h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">requested_toppings</span> <span class="o">=</span> <span class="p">[</span><span class="s1">&#39;mushrooms&#39;</span><span class="p">,</span> <span class="s1">&#39;green peppers&#39;</span><span class="p">,</span> <span class="s1">&#39;extra cheese&#39;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">for</span> <span class="n">requested_topping</span> <span class="ow">in</span> <span class="n">requested_toppings</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="n">requested_topping</span> <span class="o">==</span> <span class="s1">&#39;green peppers&#39;</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;Sorry, we ran out of &#34;</span> <span class="o">+</span> <span class="n">requested_topping</span> <span class="o">+</span> <span class="s2">&#34;.&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="k">else</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;Adding &#34;</span> <span class="o">+</span> <span class="n">requested_topping</span> <span class="o">+</span> <span class="s2">&#34;.&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="s2">&#34;Finished!&#34;</span><span class="p">)</span>
</span></span></code></pre></div><pre><code>Adding mushrooms.
Sorry, we ran out of green peppers.
Adding extra cheese.
Finished!
</code></pre>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">requested_toppings</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="n">requested_toppings</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="n">requested_topping</span> <span class="ow">in</span> <span class="n">requested_toppings</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="n">requested_topping</span> <span class="o">==</span> <span class="s1">&#39;green peppers&#39;</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;Sorry, we ran out of &#34;</span> <span class="o">+</span> <span class="n">requested_topping</span> <span class="o">+</span> <span class="s2">&#34;.&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="k">else</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;Adding &#34;</span> <span class="o">+</span> <span class="n">requested_topping</span> <span class="o">+</span> <span class="s2">&#34;.&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="k">else</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;You want a plain pizza?&#34;</span><span class="p">)</span>
</span></span></code></pre></div><pre><code>You want a plain pizza?
</code></pre>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">available_toppings</span> <span class="o">=</span> <span class="p">[</span><span class="s1">&#39;mushrooms&#39;</span><span class="p">,</span> <span class="s1">&#39;extra cheese&#39;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="n">requested_toppings</span> <span class="o">=</span> <span class="p">[</span><span class="s1">&#39;mushrooms&#39;</span><span class="p">,</span> <span class="s1">&#39;green peppers&#39;</span><span class="p">,</span> <span class="s1">&#39;extra cheese&#39;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="n">requested_toppings</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="n">requested_topping</span> <span class="ow">in</span> <span class="n">requested_toppings</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="n">requested_topping</span> <span class="ow">in</span> <span class="n">available_toppings</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;Adding &#34;</span> <span class="o">+</span> <span class="n">requested_topping</span> <span class="o">+</span> <span class="s2">&#34;.&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="k">else</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;Sorry, we ran out of &#34;</span> <span class="o">+</span> <span class="n">requested_topping</span> <span class="o">+</span> <span class="s2">&#34;.&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="k">else</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;You want a plain pizza?&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="s2">&#34;</span><span class="se">\n</span><span class="s2">Finished!&#34;</span><span class="p">)</span>
</span></span></code></pre></div><pre><code>Adding mushrooms.
Sorry, we ran out of green peppers.
Adding extra cheese.

Finished!
</code></pre>
<!-- raw HTML omitted -->
<hr>
<h1 id="chapter-6-dictionary">Chapter 6 Dictionary</h1>
<h2 id="001-a-simple-example">001 A Simple Example</h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">alien_0</span> <span class="o">=</span> <span class="p">{</span><span class="s1">&#39;color&#39;</span> <span class="p">:</span> <span class="s1">&#39;green&#39;</span><span class="p">,</span> <span class="s1">&#39;points&#39;</span> <span class="p">:</span> <span class="mi">5</span><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">alien_0</span><span class="p">[</span><span class="s1">&#39;color&#39;</span><span class="p">])</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">alien_0</span><span class="p">[</span><span class="s1">&#39;points&#39;</span><span class="p">])</span>
</span></span></code></pre></div><pre><code>green
5
</code></pre>
<p>  A dictionary is a series of &ldquo;key = value&rdquo;.<!-- raw HTML omitted -->
  <em>In this case, &lsquo;color&rsquo; and &lsquo;points&rsquo; are two keys, and &lsquo;green&rsquo; and 5 are two values.</em></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">alien_0</span> <span class="o">=</span> <span class="p">{</span><span class="s1">&#39;color&#39;</span> <span class="p">:</span> <span class="s1">&#39;green&#39;</span><span class="p">,</span> <span class="s1">&#39;points&#39;</span> <span class="p">:</span> <span class="mi">5</span><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">color_0</span> <span class="o">=</span> <span class="n">alien_0</span><span class="p">[</span><span class="s1">&#39;color&#39;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="s1">&#39;The color is &#39;</span> <span class="o">+</span> <span class="n">color_0</span> <span class="o">+</span> <span class="s1">&#39;.&#39;</span><span class="p">)</span>
</span></span></code></pre></div><pre><code>The color is green.
</code></pre>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">alien_0</span> <span class="o">=</span> <span class="p">{</span><span class="s1">&#39;color&#39;</span> <span class="p">:</span> <span class="s1">&#39;green&#39;</span><span class="p">,</span> <span class="s1">&#39;points&#39;</span> <span class="p">:</span> <span class="mi">5</span><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="s1">&#39;The color is &#39;</span> <span class="o">+</span> <span class="n">alien_0</span><span class="p">[</span><span class="s1">&#39;color&#39;</span><span class="p">]</span> <span class="o">+</span> <span class="s1">&#39;.&#39;</span><span class="p">)</span>
</span></span></code></pre></div><pre><code>The color is green.
</code></pre>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">alien_0</span> <span class="o">=</span> <span class="p">{</span><span class="s1">&#39;color&#39;</span> <span class="p">:</span> <span class="s1">&#39;green&#39;</span><span class="p">,</span> <span class="s1">&#39;points&#39;</span> <span class="p">:</span> <span class="mi">5</span><span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">alien_0</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">alien_0</span><span class="p">[</span><span class="s1">&#39;x_position&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span>
</span></span><span class="line"><span class="cl"><span class="n">alien_0</span><span class="p">[</span><span class="s1">&#39;y_position&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="mi">25</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">alien_0</span><span class="p">)</span>
</span></span></code></pre></div><pre><code>{'color': 'green', 'points': 5}
{'color': 'green', 'points': 5, 'x_position': 0, 'y_position': 25}
</code></pre>
<p>  <em><strong>You can create an empty dictionary for convenience, just like you have done for lists.</strong></em></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">alien_0</span> <span class="o">=</span> <span class="p">{}</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">alien_0</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">alien_0</span><span class="p">[</span><span class="s1">&#39;color&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s1">&#39;green&#39;</span>
</span></span><span class="line"><span class="cl"><span class="n">alien_0</span><span class="p">[</span><span class="s1">&#39;points&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="mi">5</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">alien_0</span><span class="p">)</span>
</span></span></code></pre></div><pre><code>{}
{'color': 'green', 'points': 5}
</code></pre>
<h2 id="002-modification-and-deletion">002 Modification and Deletion</h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">alien_0</span> <span class="o">=</span> <span class="p">{</span><span class="s1">&#39;color&#39;</span> <span class="p">:</span> <span class="s1">&#39;green&#39;</span><span class="p">,</span> <span class="s1">&#39;points&#39;</span> <span class="p">:</span> <span class="mi">5</span><span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">alien_0</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">alien_0</span><span class="p">[</span><span class="s1">&#39;color&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s1">&#39;yellow&#39;</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">alien_0</span><span class="p">)</span>
</span></span></code></pre></div><pre><code>{'color': 'green', 'points': 5}
{'color': 'yellow', 'points': 5}
</code></pre>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">alien_0</span> <span class="o">=</span> <span class="p">{</span><span class="s1">&#39;color&#39;</span> <span class="p">:</span> <span class="s1">&#39;green&#39;</span><span class="p">,</span> <span class="s1">&#39;points&#39;</span> <span class="p">:</span> <span class="mi">5</span><span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">alien_0</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">del</span> <span class="n">alien_0</span><span class="p">[</span><span class="s1">&#39;points&#39;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">alien_0</span><span class="p">)</span>
</span></span></code></pre></div><pre><code>{'color': 'green', 'points': 5}
{'color': 'green'}
</code></pre>
<p>  <em><strong>Code Standards For Long Statements</strong></em></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">favorite_languages</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;jen&#39;</span> <span class="p">:</span> <span class="s1">&#39;python&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;sarah&#39;</span> <span class="p">:</span> <span class="s1">&#39;C&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;edward&#39;</span> <span class="p">:</span> <span class="s1">&#39;ruby&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;phil&#39;</span> <span class="p">:</span> <span class="s1">&#39;python&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="s2">&#34;Sarah&#39;s favorite language is &#34;</span> <span class="o">+</span> 
</span></span><span class="line"><span class="cl">     <span class="n">favorite_languages</span><span class="p">[</span><span class="s1">&#39;sarah&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">title</span><span class="p">()</span> <span class="o">+</span> 
</span></span><span class="line"><span class="cl">     <span class="s1">&#39;.&#39;</span><span class="p">)</span>
</span></span></code></pre></div><pre><code>Sarah's favorite language is C.
</code></pre>
<h2 id="003-traverse-a-dictionary">003 Traverse A Dictionary</h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">user_0</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;username&#39;</span> <span class="p">:</span> <span class="s1">&#39;efermi&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;first&#39;</span> <span class="p">:</span> <span class="s1">&#39;enrico&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;last&#39;</span> <span class="p">:</span> <span class="s1">&#39;fermi&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">for</span> <span class="n">key</span><span class="p">,</span> <span class="n">value</span> <span class="ow">in</span> <span class="n">user_0</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;</span><span class="se">\n</span><span class="s2">Key: &#34;</span> <span class="o">+</span> <span class="n">key</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;Value: &#34;</span> <span class="o">+</span> <span class="n">value</span><span class="p">)</span>
</span></span></code></pre></div><pre><code>Key: username
Value: efermi

Key: first
Value: enrico

Key: last
Value: fermi
</code></pre>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">favorite_languages</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;jen&#39;</span> <span class="p">:</span> <span class="s1">&#39;python&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;sarah&#39;</span> <span class="p">:</span> <span class="s1">&#39;C&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;edward&#39;</span> <span class="p">:</span> <span class="s1">&#39;ruby&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;phil&#39;</span> <span class="p">:</span> <span class="s1">&#39;python&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">for</span> <span class="n">name</span><span class="p">,</span> <span class="n">language</span> <span class="ow">in</span> <span class="n">favorite_languages</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="n">name</span><span class="o">.</span><span class="n">title</span><span class="p">()</span> <span class="o">+</span> <span class="s2">&#34;&#39;s favortie language is &#34;</span> <span class="o">+</span>
</span></span><span class="line"><span class="cl">         <span class="n">language</span><span class="o">.</span><span class="n">title</span><span class="p">()</span> <span class="o">+</span> <span class="s2">&#34;.&#34;</span><span class="p">)</span>
</span></span></code></pre></div><pre><code>Jen's favortie language is Python.
Sarah's favortie language is C.
Edward's favortie language is Ruby.
Phil's favortie language is Python.
</code></pre>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">favorite_languages</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;jen&#39;</span> <span class="p">:</span> <span class="s1">&#39;python&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;sarah&#39;</span> <span class="p">:</span> <span class="s1">&#39;C&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;edward&#39;</span> <span class="p">:</span> <span class="s1">&#39;ruby&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;phil&#39;</span> <span class="p">:</span> <span class="s1">&#39;python&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">for</span> <span class="n">name</span> <span class="ow">in</span> <span class="n">favorite_languages</span><span class="o">.</span><span class="n">keys</span><span class="p">():</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="n">name</span><span class="o">.</span><span class="n">title</span><span class="p">())</span>
</span></span></code></pre></div><pre><code>Jen
Sarah
Edward
Phil
</code></pre>
<p>  <em><strong>In fact, <code>.keys()</code> can be omitted.</strong></em></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">favorite_languages</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;jen&#39;</span> <span class="p">:</span> <span class="s1">&#39;python&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;sarah&#39;</span> <span class="p">:</span> <span class="s1">&#39;C&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;edward&#39;</span> <span class="p">:</span> <span class="s1">&#39;ruby&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;phil&#39;</span> <span class="p">:</span> <span class="s1">&#39;python&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">for</span> <span class="n">name</span> <span class="ow">in</span> <span class="n">favorite_languages</span><span class="p">:</span> <span class="c1">#mind here!</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="n">name</span><span class="o">.</span><span class="n">title</span><span class="p">())</span>
</span></span></code></pre></div><pre><code>Jen
Sarah
Edward
Phil
</code></pre>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">favorite_languages</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;jen&#39;</span> <span class="p">:</span> <span class="s1">&#39;python&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;sarah&#39;</span> <span class="p">:</span> <span class="s1">&#39;C&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;edward&#39;</span> <span class="p">:</span> <span class="s1">&#39;ruby&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;phil&#39;</span> <span class="p">:</span> <span class="s1">&#39;python&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">friends</span> <span class="o">=</span> <span class="p">[</span><span class="s1">&#39;phil&#39;</span><span class="p">,</span> <span class="s1">&#39;sarah&#39;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="k">for</span> <span class="n">name</span> <span class="ow">in</span> <span class="n">favorite_languages</span><span class="o">.</span><span class="n">keys</span><span class="p">():</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="n">name</span><span class="o">.</span><span class="n">title</span><span class="p">())</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="n">name</span> <span class="ow">in</span> <span class="n">friends</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="s2">&#34; Hi! &#34;</span> <span class="o">+</span> <span class="n">name</span><span class="o">.</span><span class="n">title</span><span class="p">()</span> <span class="o">+</span> 
</span></span><span class="line"><span class="cl">              <span class="s2">&#34;, I see your favorite language is &#34;</span> <span class="o">+</span>
</span></span><span class="line"><span class="cl">             <span class="n">favorite_languages</span><span class="p">[</span><span class="n">name</span><span class="p">]</span><span class="o">.</span><span class="n">title</span><span class="p">()</span> <span class="o">+</span> <span class="s2">&#34;!&#34;</span><span class="p">)</span>
</span></span></code></pre></div><pre><code>Jen
Sarah
 Hi! Sarah, I see your favorite language is C!
Edward
Phil
 Hi! Phil, I see your favorite language is Python!
</code></pre>
<p>  <em><strong>This is how <code>.keys()</code> actually works.</strong></em></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">favorite_languages</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;jen&#39;</span> <span class="p">:</span> <span class="s1">&#39;python&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;sarah&#39;</span> <span class="p">:</span> <span class="s1">&#39;C&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;edward&#39;</span> <span class="p">:</span> <span class="s1">&#39;ruby&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;phil&#39;</span> <span class="p">:</span> <span class="s1">&#39;python&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">favorite_languages</span><span class="o">.</span><span class="n">keys</span><span class="p">()</span>
</span></span></code></pre></div><pre><code>dict_keys(['jen', 'sarah', 'edward', 'phil'])
</code></pre>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">favorite_languages</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;jen&#39;</span> <span class="p">:</span> <span class="s1">&#39;python&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;sarah&#39;</span> <span class="p">:</span> <span class="s1">&#39;C&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;edward&#39;</span> <span class="p">:</span> <span class="s1">&#39;ruby&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;phil&#39;</span> <span class="p">:</span> <span class="s1">&#39;python&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="s1">&#39;erin&#39;</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">favorite_languages</span><span class="o">.</span><span class="n">keys</span><span class="p">():</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;Erin, please take our poll!&#34;</span><span class="p">)</span>
</span></span></code></pre></div><pre><code>Erin, please take our poll!
</code></pre>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">favorite_languages</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;jen&#39;</span> <span class="p">:</span> <span class="s1">&#39;python&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;sarah&#39;</span> <span class="p">:</span> <span class="s1">&#39;C&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;edward&#39;</span> <span class="p">:</span> <span class="s1">&#39;ruby&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;phil&#39;</span> <span class="p">:</span> <span class="s1">&#39;python&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">for</span> <span class="n">name</span> <span class="ow">in</span> <span class="nb">sorted</span><span class="p">(</span><span class="n">favorite_languages</span><span class="o">.</span><span class="n">keys</span><span class="p">()):</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="n">name</span><span class="o">.</span><span class="n">title</span><span class="p">())</span>
</span></span></code></pre></div><pre><code>Edward
Jen
Phil
Sarah
</code></pre>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">favorite_languages</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;jen&#39;</span> <span class="p">:</span> <span class="s1">&#39;python&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;sarah&#39;</span> <span class="p">:</span> <span class="s1">&#39;C&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;edward&#39;</span> <span class="p">:</span> <span class="s1">&#39;ruby&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;phil&#39;</span> <span class="p">:</span> <span class="s1">&#39;python&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">favorite_languages</span><span class="o">.</span><span class="n">values</span><span class="p">()</span>
</span></span></code></pre></div><pre><code>dict_values(['python', 'C', 'ruby', 'python'])
</code></pre>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">favorite_languages</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;jen&#39;</span> <span class="p">:</span> <span class="s1">&#39;python&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;sarah&#39;</span> <span class="p">:</span> <span class="s1">&#39;C&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;edward&#39;</span> <span class="p">:</span> <span class="s1">&#39;ruby&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;phil&#39;</span> <span class="p">:</span> <span class="s1">&#39;python&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nb">set</span><span class="p">(</span><span class="n">favorite_languages</span><span class="o">.</span><span class="n">values</span><span class="p">())</span>
</span></span></code></pre></div><pre><code>{'C', 'python', 'ruby'}
</code></pre>
<p>  <em><strong>This will remove the repeated values!</strong></em></p>
<h2 id="004-nest">004 Nest</h2>
<h3 id="dictionaries-in-a-list">Dictionaries in A List</h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">aliens</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">for</span> <span class="n">alien_number</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">30</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="n">new_alien</span> <span class="o">=</span> <span class="p">{</span><span class="s1">&#39;color&#39;</span><span class="p">:</span> <span class="s1">&#39;green&#39;</span><span class="p">,</span> <span class="s1">&#39;points&#39;</span><span class="p">:</span> <span class="mi">5</span><span class="p">,</span> <span class="s1">&#39;speed&#39;</span><span class="p">:</span> <span class="s1">&#39;slow&#39;</span><span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="n">aliens</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">new_alien</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">for</span> <span class="n">alien</span> <span class="ow">in</span> <span class="n">aliens</span><span class="p">[</span><span class="mi">0</span><span class="p">:</span><span class="mi">3</span><span class="p">]:</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="n">alien</span><span class="p">[</span><span class="s1">&#39;color&#39;</span><span class="p">]</span> <span class="o">==</span> <span class="s1">&#39;green&#39;</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="n">alien</span><span class="p">[</span><span class="s1">&#39;color&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s1">&#39;yellow&#39;</span>
</span></span><span class="line"><span class="cl">        <span class="n">alien</span><span class="p">[</span><span class="s1">&#39;speed&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s1">&#39;medium&#39;</span>
</span></span><span class="line"><span class="cl">        <span class="n">alien</span><span class="p">[</span><span class="s1">&#39;points&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="mi">10</span>
</span></span><span class="line"><span class="cl">    <span class="k">elif</span> <span class="n">alien</span><span class="p">[</span><span class="s1">&#39;color&#39;</span><span class="p">]</span> <span class="o">==</span> <span class="s1">&#39;yellow&#39;</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="n">alien</span><span class="p">[</span><span class="s1">&#39;color&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s1">&#39;res&#39;</span>
</span></span><span class="line"><span class="cl">        <span class="n">alien</span><span class="p">[</span><span class="s1">&#39;speed&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s1">&#39;fast&#39;</span>
</span></span><span class="line"><span class="cl">        <span class="n">alien</span><span class="p">[</span><span class="s1">&#39;points&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="mi">15</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl"><span class="k">for</span> <span class="n">alien</span> <span class="ow">in</span> <span class="n">aliens</span><span class="p">[:</span><span class="mi">5</span><span class="p">]:</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="n">alien</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="s2">&#34;...&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="s2">&#34;Total number of aliens: &#34;</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">aliens</span><span class="p">)))</span>
</span></span></code></pre></div><pre><code>{'color': 'yellow', 'points': 10, 'speed': 'medium'}
{'color': 'yellow', 'points': 10, 'speed': 'medium'}
{'color': 'yellow', 'points': 10, 'speed': 'medium'}
{'color': 'green', 'points': 5, 'speed': 'slow'}
{'color': 'green', 'points': 5, 'speed': 'slow'}
...
Total number of aliens: 30
</code></pre>
<h3 id="lists-in-a-dictionary">Lists in A Dictionary</h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">favorite_languages</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;jen&#39;</span> <span class="p">:</span> <span class="p">[</span><span class="s1">&#39;python&#39;</span><span class="p">,</span> <span class="s1">&#39;ruby&#39;</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;sarah&#39;</span> <span class="p">:</span> <span class="p">[</span><span class="s1">&#39;C&#39;</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;edward&#39;</span> <span class="p">:</span> <span class="p">[</span><span class="s1">&#39;ruby&#39;</span><span class="p">,</span> <span class="s1">&#39;go&#39;</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;phil&#39;</span> <span class="p">:</span> <span class="p">[</span><span class="s1">&#39;python&#39;</span><span class="p">,</span> <span class="s1">&#39;haskell&#39;</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">for</span> <span class="n">name</span><span class="p">,</span> <span class="n">language</span> <span class="ow">in</span> <span class="n">favorite_languages</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">language</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;</span><span class="se">\n</span><span class="s2">&#34;</span> <span class="o">+</span> <span class="n">name</span><span class="o">.</span><span class="n">title</span><span class="p">()</span> <span class="o">+</span> <span class="s2">&#34;&#39;s favorite language is &#34;</span> <span class="o">+</span> <span class="n">language</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">title</span><span class="p">())</span>
</span></span><span class="line"><span class="cl">    <span class="k">else</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;</span><span class="se">\n</span><span class="s2">&#34;</span> <span class="o">+</span> <span class="n">name</span><span class="o">.</span><span class="n">title</span><span class="p">()</span> <span class="o">+</span> <span class="s2">&#34;&#39;s favorite languages are:&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="k">for</span> <span class="n">language</span> <span class="ow">in</span> <span class="n">languages</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;</span><span class="se">\t</span><span class="s2">&#34;</span> <span class="o">+</span> <span class="n">language</span><span class="o">.</span><span class="n">title</span><span class="p">())</span>
</span></span></code></pre></div><pre><code>Jen's favorite languages are:
	Python
	Haskell

Sarah's favorite language is C

Edward's favorite languages are:
	Python
	Haskell

Phil's favorite languages are:
	Python
	Haskell
</code></pre>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">users</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;aeinsein&#39;</span> <span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="s1">&#39;first&#39;</span> <span class="p">:</span> <span class="s1">&#39;albert&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="s1">&#39;last&#39;</span> <span class="p">:</span> <span class="s1">&#39;einstein&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="s1">&#39;location&#39;</span> <span class="p">:</span> <span class="s1">&#39;princeton&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;mcurie&#39;</span><span class="p">:{</span>
</span></span><span class="line"><span class="cl">        <span class="s1">&#39;first&#39;</span> <span class="p">:</span> <span class="s1">&#39;marie&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="s1">&#39;last&#39;</span> <span class="p">:</span> <span class="s1">&#39;curie&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="s1">&#39;location&#39;</span> <span class="p">:</span> <span class="s1">&#39;paris&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">for</span> <span class="n">username</span><span class="p">,</span> <span class="n">user_info</span> <span class="ow">in</span> <span class="n">users</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;</span><span class="se">\n</span><span class="s2">Username: &#34;</span> <span class="o">+</span> <span class="n">username</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">full_name</span> <span class="o">=</span> <span class="n">user_info</span><span class="p">[</span><span class="s1">&#39;first&#39;</span><span class="p">]</span> <span class="o">+</span> <span class="s2">&#34; &#34;</span> <span class="o">+</span> <span class="n">user_info</span><span class="p">[</span><span class="s1">&#39;last&#39;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">    <span class="n">location</span> <span class="o">=</span> <span class="n">user_info</span><span class="p">[</span><span class="s1">&#39;location&#39;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;</span><span class="se">\t</span><span class="s2">Full name:&#34;</span> <span class="o">+</span> <span class="n">full_name</span><span class="o">.</span><span class="n">title</span><span class="p">())</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;</span><span class="se">\t</span><span class="s2">Location: &#34;</span> <span class="o">+</span> <span class="n">location</span><span class="o">.</span><span class="n">title</span><span class="p">())</span>
</span></span></code></pre></div><pre><code>Username: aeinsein
	Full name:Albert Einstein
	Location: Princeton

Username: mcurie
	Full name:Marie Curie
	Location: Paris
</code></pre>
<hr>
<h1 id="chapter-7-input-and-while-loop">Chapter 7 Input and While Loop</h1>
<h2 id="001-input-----try-int">001 <code>input()</code>  ？   Try <code>int()</code></h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">msg</span> <span class="o">=</span> <span class="nb">input</span><span class="p">(</span><span class="s2">&#34;Tell me sth:&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">msg</span><span class="p">)</span>
</span></span></code></pre></div><pre><code>Tell me sth:test
test
</code></pre>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">msg0</span> <span class="o">=</span> <span class="s2">&#34;hello &#34;</span>
</span></span><span class="line"><span class="cl"><span class="n">msg0</span> <span class="o">+=</span> <span class="s2">&#34;</span><span class="se">\n</span><span class="s2">input sth: &#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">msg1</span> <span class="o">=</span> <span class="nb">input</span><span class="p">(</span><span class="n">msg0</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">msg1</span><span class="p">)</span>
</span></span></code></pre></div><pre><code>hello 
input sth: test1
test1
</code></pre>
<p>  <em><strong>But, how to input a number?</strong></em></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">age</span> <span class="o">=</span> <span class="nb">input</span><span class="p">(</span><span class="s2">&#34;your age&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">age</span>
</span></span></code></pre></div><pre><code>your age18





'18'
</code></pre>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">age</span> <span class="o">=</span> <span class="nb">input</span><span class="p">(</span><span class="s2">&#34;your age&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">age</span> <span class="o">&gt;=</span> <span class="mi">18</span>
</span></span></code></pre></div><pre><code>your age18



---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

&lt;ipython-input-9-74683d3f63a8&gt; in &lt;module&gt;
      1 age = input(&quot;your age&quot;)
----&gt; 2 age &gt;= 18


TypeError: '&gt;=' not supported between instances of 'str' and 'int'
</code></pre>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">age1</span> <span class="o">=</span> <span class="nb">input</span><span class="p">(</span><span class="n">age1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">age1</span>
</span></span></code></pre></div><pre><code>---------------------------------------------------------------------------

NameError                                 Traceback (most recent call last)

&lt;ipython-input-7-b4864473f466&gt; in &lt;module&gt;
----&gt; 1 age1 = input(age1)
      2 age1


NameError: name 'age1' is not defined
</code></pre>
<p>  <em>Above is just a silly test out of my curiosity.</em></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">age</span> <span class="o">=</span> <span class="nb">input</span><span class="p">(</span><span class="s2">&#34;your age&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">age</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">age</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">age</span> <span class="o">&gt;=</span> <span class="mi">18</span>
</span></span></code></pre></div><pre><code>your age18





True
</code></pre>
<h3 id="mod-">Mod <code>%</code></h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="mi">4</span> <span class="o">%</span> <span class="mi">3</span>
</span></span></code></pre></div><pre><code>1
</code></pre>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">num</span> <span class="o">=</span> <span class="nb">input</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="n">num</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">num</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="n">num</span> <span class="o">%</span> <span class="mi">2</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;</span><span class="se">\n</span><span class="s2">The number &#34;</span> <span class="o">+</span> <span class="n">num</span> <span class="o">+</span> <span class="s2">&#34; is even.&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="k">else</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;</span><span class="se">\n</span><span class="s2">The number &#34;</span> <span class="o">+</span> <span class="n">num</span> <span class="o">+</span> <span class="s2">&#34; is odd.&#34;</span><span class="p">)</span>
</span></span></code></pre></div><pre><code>100



---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

&lt;ipython-input-13-2b870bf3f31d&gt; in &lt;module&gt;
      3 
      4 if num % 2 == 0:
----&gt; 5     print(&quot;\nThe number &quot; + num + &quot; is even.&quot;)
      6 else:
      7     print(&quot;\nThe number &quot; + num + &quot; is odd.&quot;)


TypeError: must be str, not int
</code></pre>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">num</span> <span class="o">=</span> <span class="nb">input</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="n">num</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">num</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="n">num</span> <span class="o">%</span> <span class="mi">2</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;</span><span class="se">\n</span><span class="s2">The number &#34;</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">num</span><span class="p">)</span> <span class="o">+</span> <span class="s2">&#34; is even.&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="k">else</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;</span><span class="se">\n</span><span class="s2">The number &#34;</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">num</span><span class="p">)</span> <span class="o">+</span> <span class="s2">&#34; is odd.&#34;</span><span class="p">)</span>
</span></span></code></pre></div><pre><code>100

The number 100 is even.
</code></pre>
<p>  <em><strong>Bear in mind that <code>str()</code> is necessary when inserting a number into a string.</strong></em></p>
<h2 id="002-while">002 While</h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">cnt</span> <span class="o">=</span> <span class="mi">1</span>
</span></span><span class="line"><span class="cl"><span class="k">while</span> <span class="n">cnt</span> <span class="o">&lt;=</span> <span class="mi">5</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="n">cnt</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">cnt</span> <span class="o">+=</span> <span class="mi">1</span>
</span></span></code></pre></div><pre><code>1
2
3
4
5
</code></pre>
<p>  <em><strong><code>cnt++</code> is illegal in Python!</strong></em></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">msg</span> <span class="o">=</span> <span class="s2">&#34;&#34;</span>
</span></span><span class="line"><span class="cl"><span class="k">while</span> <span class="n">msg</span> <span class="o">!=</span> <span class="s2">&#34;quit&#34;</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="n">msg</span> <span class="o">=</span> <span class="nb">input</span><span class="p">(</span><span class="n">msg</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="n">msg</span> <span class="o">!=</span> <span class="s2">&#34;quit&#34;</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="n">msg</span> <span class="o">+</span> <span class="s2">&#34;</span><span class="se">\n</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span></code></pre></div><pre><code>666
666

666quit
</code></pre>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">active</span> <span class="o">=</span> <span class="kc">True</span>
</span></span><span class="line"><span class="cl"><span class="k">while</span> <span class="n">active</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="n">msg</span> <span class="o">=</span> <span class="nb">input</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="n">msg</span> <span class="o">==</span> <span class="s2">&#34;quit&#34;</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="n">active</span> <span class="o">=</span> <span class="kc">False</span>
</span></span><span class="line"><span class="cl">    <span class="k">else</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="n">msg</span><span class="p">)</span>
</span></span></code></pre></div><pre><code>666
666
quit
</code></pre>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">while</span> <span class="kc">True</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="n">msg</span> <span class="o">=</span> <span class="nb">input</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="n">msg</span> <span class="o">==</span> <span class="s2">&#34;quit&#34;</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="k">break</span>
</span></span><span class="line"><span class="cl">    <span class="k">else</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="n">msg</span><span class="p">)</span>
</span></span></code></pre></div><pre><code>666
666
quit
</code></pre>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span>
</span></span><span class="line"><span class="cl"><span class="k">while</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="mi">10</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="n">i</span> <span class="o">+=</span> <span class="mi">1</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="n">i</span> <span class="o">%</span> <span class="mi">2</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="k">continue</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="n">i</span><span class="p">)</span>
</span></span></code></pre></div><pre><code>1
3
5
7
9
</code></pre>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">i</span> <span class="o">=</span> <span class="mi">1</span>
</span></span><span class="line"><span class="cl"><span class="k">while</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="mi">10</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="n">i</span><span class="p">)</span>
</span></span></code></pre></div><p>  <em><strong>Above is a endless loop!</strong></em></p>
<h2 id="003-while--list--dictionary">003 While &amp; List &amp; Dictionary</h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">unconfirmed_users</span> <span class="o">=</span> <span class="p">[</span><span class="s1">&#39;alice&#39;</span><span class="p">,</span> <span class="s1">&#39;brain&#39;</span><span class="p">,</span> <span class="s1">&#39;candace&#39;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="n">confirmed_users</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">while</span> <span class="n">unconfirmed_users</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="n">current_user</span> <span class="o">=</span> <span class="n">unconfirmed_users</span><span class="o">.</span><span class="n">pop</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;Verifying user: &#34;</span> <span class="o">+</span> <span class="n">current_user</span><span class="o">.</span><span class="n">title</span><span class="p">())</span>
</span></span><span class="line"><span class="cl">    <span class="n">confirmed_users</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">current_user</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="s2">&#34;</span><span class="se">\n</span><span class="s2">The following users have been confirmed:&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="k">for</span> <span class="n">confirmed_user</span> <span class="ow">in</span> <span class="n">confirmed_users</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="n">confirmed_user</span><span class="o">.</span><span class="n">title</span><span class="p">())</span>
</span></span></code></pre></div><pre><code>Verifying user: Candace
Verifying user: Brain
Verifying user: Alice

The following users have been confirmed:
Candace
Brain
Alice
</code></pre>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">pets</span> <span class="o">=</span> <span class="p">[</span><span class="s1">&#39;dog&#39;</span><span class="p">,</span> <span class="s1">&#39;cat&#39;</span><span class="p">,</span> <span class="s1">&#39;dog&#39;</span><span class="p">,</span> <span class="s1">&#39;goldfish&#39;</span><span class="p">,</span> <span class="s1">&#39;cat&#39;</span><span class="p">,</span> <span class="s1">&#39;rabbit&#39;</span><span class="p">,</span> <span class="s1">&#39;cat&#39;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">pets</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">while</span> <span class="s1">&#39;cat&#39;</span> <span class="ow">in</span> <span class="n">pets</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="n">pets</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="s1">&#39;cat&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">pets</span><span class="p">)</span>
</span></span></code></pre></div><pre><code>['dog', 'cat', 'dog', 'goldfish', 'cat', 'rabbit', 'cat']
['dog', 'dog', 'goldfish', 'rabbit']
</code></pre>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">responses</span> <span class="o">=</span> <span class="p">{}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">polling_active</span> <span class="o">=</span> <span class="kc">True</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">while</span> <span class="n">polling_active</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="n">name</span> <span class="o">=</span> <span class="nb">input</span><span class="p">(</span><span class="s2">&#34;</span><span class="se">\n</span><span class="s2">What&#39;s your name? &#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">response</span> <span class="o">=</span> <span class="nb">input</span><span class="p">(</span><span class="s2">&#34;Which mountain would you like to climb someday? &#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="n">responses</span><span class="p">[</span><span class="n">name</span><span class="p">]</span> <span class="o">=</span> <span class="n">response</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="n">repeat</span> <span class="o">=</span> <span class="nb">input</span><span class="p">(</span><span class="s2">&#34;Would you like to let another person respond? (yes/no)&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="n">repeat</span> <span class="o">==</span> <span class="s1">&#39;no&#39;</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="n">polling_active</span> <span class="o">=</span> <span class="kc">False</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="s2">&#34;</span><span class="se">\n</span><span class="s2">--- Poll Results ---&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="k">for</span> <span class="n">name</span><span class="p">,</span> <span class="n">response</span> <span class="ow">in</span> <span class="n">responses</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="n">name</span> <span class="o">+</span> <span class="s2">&#34; would like to climb &#34;</span> <span class="o">+</span> <span class="n">response</span> <span class="o">+</span> <span class="s1">&#39;.&#39;</span><span class="p">)</span>
</span></span></code></pre></div><pre><code>What's your name? 1
Which mountain would you like to climb someday? 1
Would you like to let another person respond? (yes/no)No

What's your name? 2
Which mountain would you like to climb someday? 2
Would you like to let another person respond? (yes/no)no

--- Poll Results ---
1 would like to climb 1.
2 would like to climb 2.
</code></pre>
<hr>
<h1 id="chapter-8-function">Chapter 8 Function</h1>
<h2 id="001-define-a-function">001 Define a function</h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">greet_user</span><span class="p">():</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;Hello!&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl"><span class="n">greet_user</span><span class="p">()</span>
</span></span></code></pre></div><pre><code>Hello!
</code></pre>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">greet_user</span><span class="p">(</span><span class="n">username</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;Hello, &#34;</span> <span class="o">+</span> <span class="n">username</span><span class="o">.</span><span class="n">title</span><span class="p">()</span> <span class="o">+</span> <span class="s2">&#34;!&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl"><span class="n">greet_user</span><span class="p">(</span><span class="s2">&#34;charlie&#34;</span><span class="p">)</span>
</span></span></code></pre></div><pre><code>Hello, Charlie!
</code></pre>
<p>  <em>Mind the formal parameter and the actual parameter</em></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">describe_pet</span><span class="p">(</span><span class="n">animal_type</span><span class="p">,</span> <span class="n">pet_name</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;</span><span class="se">\n</span><span class="s2">I have a &#34;</span> <span class="o">+</span> <span class="n">animal_type</span> <span class="o">+</span> <span class="s2">&#34;.&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;My &#34;</span> <span class="o">+</span> <span class="n">animal_type</span> <span class="o">+</span> <span class="s2">&#34;&#39;s name is&#34;</span> <span class="o">+</span> <span class="n">pet_name</span><span class="o">.</span><span class="n">title</span><span class="p">()</span> <span class="o">+</span> <span class="s2">&#34;.&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl"><span class="n">describe_pet</span><span class="p">(</span><span class="s2">&#34;hamster&#34;</span><span class="p">,</span> <span class="s1">&#39;harry&#39;</span><span class="p">)</span>
</span></span></code></pre></div><pre><code>I have a hamster.
My hamster's name isHarry.
</code></pre>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">describe_pet</span><span class="p">(</span><span class="n">animal_type</span><span class="p">,</span> <span class="n">pet_name</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;</span><span class="se">\n</span><span class="s2">I have a &#34;</span> <span class="o">+</span> <span class="n">animal_type</span> <span class="o">+</span> <span class="s2">&#34;.&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;My &#34;</span> <span class="o">+</span> <span class="n">animal_type</span> <span class="o">+</span> <span class="s2">&#34;&#39;s name is&#34;</span> <span class="o">+</span> <span class="n">pet_name</span><span class="o">.</span><span class="n">title</span><span class="p">()</span> <span class="o">+</span> <span class="s2">&#34;.&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl"><span class="n">describe_pet</span><span class="p">(</span><span class="s2">&#34;hamster&#34;</span><span class="p">,</span> <span class="s1">&#39;harry&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">describe_pet</span><span class="p">(</span><span class="s2">&#34;dog&#34;</span><span class="p">,</span> <span class="s1">&#39;willie&#39;</span><span class="p">)</span>
</span></span></code></pre></div><pre><code>I have a hamster.
My hamster's name isHarry.

I have a dog.
My dog's name isWillie.
</code></pre>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">describe_pet</span><span class="p">(</span><span class="n">animal_type</span><span class="p">,</span> <span class="n">pet_name</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;</span><span class="se">\n</span><span class="s2">I have a &#34;</span> <span class="o">+</span> <span class="n">animal_type</span> <span class="o">+</span> <span class="s2">&#34;.&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;My &#34;</span> <span class="o">+</span> <span class="n">animal_type</span> <span class="o">+</span> <span class="s2">&#34;&#39;s name is&#34;</span> <span class="o">+</span> <span class="n">pet_name</span><span class="o">.</span><span class="n">title</span><span class="p">()</span> <span class="o">+</span> <span class="s2">&#34;.&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl"><span class="n">describe_pet</span><span class="p">(</span><span class="s2">&#34;hamster&#34;</span><span class="p">,</span> <span class="s1">&#39;harry&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">describe_pet</span><span class="p">(</span><span class="s1">&#39;harry&#39;</span><span class="p">,</span> <span class="s2">&#34;hamster&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">describe_pet</span><span class="p">(</span><span class="n">animal_type</span> <span class="o">=</span> <span class="s1">&#39;hamster&#39;</span><span class="p">,</span> <span class="n">pet_name</span> <span class="o">=</span> <span class="s1">&#39;harry&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">describe_pet</span><span class="p">(</span><span class="n">pet_name</span> <span class="o">=</span> <span class="s1">&#39;harry&#39;</span><span class="p">,</span> <span class="n">animal_type</span> <span class="o">=</span> <span class="s1">&#39;hamster&#39;</span><span class="p">)</span>
</span></span></code></pre></div><pre><code>I have a hamster.
My hamster's name isHarry.

I have a harry.
My harry's name isHamster.

I have a hamster.
My hamster's name isHarry.

I have a hamster.
My hamster's name isHarry.
</code></pre>
<p>  <em><strong>Mind the last two calling of the function <code>describe_pet</code> !</strong></em></p>
<h2 id="002-functions-with-default-values">002 Functions with default values</h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">describe_pet</span><span class="p">(</span><span class="n">pet_name</span><span class="p">,</span> <span class="n">animal_type</span> <span class="o">=</span> <span class="s1">&#39;dog&#39;</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;</span><span class="se">\n</span><span class="s2">I have a &#34;</span> <span class="o">+</span> <span class="n">animal_type</span> <span class="o">+</span> <span class="s2">&#34;.&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;My &#34;</span> <span class="o">+</span> <span class="n">animal_type</span> <span class="o">+</span> <span class="s2">&#34;&#39;s name is&#34;</span> <span class="o">+</span> <span class="n">pet_name</span><span class="o">.</span><span class="n">title</span><span class="p">()</span> <span class="o">+</span> <span class="s2">&#34;.&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl"><span class="n">describe_pet</span><span class="p">(</span><span class="s1">&#39;harry&#39;</span><span class="p">,</span> <span class="s2">&#34;hamster&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">describe_pet</span><span class="p">(</span><span class="s1">&#39;willie&#39;</span><span class="p">)</span>
</span></span></code></pre></div><pre><code>I have a hamster.
My hamster's name isHarry.

I have a dog.
My dog's name isWillie.
</code></pre>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">describe_pet</span><span class="p">(</span><span class="n">animal_type</span> <span class="o">=</span> <span class="s1">&#39;dog&#39;</span><span class="p">,</span> <span class="n">pet_name</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;</span><span class="se">\n</span><span class="s2">I have a &#34;</span> <span class="o">+</span> <span class="n">animal_type</span> <span class="o">+</span> <span class="s2">&#34;.&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;My &#34;</span> <span class="o">+</span> <span class="n">animal_type</span> <span class="o">+</span> <span class="s2">&#34;&#39;s name is&#34;</span> <span class="o">+</span> <span class="n">pet_name</span><span class="o">.</span><span class="n">title</span><span class="p">()</span> <span class="o">+</span> <span class="s2">&#34;.&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl"><span class="n">describe_pet</span><span class="p">(</span><span class="s2">&#34;hamster&#34;</span><span class="p">,</span> <span class="s1">&#39;harry&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">describe_pet</span><span class="p">(</span><span class="s1">&#39;willie&#39;</span><span class="p">)</span>
</span></span></code></pre></div><pre><code>  File &quot;&lt;ipython-input-22-783719293d54&gt;&quot;, line 1
    def describe_pet(animal_type = 'dog', pet_name):
                    ^
SyntaxError: non-default argument follows default argument
</code></pre>
<p>  <em>This time, an error occured!</em></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">describe_pet</span><span class="p">(</span><span class="n">animal_type</span> <span class="o">=</span> <span class="s1">&#39;dog&#39;</span><span class="p">,</span> <span class="n">pet_name</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;</span><span class="se">\n</span><span class="s2">I have a &#34;</span> <span class="o">+</span> <span class="n">animal_type</span> <span class="o">+</span> <span class="s2">&#34;.&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;My &#34;</span> <span class="o">+</span> <span class="n">animal_type</span> <span class="o">+</span> <span class="s2">&#34;&#39;s name is&#34;</span> <span class="o">+</span> <span class="n">pet_name</span><span class="o">.</span><span class="n">title</span><span class="p">()</span> <span class="o">+</span> <span class="s2">&#34;.&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl"><span class="n">describe_pet</span><span class="p">(</span><span class="s2">&#34;hamster&#34;</span><span class="p">,</span> <span class="s1">&#39;harry&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">describe_pet</span><span class="p">(</span><span class="n">pet_name</span> <span class="o">=</span> <span class="s1">&#39;willie&#39;</span><span class="p">)</span>
</span></span></code></pre></div><pre><code>  File &quot;&lt;ipython-input-23-697809b5a3b4&gt;&quot;, line 1
    def describe_pet(animal_type = 'dog', pet_name):
                    ^
SyntaxError: non-default argument follows default argument
</code></pre>
<p>  <em>Another error!</em></p>
<p>  <em><strong>In Python, you have to put the non-default arguments before the default ones!!!</strong></em></p>
<h2 id="003-return-value">003 Return Value</h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_full_name</span><span class="p">(</span><span class="n">first_name</span><span class="p">,</span> <span class="n">second_name</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="n">full_name</span> <span class="o">=</span> <span class="n">first_name</span> <span class="o">+</span> <span class="s1">&#39; &#39;</span> <span class="o">+</span> <span class="n">second_name</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">full_name</span><span class="o">.</span><span class="n">title</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">musician</span> <span class="o">=</span> <span class="n">get_full_name</span><span class="p">(</span><span class="s1">&#39;jimi&#39;</span><span class="p">,</span> <span class="s1">&#39;hendrix&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">musician</span><span class="p">)</span>
</span></span></code></pre></div><pre><code>Jimi Hendrix
</code></pre>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_formatted_name</span><span class="p">(</span><span class="n">first_name</span><span class="p">,</span> <span class="n">last_name</span><span class="p">,</span> <span class="n">middle_name</span><span class="o">=</span><span class="s1">&#39;&#39;</span><span class="p">):</span> <span class="c1"># Pay Attention!</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="n">middle_name</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="n">full_name</span> <span class="o">=</span> <span class="n">first_name</span> <span class="o">+</span> <span class="s1">&#39; &#39;</span> <span class="o">+</span> <span class="n">middle_name</span> <span class="o">+</span> <span class="s1">&#39; &#39;</span> <span class="o">+</span> <span class="n">last_name</span>
</span></span><span class="line"><span class="cl">    <span class="k">else</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="n">full_name</span> <span class="o">=</span> <span class="n">first_name</span> <span class="o">+</span> <span class="s1">&#39; &#39;</span> <span class="o">+</span> <span class="n">last_name</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">full_name</span><span class="o">.</span><span class="n">title</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">musician</span> <span class="o">=</span> <span class="n">get_formatted_name</span><span class="p">(</span><span class="s1">&#39;jimi&#39;</span><span class="p">,</span> <span class="s1">&#39;hendrix&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">musician</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">musician</span> <span class="o">=</span> <span class="n">get_formatted_name</span><span class="p">(</span><span class="s1">&#39;john&#39;</span><span class="p">,</span> <span class="s1">&#39;hooker&#39;</span><span class="p">,</span> <span class="s1">&#39;lee&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">musician</span><span class="p">)</span>
</span></span></code></pre></div><pre><code>Jimi Hendrix
John Lee Hooker
</code></pre>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">build_person</span><span class="p">(</span><span class="n">first_name</span><span class="p">,</span> <span class="n">last_name</span><span class="p">,</span> <span class="n">age</span><span class="o">=</span><span class="s1">&#39;&#39;</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="n">person</span> <span class="o">=</span> <span class="p">{</span><span class="s1">&#39;first&#39;</span><span class="p">:</span> <span class="n">first_name</span><span class="p">,</span> <span class="s1">&#39;last&#39;</span><span class="p">:</span> <span class="n">last_name</span><span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="n">age</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="n">person</span><span class="p">[</span><span class="s1">&#39;age&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">age</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">person</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">musician</span> <span class="o">=</span> <span class="n">build_person</span><span class="p">(</span><span class="s1">&#39;jimi&#39;</span><span class="p">,</span> <span class="s1">&#39;hendrix&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">musician</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">musician</span> <span class="o">=</span> <span class="n">build_person</span><span class="p">(</span><span class="s1">&#39;jimi&#39;</span><span class="p">,</span> <span class="s1">&#39;hendrix&#39;</span><span class="p">,</span> <span class="mi">27</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">musician</span><span class="p">)</span>
</span></span></code></pre></div><pre><code>{'first': 'jimi', 'last': 'hendrix'}
{'first': 'jimi', 'last': 'hendrix', 'age': 27}
</code></pre>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_full_name</span><span class="p">(</span><span class="n">first_name</span><span class="p">,</span> <span class="n">second_name</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="n">full_name</span> <span class="o">=</span> <span class="n">first_name</span> <span class="o">+</span> <span class="s1">&#39; &#39;</span> <span class="o">+</span> <span class="n">second_name</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">full_name</span><span class="o">.</span><span class="n">title</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">while</span> <span class="kc">True</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;</span><span class="se">\n</span><span class="s2">Please tell me your name:&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;(Enter &#39;q&#39; to quit!)&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">f_name</span> <span class="o">=</span> <span class="nb">input</span><span class="p">(</span><span class="s2">&#34;First name:&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="n">f_name</span> <span class="o">==</span> <span class="s1">&#39;q&#39;</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="k">break</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">l_name</span> <span class="o">=</span> <span class="nb">input</span><span class="p">(</span><span class="s2">&#34;Last name:&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="n">l_name</span> <span class="o">==</span> <span class="s1">&#39;q&#39;</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="k">break</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="n">formatted_name</span> <span class="o">=</span> <span class="n">get_full_name</span><span class="p">(</span><span class="n">f_name</span><span class="p">,</span> <span class="n">l_name</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;</span><span class="se">\n</span><span class="s2">Hello, &#34;</span> <span class="o">+</span> <span class="n">formatted_name</span> <span class="o">+</span> <span class="s1">&#39;!&#39;</span><span class="p">)</span>
</span></span></code></pre></div><pre><code>Please tell me your name:
(Enter 'q' to quit!)
First name:charlie
Last name:jiang

Hello, Charlie Jiang!

Please tell me your name:
(Enter 'q' to quit!)
First name:charlie
Last name:jiang

Hello, Charlie Jiang!

Please tell me your name:
(Enter 'q' to quit!)
First name:c
Last name:q
</code></pre>
<h2 id="004-relay-lists">004 Relay Lists</h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">greet_users</span><span class="p">(</span><span class="n">names</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="n">name</span> <span class="ow">in</span> <span class="n">names</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="n">msg</span> <span class="o">=</span> <span class="s2">&#34;Hello, &#34;</span> <span class="o">+</span> <span class="n">name</span><span class="o">.</span><span class="n">title</span><span class="p">()</span> <span class="o">+</span> <span class="s2">&#34;!&#34;</span>
</span></span><span class="line"><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="n">msg</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        
</span></span><span class="line"><span class="cl"><span class="n">usernames</span> <span class="o">=</span> <span class="p">[</span><span class="s1">&#39;hannah&#39;</span><span class="p">,</span> <span class="s1">&#39;ty&#39;</span><span class="p">,</span> <span class="s1">&#39;margot&#39;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="n">greet_users</span><span class="p">(</span><span class="n">usernames</span><span class="p">)</span>
</span></span></code></pre></div><pre><code>Hello, Hannah!
Hello, Ty!
Hello, Margot!
</code></pre>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">print_models</span><span class="p">(</span><span class="n">unprinted_designs</span><span class="p">,</span> <span class="n">completed_models</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="k">while</span> <span class="n">unprinted_designs</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="n">current_design</span> <span class="o">=</span> <span class="n">unprinted_designs</span><span class="o">.</span><span class="n">pop</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;Printing: &#34;</span> <span class="o">+</span> <span class="n">current_design</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="n">completed_models</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">current_design</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        
</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">show_completed_models</span><span class="p">(</span><span class="n">completed_models</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;</span><span class="se">\n</span><span class="s2">The following models have been printed:&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="n">completed_model</span> <span class="ow">in</span> <span class="n">completed_models</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="n">completed_model</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        
</span></span><span class="line"><span class="cl"><span class="n">unprinted_designs</span> <span class="o">=</span> <span class="p">[</span><span class="s1">&#39;iphone case&#39;</span><span class="p">,</span> <span class="s1">&#39;robot pendant&#39;</span><span class="p">,</span> <span class="s1">&#39;dodecahedron&#39;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="n">completed_models</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">print_models</span><span class="p">(</span><span class="n">unprinted_designs</span><span class="p">,</span> <span class="n">completed_models</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">show_completed_models</span><span class="p">(</span><span class="n">completed_models</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">unprinted_designs</span><span class="p">)</span>
</span></span></code></pre></div><pre><code>Printing: dodecahedron
Printing: robot pendant
Printing: iphone case

The following models have been printed:
dodecahedron
robot pendant
iphone case
[]
</code></pre>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">print_models</span><span class="p">(</span><span class="n">unprinted_designs</span><span class="p">,</span> <span class="n">completed_models</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="k">while</span> <span class="n">unprinted_designs</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="n">current_design</span> <span class="o">=</span> <span class="n">unprinted_designs</span><span class="o">.</span><span class="n">pop</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;Printing: &#34;</span> <span class="o">+</span> <span class="n">current_design</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="n">completed_models</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">current_design</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        
</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">show_completed_models</span><span class="p">(</span><span class="n">completed_models</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;</span><span class="se">\n</span><span class="s2">The following models have been printed:&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="n">completed_model</span> <span class="ow">in</span> <span class="n">completed_models</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="n">completed_model</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        
</span></span><span class="line"><span class="cl"><span class="n">unprinted_designs</span> <span class="o">=</span> <span class="p">[</span><span class="s1">&#39;iphone case&#39;</span><span class="p">,</span> <span class="s1">&#39;robot pendant&#39;</span><span class="p">,</span> <span class="s1">&#39;dodecahedron&#39;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="n">completed_models</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">print_models</span><span class="p">(</span><span class="n">unprinted_designs</span><span class="p">[:],</span> <span class="n">completed_models</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">show_completed_models</span><span class="p">(</span><span class="n">completed_models</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">unprinted_designs</span><span class="p">)</span>
</span></span></code></pre></div><pre><code>Printing: dodecahedron
Printing: robot pendant
Printing: iphone case

The following models have been printed:
dodecahedron
robot pendant
iphone case
['iphone case', 'robot pendant', 'dodecahedron']
</code></pre>
<p>  <em>The second version of this programme conveys a copy of a list!</em></p>
<h2 id="005-relay-as-many-actual-parameters-as-you-like">005 Relay as many actual parameters as you like!</h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">make_pizza</span><span class="p">(</span><span class="o">*</span><span class="n">toppings</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;</span><span class="se">\n</span><span class="s2">Making a pizza with the following toppings:&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="n">topping</span> <span class="ow">in</span> <span class="n">toppings</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;- &#34;</span> <span class="o">+</span> <span class="n">topping</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        
</span></span><span class="line"><span class="cl"><span class="n">make_pizza</span><span class="p">(</span><span class="s1">&#39;pepperoni&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">make_pizza</span><span class="p">(</span><span class="s1">&#39;mushrooms&#39;</span><span class="p">,</span> <span class="s1">&#39;green peppers&#39;</span><span class="p">,</span> <span class="s1">&#39;extra cheese&#39;</span><span class="p">)</span>
</span></span></code></pre></div><pre><code>Making a pizza with the following toppings:
- pepperoni

Making a pizza with the following toppings:
- mushrooms
- green peppers
- extra cheese
</code></pre>
<p>  <code>*</code> let Python create a tuple that contains the actual parameters you relayed, no matter how many actual parameters you relayed to the function.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">make_pizza</span><span class="p">(</span><span class="n">size</span><span class="p">,</span> <span class="o">*</span><span class="n">toppings</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;</span><span class="se">\n</span><span class="s2">Making a &#34;</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">size</span><span class="p">)</span> <span class="o">+</span> <span class="s2">&#34;-inch pizza with the following toppings:&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="n">topping</span> <span class="ow">in</span> <span class="n">toppings</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;- &#34;</span> <span class="o">+</span> <span class="n">topping</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        
</span></span><span class="line"><span class="cl"><span class="n">make_pizza</span><span class="p">(</span><span class="mi">16</span><span class="p">,</span> <span class="s1">&#39;pepperoni&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">make_pizza</span><span class="p">(</span><span class="mi">12</span><span class="p">,</span> <span class="s1">&#39;mushrooms&#39;</span><span class="p">,</span> <span class="s1">&#39;green peppers&#39;</span><span class="p">,</span> <span class="s1">&#39;extra cheese&#39;</span><span class="p">)</span>
</span></span></code></pre></div><pre><code>Making a 16-inch pizza with the following toppings:
- pepperoni

Making a 12-inch pizza with the following toppings:
- mushrooms
- green peppers
- extra cheese
</code></pre>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">build_profile</span><span class="p">(</span><span class="n">first</span><span class="p">,</span> <span class="n">last</span><span class="p">,</span> <span class="o">**</span><span class="n">user_info</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="n">profile</span> <span class="o">=</span> <span class="p">{}</span>
</span></span><span class="line"><span class="cl">    <span class="n">profile</span><span class="p">[</span><span class="s1">&#39;first_name&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">first</span>
</span></span><span class="line"><span class="cl">    <span class="n">profile</span><span class="p">[</span><span class="s1">&#39;last_name&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">last</span>
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="n">key</span><span class="p">,</span><span class="n">value</span> <span class="ow">in</span> <span class="n">user_info</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
</span></span><span class="line"><span class="cl">        <span class="n">profile</span><span class="p">[</span><span class="n">key</span><span class="p">]</span> <span class="o">=</span> <span class="n">value</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">profile</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">user_profile</span> <span class="o">=</span> <span class="n">build_profile</span><span class="p">(</span><span class="s1">&#39;albert&#39;</span><span class="p">,</span> <span class="s1">&#39;einstein&#39;</span><span class="p">,</span> 
</span></span><span class="line"><span class="cl">                            <span class="n">location</span> <span class="o">=</span> <span class="s1">&#39;princeton&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                            <span class="n">field</span> <span class="o">=</span> <span class="s1">&#39;physics&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">user_profile</span><span class="p">)</span>
</span></span></code></pre></div><pre><code>{'first_name': 'albert', 'last_name': 'einstein', 'location': 'princeton', 'field': 'physics'}
</code></pre>
<p>  <code>**</code> let Python create a dictionary that contains the keys and values you relayed, no matter how many pairs you have relayed to the function.</p>
<h2 id="006-import">006 Import</h2>
<p>  Due to the difficulty of using <code>import</code> in notebook. I&rsquo;ll practice this part in sublime text 3.</p>
<h2 id="007-pep8-again">007 PEP8, again!</h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-Python" data-lang="Python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">function_name</span><span class="p">(</span><span class="n">parameter_0</span><span class="p">,</span> <span class="n">parameter_1</span><span class="o">=</span><span class="s1">&#39;default_value&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">function_name</span><span class="p">(</span><span class="n">value_0</span><span class="p">,</span> <span class="n">parameter_1</span><span class="o">=</span><span class="s1">&#39;value_1&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">function_name</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">        <span class="n">parameter_0</span><span class="p">,</span> <span class="n">parameter_1</span><span class="p">,</span> <span class="n">parameter_2</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="n">parameter_3</span><span class="p">,</span> <span class="n">parameter_4</span><span class="p">,</span> <span class="n">parameter_5</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="n">function</span> <span class="n">body</span><span class="o">...</span>
</span></span></code></pre></div><hr>
<h1 id="chapter-9-class">Chapter 9 Class</h1>
<h2 id="001-introduction-to-class">001 Introduction to Class</h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Dog</span><span class="p">():</span>
</span></span><span class="line"><span class="cl">    <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">age</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">name</span>
</span></span><span class="line"><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">age</span> <span class="o">=</span> <span class="n">age</span>
</span></span><span class="line"><span class="cl">        
</span></span><span class="line"><span class="cl">    <span class="k">def</span> <span class="nf">sit</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="o">.</span><span class="n">title</span><span class="p">()</span> <span class="o">+</span> <span class="s2">&#34; is now sitting.&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        
</span></span><span class="line"><span class="cl">    <span class="k">def</span> <span class="nf">roll_over</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="o">.</span><span class="n">title</span><span class="p">()</span> <span class="o">+</span> <span class="s2">&#34; rolled over!&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        
</span></span><span class="line"><span class="cl"><span class="n">my_dog</span> <span class="o">=</span> <span class="n">Dog</span><span class="p">(</span><span class="s1">&#39;willie&#39;</span><span class="p">,</span> <span class="mi">6</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="s2">&#34;name: &#34;</span> <span class="o">+</span> <span class="n">my_dog</span><span class="o">.</span><span class="n">name</span><span class="o">.</span><span class="n">title</span><span class="p">())</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="s2">&#34;age: &#34;</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">my_dog</span><span class="o">.</span><span class="n">age</span><span class="p">))</span>
</span></span></code></pre></div><pre><code>name: Willie
age: 6
</code></pre>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">my_dog</span> <span class="o">=</span> <span class="n">Dog</span><span class="p">(</span><span class="s1">&#39;willie&#39;</span><span class="p">,</span> <span class="mi">6</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="s2">&#34;name: &#34;</span> <span class="o">+</span> <span class="n">my_dog</span><span class="o">.</span><span class="n">name</span><span class="o">.</span><span class="n">title</span><span class="p">())</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="s2">&#34;age: &#34;</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">my_dog</span><span class="o">.</span><span class="n">age</span><span class="p">))</span>
</span></span></code></pre></div><pre><code>name: Willie
age: 6
</code></pre>
<p>  <em>Mind that <code>__init__</code> has <strong>two</strong> <code>_</code>s at each side!</em></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">my_dog</span><span class="o">.</span><span class="n">sit</span><span class="p">()</span>
</span></span></code></pre></div><pre><code>Willie is now sitting.
</code></pre>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">my_dog</span><span class="o">.</span><span class="n">roll_over</span><span class="p">()</span>
</span></span></code></pre></div><pre><code>Willie rolled over!
</code></pre>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">your_dog</span> <span class="o">=</span> <span class="n">Dog</span><span class="p">(</span><span class="s1">&#39;Lucy&#39;</span><span class="p">,</span> <span class="mi">3</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">your_dog</span><span class="o">.</span><span class="n">name</span>
</span></span></code></pre></div><pre><code>'Lucy'
</code></pre>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">your_dog</span><span class="o">.</span><span class="n">age</span>
</span></span></code></pre></div><pre><code>3
</code></pre>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">your_dog</span><span class="o">.</span><span class="n">sit</span><span class="p">()</span>
</span></span></code></pre></div><pre><code>Lucy is now sitting.
</code></pre>
<h2 id="002-use-class-and-instances">002 Use Class and Instances</h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Car</span><span class="p">():</span>
</span></span><span class="line"><span class="cl">    <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">make</span><span class="p">,</span> <span class="n">model</span><span class="p">,</span> <span class="n">year</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">make</span> <span class="o">=</span> <span class="n">make</span>
</span></span><span class="line"><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">model</span> <span class="o">=</span> <span class="n">model</span>
</span></span><span class="line"><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">year</span> <span class="o">=</span> <span class="n">year</span>
</span></span><span class="line"><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">odometer_reading</span> <span class="o">=</span> <span class="mi">0</span>
</span></span><span class="line"><span class="cl">        
</span></span><span class="line"><span class="cl">    <span class="k">def</span> <span class="nf">get_descriptive_name</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="n">long_name</span> <span class="o">=</span> <span class="nb">str</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">year</span><span class="p">)</span> <span class="o">+</span> <span class="s2">&#34; &#34;</span> <span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">make</span> <span class="o">+</span> <span class="s2">&#34; &#34;</span> <span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">model</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="n">long_name</span><span class="o">.</span><span class="n">title</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="k">def</span> <span class="nf">read_odometer</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;This car has &#34;</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">odometer_reading</span><span class="p">)</span> <span class="o">+</span> <span class="s2">&#34; miles on it.&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl"><span class="n">my_new_car</span> <span class="o">=</span> <span class="n">Car</span><span class="p">(</span><span class="s1">&#39;audi&#39;</span><span class="p">,</span> <span class="s1">&#39;a4&#39;</span><span class="p">,</span> <span class="mi">2016</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">my_new_car</span><span class="o">.</span><span class="n">get_descriptive_name</span><span class="p">())</span>
</span></span><span class="line"><span class="cl"><span class="n">my_new_car</span><span class="o">.</span><span class="n">read_odometer</span><span class="p">()</span>
</span></span></code></pre></div><pre><code>2016 Audi A4
This car has 0 miles on it.
</code></pre>
<p>  Here are some ways to change properties.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">my_new_car</span><span class="o">.</span><span class="n">odometer_reading</span> <span class="o">=</span> <span class="mi">23</span>
</span></span><span class="line"><span class="cl"><span class="n">my_new_car</span><span class="o">.</span><span class="n">read_odometer</span><span class="p">()</span>
</span></span></code></pre></div><pre><code>This car has 23 miles on it.
</code></pre>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Car</span><span class="p">():</span>
</span></span><span class="line"><span class="cl">    <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">make</span><span class="p">,</span> <span class="n">model</span><span class="p">,</span> <span class="n">year</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">make</span> <span class="o">=</span> <span class="n">make</span>
</span></span><span class="line"><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">model</span> <span class="o">=</span> <span class="n">model</span>
</span></span><span class="line"><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">year</span> <span class="o">=</span> <span class="n">year</span>
</span></span><span class="line"><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">odometer_reading</span> <span class="o">=</span> <span class="mi">0</span>
</span></span><span class="line"><span class="cl">        
</span></span><span class="line"><span class="cl">    <span class="k">def</span> <span class="nf">get_descriptive_name</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="n">long_name</span> <span class="o">=</span> <span class="nb">str</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">year</span><span class="p">)</span> <span class="o">+</span> <span class="s2">&#34; &#34;</span> <span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">make</span> <span class="o">+</span> <span class="s2">&#34; &#34;</span> <span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">model</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="n">long_name</span><span class="o">.</span><span class="n">title</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="k">def</span> <span class="nf">read_odometer</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;This car has &#34;</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">odometer_reading</span><span class="p">)</span> <span class="o">+</span> <span class="s2">&#34; miles on it.&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="k">def</span> <span class="nf">update_odometer</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">mileage</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="n">mileage</span> <span class="o">&gt;</span> <span class="bp">self</span><span class="o">.</span><span class="n">odometer_reading</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="bp">self</span><span class="o">.</span><span class="n">odometer_reading</span> <span class="o">=</span> <span class="n">mileage</span>
</span></span><span class="line"><span class="cl">        <span class="k">else</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;You can&#39;t roll back an odometer!&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl"><span class="n">my_new_car</span> <span class="o">=</span> <span class="n">Car</span><span class="p">(</span><span class="s1">&#39;audi&#39;</span><span class="p">,</span> <span class="s1">&#39;a4&#39;</span><span class="p">,</span> <span class="mi">2016</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">my_new_car</span><span class="o">.</span><span class="n">get_descriptive_name</span><span class="p">())</span>
</span></span><span class="line"><span class="cl"><span class="n">my_new_car</span><span class="o">.</span><span class="n">read_odometer</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="n">my_new_car</span><span class="o">.</span><span class="n">update_odometer</span><span class="p">(</span><span class="mi">23</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">my_new_car</span><span class="o">.</span><span class="n">read_odometer</span><span class="p">()</span>
</span></span></code></pre></div><pre><code>2016 Audi A4
This car has 0 miles on it.
This car has 23 miles on it.
</code></pre>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">my_new_car</span><span class="o">.</span><span class="n">update_odometer</span><span class="p">(</span><span class="mi">46</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">my_new_car</span><span class="o">.</span><span class="n">read_odometer</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="n">my_new_car</span><span class="o">.</span><span class="n">update_odometer</span><span class="p">(</span><span class="mi">23</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">my_new_car</span><span class="o">.</span><span class="n">read_odometer</span><span class="p">()</span>
</span></span></code></pre></div><pre><code>This car has 46 miles on it.
You can't roll back an odometer!
This car has 46 miles on it.
</code></pre>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Car</span><span class="p">():</span>
</span></span><span class="line"><span class="cl">    <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">make</span><span class="p">,</span> <span class="n">model</span><span class="p">,</span> <span class="n">year</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">make</span> <span class="o">=</span> <span class="n">make</span>
</span></span><span class="line"><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">model</span> <span class="o">=</span> <span class="n">model</span>
</span></span><span class="line"><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">year</span> <span class="o">=</span> <span class="n">year</span>
</span></span><span class="line"><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">odometer_reading</span> <span class="o">=</span> <span class="mi">0</span>
</span></span><span class="line"><span class="cl">        
</span></span><span class="line"><span class="cl">    <span class="k">def</span> <span class="nf">get_descriptive_name</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="n">long_name</span> <span class="o">=</span> <span class="nb">str</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">year</span><span class="p">)</span> <span class="o">+</span> <span class="s2">&#34; &#34;</span> <span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">make</span> <span class="o">+</span> <span class="s2">&#34; &#34;</span> <span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">model</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="n">long_name</span><span class="o">.</span><span class="n">title</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="k">def</span> <span class="nf">read_odometer</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;This car has &#34;</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">odometer_reading</span><span class="p">)</span> <span class="o">+</span> <span class="s2">&#34; miles on it.&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="k">def</span> <span class="nf">update_odometer</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">mileage</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="n">mileage</span> <span class="o">&gt;</span> <span class="bp">self</span><span class="o">.</span><span class="n">odometer_reading</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="bp">self</span><span class="o">.</span><span class="n">odometer_reading</span> <span class="o">=</span> <span class="n">mileage</span>
</span></span><span class="line"><span class="cl">        <span class="k">else</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;You can&#39;t roll back an odometer!&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">            
</span></span><span class="line"><span class="cl">    <span class="k">def</span> <span class="nf">increment_odometer</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">miles</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="n">miles</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="bp">self</span><span class="o">.</span><span class="n">odometer_reading</span> <span class="o">+=</span> <span class="n">miles</span>
</span></span><span class="line"><span class="cl">        <span class="k">else</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;You can&#39;t roll back an odometer!&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl"><span class="n">my_new_car</span> <span class="o">=</span> <span class="n">Car</span><span class="p">(</span><span class="s1">&#39;audi&#39;</span><span class="p">,</span> <span class="s1">&#39;a4&#39;</span><span class="p">,</span> <span class="mi">2016</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">my_new_car</span><span class="o">.</span><span class="n">get_descriptive_name</span><span class="p">())</span>
</span></span><span class="line"><span class="cl"><span class="n">my_new_car</span><span class="o">.</span><span class="n">read_odometer</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="n">my_new_car</span><span class="o">.</span><span class="n">update_odometer</span><span class="p">(</span><span class="mi">23</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">my_new_car</span><span class="o">.</span><span class="n">read_odometer</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="n">my_new_car</span><span class="o">.</span><span class="n">increment_odometer</span><span class="p">(</span><span class="mi">100</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">my_new_car</span><span class="o">.</span><span class="n">read_odometer</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="n">my_new_car</span><span class="o">.</span><span class="n">increment_odometer</span><span class="p">(</span><span class="o">-</span><span class="mi">100</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">my_new_car</span><span class="o">.</span><span class="n">read_odometer</span><span class="p">()</span>
</span></span></code></pre></div><pre><code>2016 Audi A4
This car has 0 miles on it.
This car has 23 miles on it.
This car has 123 miles on it.
You can't roll back an odometer!
This car has 123 miles on it.
</code></pre>
<h2 id="003-inheritance">003 Inheritance</h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Car</span><span class="p">():</span>
</span></span><span class="line"><span class="cl">    <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">make</span><span class="p">,</span> <span class="n">model</span><span class="p">,</span> <span class="n">year</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">make</span> <span class="o">=</span> <span class="n">make</span>
</span></span><span class="line"><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">model</span> <span class="o">=</span> <span class="n">model</span>
</span></span><span class="line"><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">year</span> <span class="o">=</span> <span class="n">year</span>
</span></span><span class="line"><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">odometer_reading</span> <span class="o">=</span> <span class="mi">0</span>
</span></span><span class="line"><span class="cl">        
</span></span><span class="line"><span class="cl">    <span class="k">def</span> <span class="nf">get_descriptive_name</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="n">long_name</span> <span class="o">=</span> <span class="nb">str</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">year</span><span class="p">)</span> <span class="o">+</span> <span class="s2">&#34; &#34;</span> <span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">make</span> <span class="o">+</span> <span class="s2">&#34; &#34;</span> <span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">model</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="n">long_name</span><span class="o">.</span><span class="n">title</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="k">def</span> <span class="nf">read_odometer</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;This car has &#34;</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">odometer_reading</span><span class="p">)</span> <span class="o">+</span> <span class="s2">&#34; miles on it.&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="k">def</span> <span class="nf">update_odometer</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">mileage</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="n">mileage</span> <span class="o">&gt;</span> <span class="bp">self</span><span class="o">.</span><span class="n">odometer_reading</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="bp">self</span><span class="o">.</span><span class="n">odometer_reading</span> <span class="o">=</span> <span class="n">mileage</span>
</span></span><span class="line"><span class="cl">        <span class="k">else</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;You can&#39;t roll back an odometer!&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">            
</span></span><span class="line"><span class="cl">    <span class="k">def</span> <span class="nf">increment_odometer</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">miles</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="n">miles</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="bp">self</span><span class="o">.</span><span class="n">odometer_reading</span> <span class="o">+=</span> <span class="n">miles</span>
</span></span><span class="line"><span class="cl">        <span class="k">else</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;You can&#39;t roll back an odometer!&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">            
</span></span><span class="line"><span class="cl">    <span class="k">def</span> <span class="nf">fill_gas_tank</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;Filled!&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">ElectricCar</span><span class="p">(</span><span class="n">Car</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">make</span><span class="p">,</span> <span class="n">model</span><span class="p">,</span> <span class="n">year</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="n">make</span><span class="p">,</span> <span class="n">model</span><span class="p">,</span> <span class="n">year</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">battery_size</span> <span class="o">=</span> <span class="mi">70</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="k">def</span> <span class="nf">describe_battery</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;This car has a &#34;</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">battery_size</span><span class="p">)</span> <span class="o">+</span> <span class="s2">&#34;-kWh battery.&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        
</span></span><span class="line"><span class="cl">    <span class="k">def</span> <span class="nf">fill_gas_tank</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;This car doesn&#39;t need a gas tank!&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        
</span></span><span class="line"><span class="cl"><span class="n">my_tesla</span> <span class="o">=</span> <span class="n">ElectricCar</span><span class="p">(</span><span class="s1">&#39;tesla&#39;</span><span class="p">,</span> <span class="s1">&#39;model s&#39;</span><span class="p">,</span> <span class="mi">2016</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">my_tesla</span><span class="o">.</span><span class="n">get_descriptive_name</span><span class="p">())</span>
</span></span><span class="line"><span class="cl"><span class="n">my_tesla</span><span class="o">.</span><span class="n">describe_battery</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="n">my_tesla</span><span class="o">.</span><span class="n">fill_gas_tank</span><span class="p">()</span>
</span></span></code></pre></div><pre><code>2016 Tesla Model S
This car has a 70-kWh battery.
This car doesn't need a gas tank!
</code></pre>
<p>  Don&rsquo;t forget <code>self</code> !!!</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Car</span><span class="p">():</span>
</span></span><span class="line"><span class="cl">    <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">make</span><span class="p">,</span> <span class="n">model</span><span class="p">,</span> <span class="n">year</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">make</span> <span class="o">=</span> <span class="n">make</span>
</span></span><span class="line"><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">model</span> <span class="o">=</span> <span class="n">model</span>
</span></span><span class="line"><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">year</span> <span class="o">=</span> <span class="n">year</span>
</span></span><span class="line"><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">odometer_reading</span> <span class="o">=</span> <span class="mi">0</span>
</span></span><span class="line"><span class="cl">        
</span></span><span class="line"><span class="cl">    <span class="k">def</span> <span class="nf">get_descriptive_name</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="n">long_name</span> <span class="o">=</span> <span class="nb">str</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">year</span><span class="p">)</span> <span class="o">+</span> <span class="s2">&#34; &#34;</span> <span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">make</span> <span class="o">+</span> <span class="s2">&#34; &#34;</span> <span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">model</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="n">long_name</span><span class="o">.</span><span class="n">title</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="k">def</span> <span class="nf">read_odometer</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;This car has &#34;</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">odometer_reading</span><span class="p">)</span> <span class="o">+</span> <span class="s2">&#34; miles on it.&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="k">def</span> <span class="nf">update_odometer</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">mileage</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="n">mileage</span> <span class="o">&gt;</span> <span class="bp">self</span><span class="o">.</span><span class="n">odometer_reading</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="bp">self</span><span class="o">.</span><span class="n">odometer_reading</span> <span class="o">=</span> <span class="n">mileage</span>
</span></span><span class="line"><span class="cl">        <span class="k">else</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;You can&#39;t roll back an odometer!&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">            
</span></span><span class="line"><span class="cl">    <span class="k">def</span> <span class="nf">increment_odometer</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">miles</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="n">miles</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="bp">self</span><span class="o">.</span><span class="n">odometer_reading</span> <span class="o">+=</span> <span class="n">miles</span>
</span></span><span class="line"><span class="cl">        <span class="k">else</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;You can&#39;t roll back an odometer!&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">            
</span></span><span class="line"><span class="cl">    <span class="k">def</span> <span class="nf">fill_gas_tank</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;Filled!&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Battery</span><span class="p">():</span>
</span></span><span class="line"><span class="cl">    <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">battery_size</span><span class="o">=</span><span class="mi">70</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">battery_size</span> <span class="o">=</span> <span class="n">battery_size</span>
</span></span><span class="line"><span class="cl">        
</span></span><span class="line"><span class="cl">    <span class="k">def</span> <span class="nf">describe_battery</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;This car has a &#34;</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">battery_size</span><span class="p">)</span> <span class="o">+</span> <span class="s2">&#34;-kWh battery.&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        
</span></span><span class="line"><span class="cl">    <span class="k">def</span> <span class="nf">get_range</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">battery_size</span> <span class="o">==</span> <span class="mi">70</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="nb">range</span> <span class="o">=</span> <span class="mi">240</span>
</span></span><span class="line"><span class="cl">        <span class="k">elif</span> <span class="bp">self</span><span class="o">.</span><span class="n">battery_size</span> <span class="o">==</span> <span class="mi">85</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="nb">range</span> <span class="o">=</span> <span class="mi">270</span>
</span></span><span class="line"><span class="cl">            
</span></span><span class="line"><span class="cl">        <span class="n">message</span> <span class="o">=</span> <span class="s2">&#34;This car can go approximately &#34;</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="nb">range</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="n">message</span> <span class="o">+=</span> <span class="s2">&#34; miles on a full charge.&#34;</span>
</span></span><span class="line"><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="n">message</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">ElectricCar</span><span class="p">(</span><span class="n">Car</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">make</span><span class="p">,</span> <span class="n">model</span><span class="p">,</span> <span class="n">year</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="n">make</span><span class="p">,</span> <span class="n">model</span><span class="p">,</span> <span class="n">year</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">battery</span> <span class="o">=</span> <span class="n">Battery</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">        
</span></span><span class="line"><span class="cl">    <span class="k">def</span> <span class="nf">fill_gas_tank</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;This car doesn&#39;t need a gas tank!&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        
</span></span><span class="line"><span class="cl"><span class="n">my_tesla</span> <span class="o">=</span> <span class="n">ElectricCar</span><span class="p">(</span><span class="s1">&#39;tesla&#39;</span><span class="p">,</span> <span class="s1">&#39;model s&#39;</span><span class="p">,</span> <span class="mi">2016</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">my_tesla</span><span class="o">.</span><span class="n">get_descriptive_name</span><span class="p">())</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">my_tesla</span><span class="o">.</span><span class="n">battery</span><span class="o">.</span><span class="n">describe_battery</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="n">my_tesla</span><span class="o">.</span><span class="n">battery</span><span class="o">.</span><span class="n">get_range</span><span class="p">()</span>
</span></span></code></pre></div><pre><code>2016 Tesla Model S
This car has a 70-kWh battery.
This car can go approximately 240 miles on a full charge.
</code></pre>
<h2 id="004-import-class">004 Import Class</h2>
<p>  Similar to import functions.</p>
<h2 id="005-python-standard-library">005 Python Standard Library</h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">collections</span> <span class="kn">import</span> <span class="n">OrderedDict</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">favorite_languages</span> <span class="o">=</span> <span class="n">OrderedDict</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">favorite_languages</span><span class="p">[</span><span class="s1">&#39;jen&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s1">&#39;python&#39;</span>
</span></span><span class="line"><span class="cl"><span class="n">favorite_languages</span><span class="p">[</span><span class="s1">&#39;sarah&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s1">&#39;c&#39;</span>
</span></span><span class="line"><span class="cl"><span class="n">favorite_languages</span><span class="p">[</span><span class="s1">&#39;edward&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s1">&#39;ruby&#39;</span>
</span></span><span class="line"><span class="cl"><span class="n">favorite_languages</span><span class="p">[</span><span class="s1">&#39;phil&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s1">&#39;python&#39;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">for</span> <span class="n">name</span><span class="p">,</span> <span class="n">language</span> <span class="ow">in</span> <span class="n">favorite_languages</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="n">name</span><span class="o">.</span><span class="n">title</span><span class="p">()</span> <span class="o">+</span> <span class="s2">&#34;&#39;s favorite language is &#34;</span> <span class="o">+</span>
</span></span><span class="line"><span class="cl">         <span class="n">language</span><span class="o">.</span><span class="n">title</span><span class="p">()</span> <span class="o">+</span> <span class="s2">&#34;.&#34;</span><span class="p">)</span>
</span></span></code></pre></div><pre><code>Jen's favorite language is Python.
Sarah's favorite language is C.
Edward's favorite language is Ruby.
Phil's favorite language is Python.
</code></pre>
<hr>
]]></content:encoded>
    </item>
  </channel>
</rss>
