{
  "version": "https://jsonfeed.org/version/1.1",
  "title": "AI悦创-Python一对一辅导",
  "home_page_url": "https://bornforthis.cn/",
  "feed_url": "https://bornforthis.cn/feed.json",
  "description": "Python 1v1,AI悦创,一对一,Python,编程一对一,C++,Java,AI,人工智能,黄家宝,Python一对一教学",
  "icon": "https://bornforthis.cn/aiyc.png",
  "favicon": "https://bornforthis.cn/python",
  "items": [
    {
      "title": "Wang AI泛娱乐创业讨论",
      "url": "https://bornforthis.cn/blog/2026/ai-entertainment-startup-discussion.html",
      "id": "https://bornforthis.cn/blog/2026/ai-entertainment-startup-discussion.html",
      "summary": "First Second 核心原则：低成本试错、技术落地为先、共创共享、快速验证。 一、会议核心共识 项目本质是AI 技术应用与研究型公司，非单纯做视频 / 流量，视频号仅为首个技术验证切口，最终目标是为制造业、政府、企业等主体提供低成本 AI 内容制作与推广服务。 核心逻辑是小成本多方向试错，失败是大概率事件，试错的核心价值是积累技术、运营经验和数据...",
      "content_html": "<h2>First</h2>\n\n<h2>Second</h2>\n<p><strong>核心原则</strong>：低成本试错、技术落地为先、共创共享、快速验证。</p>\n<h3>一、会议核心共识</h3>\n<ol>\n<li>项目本质是<strong>AI 技术应用与研究型公司</strong>，非单纯做视频 / 流量，视频号仅为首个技术验证切口，最终目标是为制造业、政府、企业等主体提供低成本 AI 内容制作与推广服务。</li>\n<li>核心逻辑是<strong>小成本多方向试错</strong>，失败是大概率事件，试错的核心价值是积累技术、运营经验和数据，而非追求短期盈利。</li>\n<li>团队模式为<strong>互联网化共创</strong>，拒绝大厂病、熟人思维，专业优先，线上远程协作为主，快速落地执行。</li>\n<li>利益分配采用<strong>股权代币化 + 上链</strong>，前期共创者收入为 “现金 + 公司代币”，代币与股权完全捆绑，验证成功后代币同步增值。</li>\n<li>AI 的核心定位是<strong>生产工具</strong>，创意 + 工具高效使用才是核心竞争力，无需研发全新 AI 产品，优先组合主流开源 AI 工具实现功能落地。</li>\n</ol>\n<h3>二、项目核心定位与愿景</h3>\n<ol>\n<li><strong>公司名称</strong>：AI 乐创计算机技术有限公司（谐音 “开心创新”，贴合 AI 技术探索与创意结合的核心）</li>\n<li><strong>核心愿景</strong>：做 AI 技术应用下沉的实践者，通过工具组合与场景验证，打造低成本、可复制的 AI 内容生产与服务体系，积累技术能力并实现商业落地。</li>\n<li><strong>核心价值</strong>：盘活自有算力资源、降低 AI 工具使用与内容制作成本、沉淀各场景 AI 应用的技术和运营经验。</li>\n<li><strong>业务路径</strong>：先通过视频号验证 AI 内容生产全流程能力→沉淀方法论与数据→为 B 端（制造业、政府、企业）提供 AI 内容制作与推广服务→拓展 AI 技术在更多垂直领域的应用。</li>\n</ol>\n<h3>三、落地执行核心步骤（分三阶段）</h3>\n<p>结合个人网站 “内容测试 - 数据反馈 - 迭代优化” 的运营逻辑，项目落地分三步走，每一步设明确目标与验收标准：</p>\n<h4>筹备期（1-2 周）</h4>\n<ol>\n<li>输出项目<strong>共创白皮书 / 章程</strong>（AI 生成初稿后人工优化，明确愿景、规则、利益、分工）；</li>\n<li>敲定核心启动预算，设定<strong>成本亏损红线</strong>（亏得有度，无意义的试错及时止损）；</li>\n<li>梳理自有资源（算力集群、人脉、启动资金），对接外部开源 AI 工具 / API；</li>\n<li>搭建核心共创群，明确首批招募角色与能力要求。</li>\n</ol>\n<h4>验证期（1-3 个月，核心试错阶段）</h4>\n<ol>\n<li>选定 2-3 个视频号题材（结合平台流量数据、下沉市场需求，如财经、动漫、泛娱乐等），小预算启动；</li>\n<li>搭建 AI 内容生产体系：组合 OpenCloud 等主流 AI 工具，实现内容自动抓取、分析、发布的基础功能；</li>\n<li>按 “测试 - 数据反馈 - 策略调整” 循环，每周复盘各题材流量、传播率，快速淘汰低效果题材；</li>\n<li>积累内容生产数据与平台运营经验，同步完成 AI 内容版权审核流程搭建，规避侵权风险。</li>\n</ol>\n<h4>迭代期（3 个月后）</h4>\n<ol>\n<li>沉淀可复制的 AI 视频号运营方法论，形成标准化操作流程；</li>\n<li>基于验证期能力，初步对接小型 B 端需求，测试 AI 内容制作的商业落地效果；</li>\n<li>梳理算力资源本地化部署实操方案，进一步降低 AI 工具使用成本；</li>\n<li>对接投资机构，基于已验证的模式争取更多资金，扩大试错与落地范围。</li>\n</ol>\n<h3>四、人员配置与核心能力要求</h3>\n<p>按 “少而精、专业优先” 原则配置，拒绝冗余岗位，各角色需贴合 AI 工具使用与互联网运营特点，结合个人网站线上招募 / 协作经验，明确核心能力要求：</p>\n<p>| 角色       | 核心能力要求                                                 |<br>\n|</p>\n",
      "image": "https://bornforthis.cn/gzh.jpg",
      "date_published": "2026-02-26T08:36:54.000Z",
      "date_modified": "2026-02-26T01:18:55.000Z",
      "authors": [
        {
          "name": "AI悦创"
        }
      ],
      "tags": []
    },
    {
      "title": "COMP1730 Final Exam Submissions",
      "url": "https://bornforthis.cn/1v1/101-Sallymisty/Mid-Final-Exam/COMP1730-Final-Exam-Submissions.html",
      "id": "https://bornforthis.cn/1v1/101-Sallymisty/Mid-Final-Exam/COMP1730-Final-Exam-Submissions.html",
      "summary": "Question 1: Improving code quality (5/40) An integer b is called a non-trivial divisor of a positive integer n if b is between 2 and n−1 such that nn is divisible by b, meaning ...",
      "content_html": "<h2>Question 1: Improving code quality (5/40)</h2>\n<p>An integer <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>b</mi></mrow><annotation encoding=\"application/x-tex\">b</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6944em;\"></span><span class=\"mord mathnormal\">b</span></span></span></span> is called a <em>non-trivial divisor</em> of a positive integer <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>n</mi></mrow><annotation encoding=\"application/x-tex\">n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.4306em;\"></span><span class=\"mord mathnormal\">n</span></span></span></span> if <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>b</mi></mrow><annotation encoding=\"application/x-tex\">b</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6944em;\"></span><span class=\"mord mathnormal\">b</span></span></span></span> is between 2 and <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>n</mi><mo>−</mo><mn>1</mn></mrow><annotation encoding=\"application/x-tex\">n−1</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6667em;vertical-align:-0.0833em;\"></span><span class=\"mord mathnormal\">n</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">−</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6444em;\"></span><span class=\"mord\">1</span></span></span></span> such that n<em>n</em> is divisible by <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>b</mi></mrow><annotation encoding=\"application/x-tex\">b</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6944em;\"></span><span class=\"mord mathnormal\">b</span></span></span></span>, meaning that the remainder of the integer division n<em>n</em> by <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>b</mi></mrow><annotation encoding=\"application/x-tex\">b</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6944em;\"></span><span class=\"mord mathnormal\">b</span></span></span></span> is zero. The following <strong>correct</strong> function takes as input a positive integer, and returns how many non-trivial divisors are there for the given input.</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> do_it</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">xxx</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    tHeReSuLt</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    u</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    while</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> u</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&lt;=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">xxx</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">//</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">        # check if divides</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> xxx</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">%</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">u</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">==</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">            # exclude some random numbers</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">            if</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> not</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(u</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">==</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> or</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> u</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">==</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">xxx):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">                tHeReSuLt</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">tHeReSuLt</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        else</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">            pass</span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"> # do nothing lol</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">        # increment but not really important</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">        u</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">u</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    return</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> int</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">str</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(tHeReSuLt))</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>Describe all <strong>distinct</strong> ways in which the quality of the code above can be improved without affecting to its functional correctness.</p>\n<p>To gain marks, your suggested improvements must be specific. For example, if you think that naming should be improved, you must give at least one specific example of which names should be changed and to what; just answering \"better names\" is not enough. Do not simply write your suggested improvements as comments inside the function. Writing a new function or rewriting the function is not an acceptable answer, regardless of whether it is correct or not.</p>\n<p><strong>Response</strong></p>\n\n\n<h2>Question 2: Testing (5/40)</h2>\n<p>We want to write tests for a function with signature and docstring defined as follows:</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> sequence_dissimilarity</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">s1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> s2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    \"\"\"</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    s1 and s2 are two sequences of the same length</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    Returns the number of i-th elements that are NOT equal</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    between two sequences, i.e., where s1[i] != s2[i]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    Assume that this comparison is always valid and evaluates to True or False</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    \"\"\"</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> sequence_dissimilarity</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">s1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> s2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    \"\"\"</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    s1 和 s2 是两个长度相同的序列</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    返回两个序列中“对应位置 i 的元素不相等”的位置数量</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    也就是统计满足 s1[i] != s2[i] 的 i 的个数</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    假设这种比较总是合法的，并且比较结果一定是 True 或 False</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    \"\"\"</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>Write <strong>at most</strong> 4 test cases for this function (every test case after the first four will be ignored). For each test case, you must write the inputs (arguments to the function) and the expected return value. You may format your answer in anyway, provided that <strong>the inputs and output can be clearly identified</strong>. Each test case should specify <strong>valid arguments</strong> for the function. Your test cases should cover relevant <strong>corner cases</strong>.</p>\n<div class=\"hint-container tip\">\n<p class=\"hint-container-title\">提示</p>\n<p>下面给出 <strong>4 个</strong>覆盖关键边界情况的测试用例（输入 + 期望输出）：</p>\n<ol>\n<li>\n<p><strong>两个空序列（长度为 0）</strong></p>\n<ul>\n<li>\n<p>输入：<code>s1 = []</code>, <code>s2 = []</code></p>\n</li>\n<li>\n<p>期望输出：<code>0</code></p>\n</li>\n</ul>\n</li>\n<li>\n<p><strong>完全相同（无任何不相等）</strong></p>\n<ul>\n<li>\n<p>输入：<code>s1 = [1, 2, 3]</code>, <code>s2 = [1, 2, 3]</code></p>\n</li>\n<li>\n<p>期望输出：<code>0</code></p>\n</li>\n</ul>\n</li>\n<li>\n<p><strong>完全不同（每个位置都不相等）</strong></p>\n<ul>\n<li>\n<p>输入：<code>s1 = \"abc\"</code>, <code>s2 = \"XYZ\"</code></p>\n</li>\n<li>\n<p>期望输出：<code>3</code></p>\n</li>\n</ul>\n</li>\n<li>\n<p><strong>部分不同 + 混合类型（比较始终合法）</strong></p>\n<ul>\n<li>\n<p>输入：<code>s1 = [1, \"2\", 3, \"x\"]</code>, <code>s2 = [1, 2, 4, \"x\"]</code></p>\n</li>\n<li>\n<p>逐位比较：<code>1==1</code>(相同), <code>\"2\"!=2</code>(不同), <code>3!=4</code>(不同), <code>\"x\"==\"x\"</code>(相同)</p>\n</li>\n<li>\n<p>期望输出：<code>2</code></p>\n</li>\n</ul>\n</li>\n</ol>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> test_sequence_dissimilarity</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">():</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">    # 1) 两个空序列（长度为0）</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    assert</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> sequence_dissimilarity</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">([], []) </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">==</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 0</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">    # 2) 完全相同（无任何不相等）</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    assert</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> sequence_dissimilarity</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">([</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">], [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]) </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">==</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 0</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">    # 3) 完全不同（每个位置都不相等）</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    assert</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> sequence_dissimilarity</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"abc\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"XYZ\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">) </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">==</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 3</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">    # 4) 部分不同 + 混合类型（比较始终合法）</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    assert</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> sequence_dissimilarity</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">([</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"2\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"x\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">], [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">4</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"x\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]) </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">==</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 2</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div></div>\n<h2>Question 3: Debugging (5/40)</h2>\n<p>The <code>argmin</code> of a sequence is the index (position) of the smallest element in the sequence. For example, if the sequence is <code>[3,4,5]</code>, the <code>argmin</code> is 0, because the smallest value is 3 and is at index 0. If the smallest value is not unique, the <code>argmin</code> function can return any index where it appears. For example, if the sequence is <code>[5,5,5]</code>, any of the indices 0, 1 or 2 is a valid answer. We assume that the input sequence is non-empty.</p>\n<p>Below is an implementation of the <code>argmin</code> function:</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> argmin</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">a</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    a </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> list</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(a)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    p </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 0</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    i </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 0</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    a.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">sort</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> x </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> a:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> x </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&lt;</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> a[p]:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">            p </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> i</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">        i </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> i </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 1</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> p</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>However, the function above is not correct:</p>\n<p><strong>(a)</strong> Provide an example of function call with arguments of correct type that makes this function return an incorrect result. <code>a</code> must be a non-empty sequence of numbers.</p>\n<p><strong>(b)</strong> Explain the cause of the error that you have found, i.e., what is wrong with this function. Your answer must explain what is wrong with the function as given. Writing a new function or rewriting/fixing the function is not an acceptable answer, regardless of whether it is correct or not.</p>\n<details class=\"hint-container details\"><summary>答案</summary>\n<h4>(a) 反例（会返回错误结果的调用）</h4>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">argmin</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">([</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">])</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div></div></div><p>正确的 <code>argmin</code> 应该返回 <code>1</code>（最小值 1 在原序列的索引是 1），但这段代码会返回 <code>0</code>。</p>\n<p>你也可以用更明显的例子：</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">argmin</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">([</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">])</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div></div></div><p>正确答案应为 <code>1</code>，但函数会返回 <code>0</code>。</p>\n<h4>(b) 错误原因解释（这段函数“哪里错了”）</h4>\n<p>核心问题是：<strong>它在计算索引之前把 <code>a</code> 排序了</strong>。</p>\n<ul>\n<li>一开始 <code>a = list(a)</code> 把输入变成列表没问题。</li>\n<li>但紧接着执行了 <code>a.sort()</code>：这一步会<strong>原地排序</strong>，把元素顺序改掉。</li>\n<li><code>argmin</code> 要返回的是“<strong>原始输入序列</strong>中最小元素的位置（索引）”，而排序以后：\n<ul>\n<li>最小元素必然跑到排序后列表的第 0 个位置</li>\n<li>所以这个函数基本上总会返回 0（除非你想象它还会找到更小的，但排序后不可能有 <code>x &lt; a[0]</code>）</li>\n</ul>\n</li>\n</ul>\n<p>更具体地说，在 <code>for x in a:</code> 这段循环中：</p>\n<ul>\n<li>排序后 <code>a[p]</code> 初始是 <code>a[0]</code>，也就是最小值</li>\n<li>对任何元素 <code>x</code> 来说，都不可能满足 <code>x &lt; a[p]</code>（因为 <code>a[p]</code> 已经是最小）</li>\n<li>因此 <code>p</code> 永远不会更新，始终是 0</li>\n<li>最终 <code>return p</code> 返回 0，<strong>这不是原序列的 argmin，而是“排序后序列”的位置</strong></li>\n</ul>\n<p>总结一句：<strong>排序破坏了原始索引信息，导致返回的索引与输入序列的位置无关</strong>。</p>\n</details>\n\n<h2>Question 4.1: Time complexity (2/40)</h2>\n<p>Consider the function:</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> g</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">A</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    res </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 0.0</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> i </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> range</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(A.shape[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> j </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> range</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(i, A.shape[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">            res </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> A[i, j]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> res</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>where <code>A</code> is an <code>n</code> by <code>n</code> 2D NumPy array of floating-point numbers (<code>A.shape[0] == A.shape[1] == n</code>).</p>\n<p>Write down the time complexity of <code>g(A)</code> in big-O notation as a function of <code>n</code> . <strong>Explain the reason why</strong>, e.g., by analysing the code line by line and summarising it**.** Correct time complexity without sufficient explanation and reasoning will receive zero marks.</p>\n<details class=\"hint-container details\"><summary>详情</summary>\n<p><strong>题目代码</strong></p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> g</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">A</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    res </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 0.0</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> i </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> range</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(A.shape[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> j </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> range</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(i, A.shape[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">            res </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> A[i, j]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> res</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>已知：</p>\n<ul>\n<li><code>A</code> 是一个 <code>n × n</code> 的 NumPy 数组</li>\n<li><code>A.shape[0] == A.shape[1] == n</code></li>\n</ul>\n<p><strong>🔍 第一步：逐行分析</strong></p>\n<ul>\n<li>\n<p>① <code>res = 0.0</code></p>\n<p>这是常数时间操作：<span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mn>1</mn><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(1)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord\">1</span><span class=\"mclose\">)</span></span></span></span></p>\n</li>\n<li>\n<p>② 外层循环</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> i </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> range</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(A.shape[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]):</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div></div></div><p>因为 <code>A.shape[0] = n</code>，所以外层循环执行：<span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>n</mi><mtext>&nbsp;次</mtext></mrow><annotation encoding=\"application/x-tex\">n \\text{ 次}</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\">n</span><span class=\"mord text\"><span class=\"mord\">&nbsp;</span><span class=\"mord cjk_fallback\">次</span></span></span></span></span></p>\n</li>\n<li>\n<p>③ 内层循环</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> j </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> range</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(i, A.shape[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]):</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div></div></div><p>这里是关键，当 <code>i = 0</code> 时：</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">j 从 </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> 到 n</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">执行 n 次</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>当 <code>i = 1</code> 时：</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">j 从 </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> 到 n</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">执行 n</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> 次</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>当 <code>i = 2</code> 时：</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">执行 n</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> 次</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div></div></div><p>……</p>\n<p>当 <code>i = n-1</code> 时：</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">执行 </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> 次</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div></div></div></li>\n</ul>\n<p><strong>🔢 总执行次数计算</strong></p>\n<p>总的 <code>res += A[i, j]</code> 执行次数为：</p>\n<p v-pre=\"\" class=\"katex-block\"><span class=\"katex-display\"><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\" display=\"block\"><semantics><mrow><mi>n</mi><mo>+</mo><mo stretchy=\"false\">(</mo><mi>n</mi><mo>−</mo><mn>1</mn><mo stretchy=\"false\">)</mo><mo>+</mo><mo stretchy=\"false\">(</mo><mi>n</mi><mo>−</mo><mn>2</mn><mo stretchy=\"false\">)</mo><mo>+</mo><mo>⋯</mo><mo>+</mo><mn>1</mn></mrow><annotation encoding=\"application/x-tex\">n + (n-1) + (n-2) + \\dots + 1\n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6667em;vertical-align:-0.0833em;\"></span><span class=\"mord mathnormal\">n</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">n</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">−</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord\">1</span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">n</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">−</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord\">2</span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6667em;vertical-align:-0.0833em;\"></span><span class=\"minner\">⋯</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6444em;\"></span><span class=\"mord\">1</span></span></span></span></span></p>\n<p>这是一个等差数列求和：</p>\n<p v-pre=\"\" class=\"katex-block\"><span class=\"katex-display\"><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\" display=\"block\"><semantics><mrow><mfrac><mrow><mi>n</mi><mo stretchy=\"false\">(</mo><mi>n</mi><mo>+</mo><mn>1</mn><mo stretchy=\"false\">)</mo></mrow><mn>2</mn></mfrac></mrow><annotation encoding=\"application/x-tex\">\\frac{n(n+1)}{2}\n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:2.113em;vertical-align:-0.686em;\"></span><span class=\"mord\"><span class=\"mopen nulldelimiter\"></span><span class=\"mfrac\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:1.427em;\"><span style=\"top:-2.314em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"mord\"><span class=\"mord\">2</span></span></span><span style=\"top:-3.23em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"frac-line\" style=\"border-bottom-width:0.04em;\"></span></span><span style=\"top:-3.677em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">n</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">n</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mord\">1</span><span class=\"mclose\">)</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.686em;\"><span></span></span></span></span></span><span class=\"mclose nulldelimiter\"></span></span></span></span></span></span></p>\n<p>展开：</p>\n<p v-pre=\"\" class=\"katex-block\"><span class=\"katex-display\"><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\" display=\"block\"><semantics><mrow><mo>=</mo><mfrac><mrow><msup><mi>n</mi><mn>2</mn></msup><mo>+</mo><mi>n</mi></mrow><mn>2</mn></mfrac></mrow><annotation encoding=\"application/x-tex\">= \\frac{n^2 + n}{2}\n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.3669em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:2.1771em;vertical-align:-0.686em;\"></span><span class=\"mord\"><span class=\"mopen nulldelimiter\"></span><span class=\"mfrac\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:1.4911em;\"><span style=\"top:-2.314em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"mord\"><span class=\"mord\">2</span></span></span><span style=\"top:-3.23em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"frac-line\" style=\"border-bottom-width:0.04em;\"></span></span><span style=\"top:-3.677em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"mord\"><span class=\"mord\"><span class=\"mord mathnormal\">n</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8141em;\"><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mord mathnormal\">n</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.686em;\"><span></span></span></span></span></span><span class=\"mclose nulldelimiter\"></span></span></span></span></span></span></p>\n<p><strong>🎯 时间复杂度分析</strong></p>\n<p>最高阶项是：</p>\n<p v-pre=\"\" class=\"katex-block\"><span class=\"katex-display\"><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\" display=\"block\"><semantics><mrow><mfrac><msup><mi>n</mi><mn>2</mn></msup><mn>2</mn></mfrac></mrow><annotation encoding=\"application/x-tex\">\\frac{n^2}{2}\n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:2.1771em;vertical-align:-0.686em;\"></span><span class=\"mord\"><span class=\"mopen nulldelimiter\"></span><span class=\"mfrac\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:1.4911em;\"><span style=\"top:-2.314em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"mord\"><span class=\"mord\">2</span></span></span><span style=\"top:-3.23em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"frac-line\" style=\"border-bottom-width:0.04em;\"></span></span><span style=\"top:-3.677em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"mord\"><span class=\"mord\"><span class=\"mord mathnormal\">n</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8141em;\"><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span></span></span></span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.686em;\"><span></span></span></span></span></span><span class=\"mclose nulldelimiter\"></span></span></span></span></span></span></p>\n<p>在 Big-O 表示法中：</p>\n<ul>\n<li>忽略常数</li>\n<li>忽略低阶项</li>\n</ul>\n<p>所以：</p>\n<p v-pre=\"\" class=\"katex-block\"><span class=\"katex-display\"><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\" display=\"block\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><msup><mi>n</mi><mn>2</mn></msup><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(n^2)\n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1.1141em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord\"><span class=\"mord mathnormal\">n</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8641em;\"><span style=\"top:-3.113em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span></span></span></span></span><span class=\"mclose\">)</span></span></span></span></span></p>\n<p><strong>📌 更直观理解</strong></p>\n<p>这段代码：</p>\n<ul>\n<li>不是遍历整个矩阵</li>\n<li>而是遍历矩阵的<strong>上三角部分（包括对角线）</strong></li>\n</ul>\n<p>矩阵一共有：</p>\n<p v-pre=\"\" class=\"katex-block\"><span class=\"katex-display\"><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\" display=\"block\"><semantics><mrow><msup><mi>n</mi><mn>2</mn></msup></mrow><annotation encoding=\"application/x-tex\">n^2\n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8641em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">n</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8641em;\"><span style=\"top:-3.113em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span></span></span></span></span></span></span></span></span></p>\n<p>个元素。</p>\n<p>而代码访问了：</p>\n<p v-pre=\"\" class=\"katex-block\"><span class=\"katex-display\"><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\" display=\"block\"><semantics><mrow><mfrac><mrow><mi>n</mi><mo stretchy=\"false\">(</mo><mi>n</mi><mo>+</mo><mn>1</mn><mo stretchy=\"false\">)</mo></mrow><mn>2</mn></mfrac></mrow><annotation encoding=\"application/x-tex\">\\frac{n(n+1)}{2}\n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:2.113em;vertical-align:-0.686em;\"></span><span class=\"mord\"><span class=\"mopen nulldelimiter\"></span><span class=\"mfrac\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:1.427em;\"><span style=\"top:-2.314em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"mord\"><span class=\"mord\">2</span></span></span><span style=\"top:-3.23em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"frac-line\" style=\"border-bottom-width:0.04em;\"></span></span><span style=\"top:-3.677em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">n</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">n</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mord\">1</span><span class=\"mclose\">)</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.686em;\"><span></span></span></span></span></span><span class=\"mclose nulldelimiter\"></span></span></span></span></span></span></p>\n<p>个元素，这仍然是二次级别增长。</p>\n<p><strong>最终答案</strong></p>\n<p v-pre=\"\" class=\"katex-block\"><span class=\"katex-display\"><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\" display=\"block\"><semantics><mrow><menclose notation=\"box\"><mstyle scriptlevel=\"0\" displaystyle=\"false\"><mstyle scriptlevel=\"0\" displaystyle=\"false\"><mstyle scriptlevel=\"0\" displaystyle=\"true\"><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><msup><mi>n</mi><mn>2</mn></msup><mo stretchy=\"false\">)</mo></mrow></mstyle></mstyle></mstyle></menclose></mrow><annotation encoding=\"application/x-tex\">\\boxed{O(n^2)}\n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1.7941em;vertical-align:-0.59em;\"></span><span class=\"mord\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:1.2041em;\"><span style=\"top:-3.7941em;\"><span class=\"pstrut\" style=\"height:3.7941em;\"></span><span class=\"boxpad\"><span class=\"mord\"><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord\"><span class=\"mord mathnormal\">n</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8641em;\"><span style=\"top:-3.113em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span></span></span></span></span><span class=\"mclose\">)</span></span></span></span></span><span style=\"top:-3.2041em;\"><span class=\"pstrut\" style=\"height:3.7941em;\"></span><span class=\"stretchy fbox\" style=\"height:1.7941em;border-style:solid;border-width:0.04em;\"></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.59em;\"><span></span></span></span></span></span></span></span></span></span></p>\n<p><strong>📌 总结一句话</strong></p>\n<p>虽然内层循环从 <code>i</code> 开始减少了次数，但所有迭代次数加起来仍然是：</p>\n<p v-pre=\"\" class=\"katex-block\"><span class=\"katex-display\"><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\" display=\"block\"><semantics><mrow><mfrac><mrow><mi>n</mi><mo stretchy=\"false\">(</mo><mi>n</mi><mo>+</mo><mn>1</mn><mo stretchy=\"false\">)</mo></mrow><mn>2</mn></mfrac></mrow><annotation encoding=\"application/x-tex\">\\frac{n(n+1)}{2}\n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:2.113em;vertical-align:-0.686em;\"></span><span class=\"mord\"><span class=\"mopen nulldelimiter\"></span><span class=\"mfrac\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:1.427em;\"><span style=\"top:-2.314em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"mord\"><span class=\"mord\">2</span></span></span><span style=\"top:-3.23em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"frac-line\" style=\"border-bottom-width:0.04em;\"></span></span><span style=\"top:-3.677em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">n</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">n</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mord\">1</span><span class=\"mclose\">)</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.686em;\"><span></span></span></span></span></span><span class=\"mclose nulldelimiter\"></span></span></span></span></span></span></p>\n<p>其增长阶为：</p>\n<p v-pre=\"\" class=\"katex-block\"><span class=\"katex-display\"><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\" display=\"block\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><msup><mi>n</mi><mn>2</mn></msup><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(n^2)\n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1.1141em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord\"><span class=\"mord mathnormal\">n</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8641em;\"><span style=\"top:-3.113em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span></span></span></span></span><span class=\"mclose\">)</span></span></span></span></span></p>\n</details>\n<h2>时间复杂度汇总</h2>\n<h3>1. 时间复杂度怎么判断（核心规则）</h3>\n<p>把程序想象成：输入规模为 <code>n</code> 时，会执行多少次“基本操作”（比较、加减、赋值、访问数组等）。</p>\n<ul>\n<li><strong>忽略常数</strong>：<code>3n + 20</code> 记为 <code>O(n)</code></li>\n<li><strong>只看最高阶</strong>：<code>n^2 + n</code> 记为 <code>O(n^2)</code></li>\n<li><strong>顺序相加</strong>：先做 A 再做 B → <code>O(A + B)</code></li>\n<li><strong>嵌套相乘</strong>：外层 <code>n</code> 次、内层 <code>n</code> 次 → <code>O(n * n) = O(n^2)</code></li>\n<li><strong>每次规模减半</strong>：<code>n → n/2 → n/4 ...</code> 是 <code>O(log n)</code></li>\n<li><strong>分支暴增</strong>（枚举子集/排列）通常是指数级或阶乘级</li>\n</ul>\n<h3>2. O(1) 常数时间</h3>\n<p><strong>特点</strong>：执行次数不随 <code>n</code> 变。</p>\n<p><strong>代码示例：数组索引访问</strong></p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> get_middle</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">a</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> a[</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(a)</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">//</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]  </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 访问一次</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p><strong>为什么是 O(1)</strong>：无论 <code>a</code> 多长，都只做固定次数操作（求长度、除法、一次索引）。</p>\n<blockquote>\n<p>典型：取数组某个位置、交换两个变量、栈/队列的 push/pop（在实现良好时）。</p>\n</blockquote>\n<h3>3. O(log n) 对数时间</h3>\n<p><strong>特点</strong>：每一步把问题规模“砍半/按比例缩小”。</p>\n<p><strong>代码示例：二分查找</strong></p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> binary_search</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">a</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> target</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    lo, hi </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(a) </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 1</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    while</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> lo </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&lt;=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> hi:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">        mid </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> (lo </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> hi) </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">//</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 2</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> a[mid] </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">==</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> target:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">            return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> mid</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        elif</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> a[mid] </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&lt;</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> target:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">            lo </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> mid </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 1</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        else</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">            hi </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> mid </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 1</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> -</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p><strong>为什么是 O(log n)</strong>：每次循环把区间缩小一半：<code>n → n/2 → n/4 → ... → 1</code> 需要的步数是 <code>log2(n)</code> 级别。</p>\n<h3>4. O(√n)（很常见但容易忽略）</h3>\n<p><strong>特点</strong>：循环到 <code>sqrt(n)</code> 就能解决（常见于数论）。</p>\n<p><strong>代码示例：判断是否有非平凡因子（试除到 √n）</strong></p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> has_divisor</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">n</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    i </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 2</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    while</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> i </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">*</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> i </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&lt;=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> n:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> n </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">%</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> i </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">==</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">            return</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> True</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">        i </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 1</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    return</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> False</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p><strong>为什么是 O(√n)</strong>：<code>i*i &lt;= n</code> ⇒ <code>i &lt;= √n</code>，最多尝试约 <code>√n</code> 次。</p>\n<h3>4. O(n) 线性时间</h3>\n<p><strong>特点</strong>：把输入完整扫一遍。</p>\n<p><strong>代码示例：线性查找</strong></p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> linear_search</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">a</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> target</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> i, x </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> enumerate</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(a):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> x </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">==</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> target:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">            return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> i</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> -</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p><strong>为什么是 O(n)</strong>：最坏情况下要检查 <code>n</code> 个元素。</p>\n<blockquote>\n<p>注意：有些操作“看起来一行”，但可能是 O(n)，例如 Python 的 <code>x in list</code>、<code>list.count</code>、<code>list.remove</code> 等都要线性扫描。</p>\n</blockquote>\n<h3>5. O(n + m)（两个规模相加）</h3>\n<p><strong>特点</strong>：分别扫两份数据，各扫一遍。</p>\n<p><strong>代码示例：合并两个数组（不排序）</strong></p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> concat</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">a</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> b</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    res </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> []</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> x </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> a:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">        res.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">append</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(x)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> y </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> b:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">        res.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">append</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(y)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> res</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p><strong>为什么是 O(n + m)</strong>：第一段做 <code>n</code> 次，第二段做 <code>m</code> 次，总计相加。</p>\n<blockquote>\n<p>图算法里常见 <code>O(V + E)</code>（点+边），也是同理。</p>\n</blockquote>\n<h3>6. O(n log n)（最常见的“高效排序/分治”复杂度）</h3>\n<p><strong>特点</strong>：通常是 <strong>分治</strong>：分成若干份（log 层），每层做 O(n) 工作。</p>\n<p><strong>代码示例：归并排序（经典）</strong></p>\n<div class=\"language-python line-numbers-mode has-collapsed-lines collapsed\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--vp-collapsed-lines:15;--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> merge_sort</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">a</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    if</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(a) </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&lt;=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> a</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    mid </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(a) </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">//</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 2</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    left </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> merge_sort</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(a[:mid])</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    right </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> merge_sort</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(a[mid:])</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> merge</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(left, right)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> merge</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">left</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> right</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    i </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> j </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 0</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    res </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> []</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    while</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> i </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&lt;</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(left) </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">and</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> j </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&lt;</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(right):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> left[i] </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&lt;=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> right[j]:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">            res.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">append</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(left[i]); i </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 1</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        else</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">            res.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">append</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(right[j]); j </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 1</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    res.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">extend</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(left[i:])</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    res.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">extend</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(right[j:])</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> res</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div><div class=\"collapsed-lines\"></div></div><p><strong>为什么是 O(n log n)</strong>：</p>\n<ul>\n<li>分裂次数：<code>n → n/2 → ...</code> 有 <code>log n</code> 层</li>\n<li>每一层合并总工作量：把所有元素合并一遍，总计 <code>O(n)</code></li>\n<li>所以总计：<code>O(n) * O(log n) = O(n log n)</code></li>\n</ul>\n<blockquote>\n<p>现实中：大多数比较排序在平均/最坏可做到 <code>O(n log n)</code>（归并、堆排序），快速排序平均 <code>O(n log n)</code> 但最坏 <code>O(n^2)</code>。</p>\n</blockquote>\n<h3>7. O(n²) 二次时间（双重循环/两两比较）</h3>\n<p><strong>特点</strong>：所有“成对组合”类问题很容易出现。</p>\n<p><strong>代码示例：统计所有配对 (i, j)</strong></p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> count_pairs</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">a</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    n </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(a)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    c </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 0</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> i </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> range</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(n):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> j </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> range</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(n):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">            c </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 1</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> c</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p><strong>为什么是 O(n²)</strong>：外层 n 次，内层 n 次，总 <code>n*n</code>。</p>\n<p><strong>更真实一点：两两比较是否相等</strong></p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> has_duplicate_slow</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">a</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    n </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(a)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> i </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> range</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(n):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> j </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> range</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(i </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, n):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">            if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> a[i] </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">==</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> a[j]:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">                return</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> True</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    return</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> False</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>这里比较次数约为 <code>n(n-1)/2</code>，仍是 <code>O(n²)</code>（忽略常数 1/2）。</p>\n<h3>8. O(n³) 三次时间（3 层嵌套/某些 DP）</h3>\n<h3>代码示例：三重循环</h3>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> triple_work</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">n</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    c </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 0</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> i </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> range</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(n):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> j </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> range</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(n):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">            for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> k </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> range</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(n):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">                c </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 1</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> c</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p><strong>为什么是 O(n³)</strong>：<code>n * n * n</code>。</p>\n<blockquote>\n<p>典型：Floyd-Warshall 全源最短路就是 <code>O(n³)</code>（n 个点）。</p>\n</blockquote>\n<h3>9. O(2^n) 指数时间（枚举所有子集 / 爆炸）</h3>\n<p><strong>代码示例：生成所有子集</strong></p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> all_subsets</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">a</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    n </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(a)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    res </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> []</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> mask </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> range</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> &lt;&lt;</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> n):      </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 2^n 个 mask</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">        subset </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> []</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> i </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> range</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(n):          </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 每个 mask 扫 n 位</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">            if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> mask </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&amp;</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> (</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> &lt;&lt;</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> i):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">                subset.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">append</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(a[i])</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">        res.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">append</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(subset)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> res</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p><strong>复杂度</strong>：严格说是 <code>O(n * 2^n)</code>（因为每个子集构造要扫 n 位）。</p>\n<p><strong>为什么会爆炸</strong>：子集数量本身就是 <code>2^n</code>，规模增长极快。</p>\n<h3>10. O(n!) 阶乘时间（排列）</h3>\n<p><strong>代码示例：生成全排列（回溯）</strong></p>\n<div class=\"language-python line-numbers-mode has-collapsed-lines collapsed\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--vp-collapsed-lines:15;--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> permutations</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">a</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    res </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> []</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    used </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">False</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">] </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">*</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(a)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    path </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> []</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> dfs</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">():</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        if</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(path) </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">==</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(a):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">            res.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">append</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(path.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">copy</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">())</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">            return</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> i </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> range</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(a)):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">            if</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> not</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> used[i]:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">                used[i] </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> True</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">                path.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">append</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(a[i])</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">                dfs</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">                path.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">pop</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">                used[i] </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> False</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">    dfs</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> res</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div><div class=\"collapsed-lines\"></div></div><p><strong>为什么是 O(n!)</strong>：第 1 位有 n 种选法，第 2 位 n-1 … ⇒ <code>n*(n-1)*...*1 = n!</code>。</p>\n<h3>11. 递归复杂度的两个典型模板（看一眼就会用）</h3>\n<p><strong>A. “每次减半”的递归：O(log n)</strong></p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> rec_half</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">n</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> n </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&lt;=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        return</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 1</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> rec_half</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(n </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">//</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">) </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 1</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>每次 <code>n → n/2</code>，递归层数 <code>log n</code>。</p>\n<p><strong>B. 经典斐波那契（错误示范）：O(2^n)</strong></p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> fib_slow</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">n</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> n </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&lt;=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> n</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> fib_slow</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(n</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">) </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> fib_slow</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(n</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>递归树分叉，节点数指数级增长（重复计算大量子问题）。</p>\n<h3>12. 常见“陷阱”：看起来是 O(n)，其实是 O(n²)</h3>\n<p><strong>代码示例：循环里用了 <code>.count()</code>（每次 O(n)）</strong></p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> count_freq_bad</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">a</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    freq </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {}</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> x </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> a:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">        freq[x] </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> a.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">count</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(x)   </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># count 是 O(n)，外层又 n 次 =&gt; O(n^2)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> freq</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p><strong>为什么是 O(n²)</strong>：外层 <code>n</code> 次，每次 <code>count</code> 扫 <code>n</code> ⇒ <code>n*n</code>。</p>\n<p>✅ 改成真正 O(n)：</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> count_freq_good</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">a</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    freq </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {}</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> x </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> a:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">        freq[x] </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> freq.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">get</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(x, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">) </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 1</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> freq</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><h3>13. 一张“常见复杂度-典型原因”速查</h3>\n<ul>\n<li><code>O(1)</code>：固定次数操作</li>\n<li><code>O(log n)</code>：每轮规模按比例缩小（/2、/3…）</li>\n<li><code>O(√n)</code>：循环到平方根（试除、某些优化）</li>\n<li><code>O(n)</code>：扫一遍输入</li>\n<li><code>O(n + m)</code>：扫两份输入</li>\n<li><code>O(n log n)</code>：分治（log 层 × 每层 O(n)）</li>\n<li><code>O(n²)</code>：两两组合/双重循环</li>\n<li><code>O(n³)</code>：三重循环/某些全局 DP</li>\n<li><code>O(2^n)</code>：枚举子集/指数分叉递归</li>\n<li><code>O(n!)</code>：枚举排列</li>\n</ul>\n<h2>表 1：常见时间复杂度（带代码结构 + 原因推导）</h2>\n<blockquote>\n<p>记 <code>n</code> 为输入规模（如列表长度），<code>m</code> 为另一份输入规模（如第二个列表长度），<code>V/E</code> 为图的点/边数。</p>\n</blockquote>\n<p>| 时间复杂度     | 典型代码结构（Python 形式）                     | 为什么是这个复杂度（次数估算）                               | 常见场景                                        |<br>\n|</p>\n",
      "image": "https://bornforthis.cn/gzh.jpg",
      "date_published": "2026-02-17T10:06:49.000Z",
      "date_modified": "2026-02-18T13:20:17.000Z",
      "authors": [
        {
          "name": "AI悦创"
        }
      ],
      "tags": []
    },
    {
      "title": "02-蒜香排骨",
      "url": "https://bornforthis.cn/column/cookdinner/P04-%E7%83%A7%E7%83%A4%E7%B1%BB/02-%E8%92%9C%E9%A6%99%E6%8E%92%E9%AA%A8.html",
      "id": "https://bornforthis.cn/column/cookdinner/P04-%E7%83%A7%E7%83%A4%E7%B1%BB/02-%E8%92%9C%E9%A6%99%E6%8E%92%E9%AA%A8.html",
      "summary": "公众号：AI悦创【二维码】 AI悦创·编程一对一 AI悦创·推出辅导班啦，包括「Python 语言辅导班、C++ 辅导班、java 辅导班、算法/数据结构辅导班、少儿编程、pygame 游戏开发、Web、Linux」，招收学员面向国内外，国外占 80%。全部都是一对一教学：一对一辅导 + 一对一答疑 + 布置作业 + 项目实践等。当然，还有线下线上摄影...",
      "content_html": "\n",
      "image": "https://bornforthis.cn/gzh.jpg",
      "date_published": "2026-02-16T11:59:13.000Z",
      "date_modified": "2026-02-18T13:20:17.000Z",
      "authors": [
        {
          "name": "AI悦创"
        }
      ],
      "tags": []
    },
    {
      "title": "macOS 配置多个 GitHub 账号 SSH 的完整指南（个人 / 公司通用）",
      "url": "https://bornforthis.cn/blog/2026/macos-multiple-github-accounts-ssh.html",
      "id": "https://bornforthis.cn/blog/2026/macos-multiple-github-accounts-ssh.html",
      "summary": "一台 MacOS 电脑，如何配置多个 GitHub 账号 SSH。 1. 为什么需要配置多个 GitHub 账号？ 在真实的开发环境中，我们常常会遇到这样的场景： 一个 GitHub 个人账号； 一个或多个 公司 / 组织账号； 不同项目要求使用 不同 GitHub 身份； 希望 git push 时 不需要手动切换账号； 如果直接使用默认的 SSH ...",
      "content_html": "<div style=\"text-align:center\">\n<h3>一台 MacOS 电脑，如何配置多个 GitHub 账号 SSH。</h3>\n</div>\n<h2>1. 为什么需要配置多个 GitHub 账号？</h2>\n<p>在真实的开发环境中，我们常常会遇到这样的场景：</p>\n<ul>\n<li>一个 <strong>GitHub 个人账号</strong>；</li>\n<li>一个或多个 <strong>公司 / 组织账号</strong>；</li>\n<li>不同项目要求使用 <strong>不同 GitHub 身份</strong>；</li>\n<li>希望 <code>git push</code> 时 <strong>不需要手动切换账号</strong>；</li>\n</ul>\n<p>如果直接使用默认的 SSH 配置，通常会遇到：</p>\n<ul>\n<li>推送到错误的 GitHub 账号；</li>\n<li>没权限却一直提示 <code>Permission denied (publickey)</code>；</li>\n<li>SSH 不停尝试错误的 key，导致认证失败；</li>\n<li>无法配置新 GitHub 账号的 SSH，显示 <code>Key is already in use GitHub</code>；</li>\n</ul>\n<p><strong>解决方案只有一个：</strong></p>\n<blockquote>\n<p><strong>使用多个 SSH Key + SSH Host 别名，将不同项目路由到不同 GitHub 账号</strong>。</p>\n<p>换句话说：<strong>同一台 Mac，一条命令无脑 push</strong>。</p>\n</blockquote>\n<h2>2. 整体实现思路（先理解，再操作）</h2>\n<p>整个方案的核心结构如下：</p>\n<p>| 模块               | 作用                 |<br>\n|</p>\n",
      "image": "https://bornforthis.cn/gzh.jpg",
      "date_published": "2026-02-03T07:10:41.000Z",
      "date_modified": "2026-02-03T13:11:38.000Z",
      "authors": [
        {
          "name": "AI悦创"
        }
      ],
      "tags": []
    },
    {
      "title": "01｜登台远望：Claude Code 底层技术全景导览",
      "url": "https://bornforthis.cn/column/Python-Programming-Course/P14-claude-code-engineering-practice/01-claude-code-technical-overview.html",
      "id": "https://bornforthis.cn/column/Python-Programming-Course/P14-claude-code-engineering-practice/01-claude-code-technical-overview.html",
      "summary": "你好，我是悦创。让我们正式开启第一课的学习。 在我们的旅程正式启航之际，请你先思考第一个问题：你眼中的 Claude Code 是什么？ 我们可能会得到很多个不同的答案： 一个能读懂代码的 AI 助手； 命令行里的 ChatGPT； 帮我写代码的工具； 比 GitHub Copilot 更强大的东西； 这些答案都对，但都不完整。 Claude Code...",
      "content_html": "<figure><figcaption></figcaption></figure>\n<p>你好，我是悦创。让我们正式开启第一课的学习。</p>\n<p>在我们的旅程正式启航之际，请你先思考第一个问题：你眼中的 Claude Code 是什么？</p>\n<p>我们可能会得到很多个不同的答案：</p>\n<ul>\n<li>一个能读懂代码的 AI 助手；</li>\n<li>命令行里的 ChatGPT；</li>\n<li>帮我写代码的工具；</li>\n<li>比 GitHub Copilot 更强大的东西；</li>\n</ul>\n<p>这些答案都对，但都不完整。</p>\n<p><strong>Claude Code 的真正身份是：一个可编程、可扩展、可组合的 AI Agent 框架。</strong></p>\n<p>它不只是一个“工具“，而是一个“平台”——你可以在上面构建自己的 AI 工作流。就像你不会说“VS Code 是一个文本编辑器”（它是，但远不止于此），Claude Code 也远不只是一个 AI 助手。</p>\n<p>这一讲，我们将站在高处，俯瞰 Claude Code 的完整技术栈。当你理解了全貌，后面学习每一个组件时，都会知道它在整个系统中的位置。</p>\n<h2>1. Claude Code 5 分钟快速上手</h2>\n<p>我们先花几分钟，把 Claude Code 用起来。第一步，在<a href=\"https://code.claude.com/docs/en/desktop\" target=\"_blank\" rel=\"noopener noreferrer\">这里</a>下载匹配你系统的 Claude Code 版本。</p>\n<figure><figcaption></figcaption></figure>\n<p>安装过程非常简单，跟着官方的说明就好。</p>\n<div class=\"language-bash line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"bash\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-bash\"><span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># macOS / Linux / WSL（推荐，自动更新）</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">curl</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> -fsSL</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> https://claude.ai/install.sh</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> | </span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">bash</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># Windows PowerShell</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">irm</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> https://claude.ai/install.ps1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> | </span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">iex</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 或使用 Homebrew（需手动更新）</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">brew</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> install</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> --cask</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> claude-code</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>然后进入操作系统的命令行，输入 claude 这个命令就可以开始对话了。</p>\n<div class=\"language-bash line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"bash\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-bash\"><span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">claude</span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">              # 首次运行会提示登录</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div></div></div><p>Claude Code 是付费软件，需要在 Claude 网站开账户。它所支持的账户类型包括：</p>\n<ul>\n<li>Claude Pro / Max / Teams / Enterprise（推荐）</li>\n<li>Claude Console（API 访问，需预付费）</li>\n</ul>\n<figure><figcaption></figcaption></figure>\n<blockquote>\n<ol>\n<li>Cursor（<a href=\"https://cursor.com\" target=\"_blank\" rel=\"noopener noreferrer\">https://cursor.com</a>）：基于 VS Code 的 AI 编辑器，内置 Claude 和 GPT 模型，支持国内网络，有免费额度，其体验最接近 Claude Code 的 IDE 集成方案。</li>\n<li>Cline（VS Code 插件）：开源的 AI 编码助手插件：支持多种 LLM 后端，包括国内的 DeepSeek、Qwen 等，可以自己配置 API，灵活度高。</li>\n<li>Windsurf（<a href=\"https://codeium.com/windsurf\" target=\"_blank\" rel=\"noopener noreferrer\">https://codeium.com/windsurf</a>）：Codeium 推出的 AI IDE，有免费版，支持 agentic 编码。</li>\n<li>通义灵码（阿里云）：国产 AI 编程助手，IDE 插件形式，完全国内可用，无需翻墙。</li>\n<li>自建方案：使用 Cline + DeepSeek API（国内可直接访问）；或者使用 Cline + 本地部署的开源模型（如 Qwen-Coder）</li>\n</ol>\n</blockquote>\n<blockquote>\n<p>本课程的知识框架（Memory、SubAgents、Skills、Hooks 等概念）对于理解和使用其他 AI 编码工具同样适用。当然，如果你有稳定的网络环境，Claude Code 仍然是目前 agentic coding 体验最好的工具之一。</p>\n</blockquote>\n<p>下面是最基本的命令行（Command Line）交互方式，以及常用命令的速查表。</p>\n<div class=\"language-bash line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"bash\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-bash\"><span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">cd</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> /path/to/your/project</span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">   # 进入项目目录</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">claude</span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">                      # 启动交互模式</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 然后你可以：</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">&gt; 这个项目是做什么的？              </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 了解项目</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">&gt; 帮我加一个 hello world 函数      </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 修改代码（会请求确认）</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">&gt; 提交我的更改                      </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># Git 操作</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><figure><figcaption>常用命令的速查表</figcaption></figure>\n<p>除了在命令行中直接使用 Claude 命令之外，另一种更为常见的方式就是和 VS Code 浏览器中，甚至是其它 AI Coder 中（如 Cursor），把 Coding IDE 和 Claude Code 命令行集成使用。这样既可以享受 IDE 的便利，又可以利用命令行的强大，一举两得。</p>\n<h2>2. 从使用者到驾驭者</h2>\n<p>总结一下上面的使用步骤：</p>\n<div class=\"language-bash line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"bash\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-bash\"><span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">用户</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> →</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> 输入问题</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> →</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> Claude</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> 回答</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> →</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> 完成</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div></div></div><p>你问，它答。就像用计算器，输入数字，得到结果。大多数人使用 Claude Code 的方式，就止步于此了。</p>\n<p>Claude Code 可以生成代码，从 0 开始做项目，整理文件，甚至优化你的操作系统……虽然能做到这些也已经很强大了，但这仍然只是<strong>被动使用！</strong></p>\n<p>而 Claude Code 还支持另一种模式：</p>\n<div class=\"language-bash line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"bash\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-bash\"><span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">用户</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> →</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> 配置</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> Agent</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> →</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> Agent</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> 自主工作</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> →</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> 自动完成任务</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div></div></div><p>这是<strong>主动驾驭</strong>——你设计，它执行。就像我们编写程序，程序自动运行。</p>\n<p>举个例子：</p>\n<figure><figcaption></figcaption></figure>\n<p><strong>这门课的目标，把你从被动使用者变成主动驾驭者。</strong></p>\n<p>你肯定会说，悦创，我当然想走得更远一些，从被动使用者晋级为主动驾驭者，<strong>那成为驾驭者需要理解什么？</strong></p>\n<p>用学开车打个比方：</p>\n<ul>\n<li><strong>使用者</strong>：知道方向盘转哪边车往哪走，油门让车动，刹车让车停。</li>\n<li><strong>驾驭者</strong>：理解发动机、变速箱、刹车系统的工作原理，能改装车辆。</li>\n</ul>\n<p>对于 Claude Code：</p>\n<ul>\n<li><strong>使用者</strong>：知道怎么提问，怎么让 Claude 帮你写代码。</li>\n<li><strong>驾驭者</strong>：理解记忆系统、子代理、技能包、钩子的工作原理，能构建自定义工作流。</li>\n</ul>\n<p>我们现在这一讲就是“驾驭者入门”——让你看到 Claude Code 引擎盖下面的东西。</p>\n<h2>3. Claude Code 底层技术全景图</h2>\n<p>Claude Code 的底层能力从技术上拆解可以分为四个层次：基础层、扩展层、集成层和编程接口层。</p>\n<figure><figcaption></figcaption></figure>\n<p>让我从下往上解释每一层。</p>\n<h2>4. 基础层：Memory（记忆系统）</h2>\n<p>基础层也可以称为是 Claude Code 的长期记忆系统，它的核心文件是 <code>CLAUDE.md</code>。</p>\n<p>比如入职一家新公司，第一天你会收到一份新员工手册，告诉你：</p>\n<ul>\n<li>公司的代码风格是什么。</li>\n<li>Git 提交信息怎么写。</li>\n<li>项目的架构是怎样的。</li>\n<li>有哪些不能碰的“禁区”。</li>\n</ul>\n<p>而 <code>CLAUDE.md</code> 就是 Claude 的“新员工手册”。</p>\n<p>因此，我强烈建议每一个人都为你的 Claude 创建 <code>CLAUDE.md</code>，以提供给它一系列最基本的信息。</p>\n<p>例如，当我们要开始一个新的电商项目，我创建了下面的 <code>CLAUDE.md</code> 文件。</p>\n<div class=\"language-bash line-numbers-mode has-collapsed-lines collapsed\" data-highlighter=\"shiki\" data-ext=\"bash\" style=\"--vp-collapsed-lines:15;--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-bash\"><span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># Project: E-commerce Platform</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">## Tech Stack</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">-</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> Frontend:</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> React</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> +</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> TypeScript</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">-</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> Backend:</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> Node.js</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> +</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> Express</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">-</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> Database:</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> PostgreSQL</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">## Code Style</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">-</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> Use</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> functional</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> components</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">-</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> Prefer</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> async/await</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> over</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> .then</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">-</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> Maximum</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> line</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> length:</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 100</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> characters</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">## Important Rules</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">-</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> NEVER</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> commit</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> to</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> main</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> directly</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">-</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> Always</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> run</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> tests</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> before</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> pushing</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div><div class=\"collapsed-lines\"></div></div><p>Claude 每次开始对话时，都会读取这个文件。这样它就“记住”了你的项目规范，不需要每次重复说明。</p>\n<p>Claude Code 并不是只有一个CLAUDE.md记忆文件，全局、项目和项目的特定模块都可以拥有属于自己的记忆文件（或者也可以叫配置文件）。</p>\n<div class=\"language-bash line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"bash\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-bash\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">~/.claude/CLAUDE.md           </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 全局（所有项目共用）</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">    ↓</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">项目根目录/CLAUDE.md</span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">          # 项目级（当前项目）</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">    ↓</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">项目根目录/.claude/rules/*.md</span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"> # 模块级（特定目录）</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>我们可以把这些文件视为 Claude Code 系统记忆的不同层级。</p>\n<h2>5. 扩展层：四大核心组件</h2>\n<p>这一层是 Claude Code 的能力中心，包含 Commands（斜杠命令）、Skills（技能）、SubAgents（子代理）、Hooks（钩子）四个核心组件。</p>\n<h3>5.1 Commands（斜杠命令）</h3>\n<p>斜杠命令是 Claude Code 内置或用户自定义的一系列核心能力，其触发方式是用户手动输入  <code>/command</code>：</p>\n<div class=\"language-bash line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"bash\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-bash\"><span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">用户输入:</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> /review</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">Claude</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> 执行:</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> 根据</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> .claude/commands/review.md</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> 的指令审查代码</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>Commands 适合<strong>标准化操作</strong>——团队统一的 commit 格式、固定的部署流程等。</p>\n<h3>5.2 Skills（技能）</h3>\n<p>技能则代表着 AI 的一系列专属能力组合，其触发方式是 Claude 自动判断（语义推理）是否激活相应技能。Skills 可以是 Claude Code 内置的，也可以由用户自己设定。</p>\n<div class=\"language-bash line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"bash\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-bash\"><span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">用户说:</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> \"帮我看看这段代码有没有安全问题\"</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">Claude</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> 思考:</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> 这是代码安全审查任务</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> →</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> 激活</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> security-review</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> Skill</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">Claude</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> 执行:</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> 按照</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> Skill</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> 中定义的流程审查代码</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>很多人第一次听到 Skills 这个概念，都会觉得 “这不就是个高级一点的 tool 吗？Agent 直接 call tool 不就行了？”</p>\n<p>我的回答是：的确像，但并不等价。原因在于 Tools 是外部能力接口，Skills 是模型内部的“行为模式 + 触发逻辑”。如果 Tool 是函数调用，Skill 就是把 if-else、prompt、策略和调用顺序，全部折叠进一个文档的整体封装，是对一个专有能力集的全面定义。</p>\n<p>如果说 Tool 解决的是<strong>我能不能做</strong>；而 Skill 解决的是<strong>我该不该做、怎么做、做到什么程度</strong>。那么又一个问题来了：什么时候该用 Skill？什么时候该用 Commands？</p>\n<p>Commands 是显式、可复用、可审计、通过斜杠命令固定触发的操作指令集，是相对固化的标准流程。</p>\n<p>而当一个能力具备强烈的“领域感”（安全、架构、性能）、判断依赖上下文而非关键词 ，执行路径可能变化 ，需要“像专家一样行事”时，就用 Skill，而不是 Command。</p>\n<p>拿刚才的例子来说——当用户问“帮我看看这段代码有没有安全问题”。Claude 的隐式判断流程是这样的。</p>\n<div class=\"language-bash line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"bash\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-bash\"><span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">1️⃣</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> 这是代码吗？——是</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">2️⃣</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> 这是哪一类代码？——Node.js</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> 后端</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">3️⃣</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> 上下文是否涉及用户输入？——是</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">4️⃣</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> 是否存在鉴权逻辑？——是</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">5️⃣</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> 是否值得深入做安全审查？——是</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>做完这些判断之后，就会自动激活 security-review Skill。</p>\n<p>在 Skill 内部，是“像专家一样”的行为说明，它不会跑固定 checklist，而是根据语言选择重点、根据上下文跳过无关项、在发现高风险点时主动深挖、在安全风险低时明确告诉你“为什么没问题” —— 这不是流程执行，这是专家判断。</p>\n<h3>5.3 SubAgents（子代理）</h3>\n<p>子代理是除了 Skills 之外的另一个大杀器，用于独立完成专项任务。其触发方式可以由 Claude 决定或用户指定。</p>\n<div class=\"language-bash line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"bash\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-bash\"><span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">主</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> Claude:</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> 这个任务需要跑大量测试，让我创建一个子代理来处理。</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">子代理（test-runner）:</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> 执行测试，只把结果汇报给主</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> Claude</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>SubAgents 适合<strong>隔离执行</strong>——高噪声任务（比如在大量日志中寻找出错信息，在大量文档中检索相关资源）、需要特定权限的任务。</p>\n<figure><figcaption></figcaption></figure>\n<h3>5.4 Hooks（钩子）</h3>\n<p>钩子是在特定事件触发时自动执行的脚本，其触发方式是事件自动触发。</p>\n<div class=\"language-bash line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"bash\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-bash\"><span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">事件:</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> Claude</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> 即将执行</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> Edit</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> 工具</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">Hook:</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> 自动检查是否有安全敏感内容</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">结果:</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> 如果发现问题，阻止执行并警告</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>Hooks 适合<strong>自动化检查</strong>——格式化、安全检查、日志记录等。</p>\n<h2>6. 集成层：连接外部世界</h2>\n<p>上面这四大核心组件之上，是集成层，负责链接外部世界。集成层包含 Headless（无头模式）和 MCP（Model Context Protocol）两大技术。</p>\n<h3>6.1 Headless（无头模式）</h3>\n<p>无头模式让 Claude Code 在没有人工交互的情况下运行，适合  <strong>CI/CD 集成</strong>——自动代码审查、自动修复、自动生成变更日志等。</p>\n<div class=\"language-bash line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"bash\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-bash\"><span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># GitHub Actions 中</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">-</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> name:</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> Auto-fix</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> code</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> issues</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">  run:</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> claude</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> --headless</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> \"Fix all linting errors in src/\"</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><h3>6.2 MCP（Model Context Protocol）</h3>\n<p>MCP 让 Claude 连接外部工具和服务，适合<strong>工具连接</strong>——可以把任何外部系统变成 Claude 可调用的工具。</p>\n<div class=\"language-bash line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"bash\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-bash\"><span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">Claude</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> →</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> MCP</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> →</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> 数据库</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">Claude</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> →</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> MCP</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> →</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> Jira</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">Claude</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> →</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> MCP</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> →</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> 自定义</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> API</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><h2>7. 编程接口层：Agent SDK</h2>\n<p>当配置式的扩展不够用时，你可以用代码来驱动 Claude。这种方式适合<strong>构建自定义 Agent</strong>——完全控制执行流程、自定义工具、复杂工作流。</p>\n<div class=\"language-bash line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"bash\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-bash\"><span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">from</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> claude_sdk</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> import</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> ClaudeSDKClient</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">client</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> =</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> ClaudeSDKClient</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 执行任务</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">result</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> =</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> client.query</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">    prompt</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"Review this code for security issues\",</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">    tools</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">[\"Read\",</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> \"Grep\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">],</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">    max_turns</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">10</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><h2>8. 组件关系和技术选型指南</h2>\n<p>在真实的系统中，这些组件不是孤立存在的——它们相互协作，共同完成复杂任务。</p>\n<h3>8.1 触发方式</h3>\n<p>首先看触发方式，也就是<strong>这些组件是怎么被激活的</strong>？不同组件的触发方式决定了它们的使用场景。</p>\n<figure><figcaption></figcaption></figure>\n<p><strong>为什么“确定性”很重要？</strong></p>\n<p>如果我们要设计一个生产系统：</p>\n<ul>\n<li>如果你需要“每次都必须执行”的操作（比如代码格式化），你需要  <strong>100% 确定性</strong>——选择 Commands 或 Hooks。</li>\n<li>如果你希望 Claude “智能判断何时使用”（比如识别到安全问题时自动深入分析），你可以接受<strong>概率性</strong>——选择 Skills。</li>\n<li>如果任务可能很重，你希望“既可以手动触发，也可以让 Claude 自己决定”，你需要<strong>可控性</strong>——选择 SubAgents。</li>\n</ul>\n<p>这个表格会在你做技术选型时反复用到。</p>\n<h3>8.2 数据流向</h3>\n<p>理解了触发方式，我们来看数据是怎么在系统中流动的。这张图展示了一个典型请求的生命周期：</p>\n<figure><figcaption></figcaption></figure>\n<p>让我结合一个具体场景来解释这个流程——当用户输入“帮我修复 <code>src/api.js</code> 中的安全漏洞”之后，Claude 可能的处理流程如下。</p>\n<ol>\n<li>\n<p><strong>Memory 层</strong>：Claude 首先加载  <code>CLAUDE.md</code>，了解到这是一个 Node.js 项目，团队要求所有安全修复必须附带测试。</p>\n</li>\n<li>\n<p><strong>扩展层分发：</strong></p>\n<p>a. 用户没有输入斜杠命令，所以 Commands 不参与。</p>\n<p>b. Claude 识别出“安全漏洞”关键词，激活  <code>security-review</code> Skill。</p>\n<p>c. Skill 指示 Claude 创建一个子代理来执行测试。</p>\n</li>\n<li>\n<p>Hooks 监控：Claude 准备执行  <code>Edit</code> 工具修改代码时，Hooks 自动运行预检查脚本，确保没有引入新的安全问题。</p>\n</li>\n<li>\n<p>工具执行：通过 Read、Edit 等工具完成代码修改。</p>\n</li>\n<li>\n<p>MCP 连接：如果配置了 Jira MCP，还可以自动更新相关的 ticket 状态。</p>\n</li>\n</ol>\n<p>关键洞察：<strong>Memory 是基础设施，始终存在；扩展层是能力中心，按需激活；Hooks 是守门人，监控一切。</strong></p>\n<h3>8.3 Plugins：打包容器</h3>\n<p>当你开发了一套好用的 Commands、Skills、Hooks 组合，想要分享给团队或社区时，就需要 Plugins。</p>\n<p><strong>Plugins 不是一种新能力，而是打包机制</strong>——就像 npm 包把一堆 JavaScript 文件打包在一起，Plugin 把一组相关的 Claude Code 扩展打包在一起。</p>\n<div class=\"language-bash line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"bash\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-bash\"><span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">my-team-plugin/</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">├──</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> commands/</span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">           # 斜杠命令</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">│</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">   └──</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> review.md</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">├──</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> skills/</span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">             # 技能</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">│</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">   └──</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> security-check/</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">│</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">       └──</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> SKILL.md</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">├──</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> agents/</span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">             # 子代理</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">│</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">   └──</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> test-runner.md</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">├──</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> hooks/</span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">              # 钩子</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">│</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">   └──</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> pre-edit.sh</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">└──</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> plugin.json</span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">         # 插件配置</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>下面是一个典型的 <strong>Plugins</strong> 使用场景：</p>\n<blockquote>\n<p>你是团队的技术 Lead，花了两周时间打磨出一套完美的代码审查流程：一个  <code>/review</code> 命令触发审查，一个  <code>code-quality</code> Skill 自动分析代码质量，一个  <code>test-runner</code> 子代理执行测试，还有一个 Hook 确保所有修改都有对应的测试。</p>\n<p>与其让团队成员手动复制这些文件，不如打包成一个 Plugin，新成员只需一条命令就能获得完整的工作流。</p>\n</blockquote>\n<p>Plugin 的价值在于<strong>可复用、可版本化、可分发</strong>。在第 16 讲我们还会详细讲解如何创建和发布 Plugins。</p>\n<h3>8.4 技术选型指南</h3>\n<p>目前，理论知识已经足够了，但当你面对一个真实需求时，如何选择正确的技术？下面这是我总结的决策流程：</p>\n<figure><figcaption></figcaption></figure>\n<p>让我用几个真实问题来演示这个决策树的使用。</p>\n<p><strong>问题 1</strong>：我希望团队成员都用统一的 commit message 格式。</p>\n<ul>\n<li>这是一种“能力”吗？是的，是生成规范 commit message 的能力。</li>\n<li>希望手动触发还是自动识别？手动触发更合适，因为不是每次对话都需要 commit。</li>\n<li><strong>答案</strong>：适合用 <strong>Commands</strong>（创建一个  <code>/commit</code> 命令）。</li>\n</ul>\n<p><strong>问题 2</strong>：每当 Claude 要修改代码时，我想自动检查是否符合我们的安全规范。</p>\n<ul>\n<li>这是一种“能力“吗？不是，这是一种“检查机制”。</li>\n<li>需要在工具执行时自动检查？ 对，在 Edit 工具执行前检查。</li>\n<li><strong>答案</strong>：适合用 <strong>Hooks</strong>（创建一个 pre-Edit hook）</li>\n</ul>\n<p><strong>问题 3</strong>：我想让 Claude 能够查询我们内部的知识库。</p>\n<ul>\n<li>这是一种“能力”吗？ 不完全是，这是“连接外部数据源”。</li>\n<li>需要连接外部系统？ 知识库是一个外部系统。</li>\n<li><strong>答案</strong>：适合用 <strong>MCP</strong>（创建一个知识库 MCP server）。</li>\n</ul>\n<p>为了帮助你快速匹配，我也准备了一份场景 VS 方案的速查表。</p>\n<figure><figcaption></figcaption></figure>\n<details class=\"hint-container details\"><summary>公众号：AI悦创【二维码】</summary>\n<figure><img src=\"/gzh.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n</details>\n<div class=\"hint-container info\">\n<p class=\"hint-container-title\">AI悦创·编程一对一</p>\n<p>AI悦创·推出辅导班啦，包括「Python 语言辅导班、C++ 辅导班、java 辅导班、算法/数据结构辅导班、少儿编程、pygame 游戏开发、Web、Linux」，招收学员面向国内外，国外占 80%。全部都是一对一教学：一对一辅导 + 一对一答疑 + 布置作业 + 项目实践等。当然，还有线下线上摄影课程、Photoshop、Premiere 一对一教学、QQ、微信在线，随时响应！微信：Jiabcdefh</p>\n<p>C++ 信息奥赛题解，长期更新！长期招收一对一中小学信息奥赛集训，莆田、厦门地区有机会线下上门，其他地区线上。微信：Jiabcdefh</p>\n<p>方法一：<a href=\"http://wpa.qq.com/msgrd?v=3&amp;uin=1432803776&amp;site=qq&amp;menu=yes\" target=\"_blank\" rel=\"noopener noreferrer\">QQ</a></p>\n<p>方法二：微信：Jiabcdefh</p>\n</div>\n<figure><img src=\"/zsxq.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n",
      "date_published": "2026-02-01T20:19:39.000Z",
      "date_modified": "2026-02-23T05:08:21.000Z",
      "authors": [
        {
          "name": "AI悦创"
        }
      ],
      "tags": []
    },
    {
      "title": "02-2026 年个人博客搭建，搭建属于自己的平台",
      "url": "https://bornforthis.cn/column/Python-Programming-Course/P13-personal-blog-building/02-Blog-build.html",
      "id": "https://bornforthis.cn/column/Python-Programming-Course/P13-personal-blog-building/02-Blog-build.html",
      "summary": "1. 所需环境 安装 Nodejs：网站运行的本质软件； 安装 VScode：网站配置、更新部署等操作软件； 安装 Typora：网站文章编写软件；（唯一的付费软件，可以选择支持盗版～） 安装 Snipaste：截图、贴图软件，文章编写中图片操作的主力软件；（强力推荐每台电脑都默认安装此软件！） 安装 Git：用于和 Github 进行交互操作；（推送...",
      "content_html": "<h2>1. 所需环境</h2>\n<ul>\n<li>安装 <strong>Nodejs</strong>：网站运行的本质软件；</li>\n<li>安装 <strong>VScode</strong>：网站配置、更新部署等操作软件；</li>\n<li>安装 <strong>Typora</strong>：网站文章编写软件；（唯一的付费软件，可以选择支持盗版～）</li>\n<li>安装 <strong>Snipaste</strong>：截图、贴图软件，文章编写中图片操作的主力软件；（强力推荐每台电脑都默认安装此软件！）</li>\n<li>安装 <strong>Git</strong>：用于和 Github 进行交互操作；（推送代码等）</li>\n<li>注册 <strong>GitHub</strong> 账号：用于网站部署、存储代码等；（作用很强大，必须注册拿下！）</li>\n<li>配置 GitHub 的 <strong>SSH</strong>，参考教程：<a href=\"https://bornforthis.cn/blog/2024/7month/git-ssh.html\" target=\"_blank\" rel=\"noopener noreferrer\">https://bornforthis.cn/blog/2024/7month/git-ssh.html</a></li>\n<li>「可选」购买 <strong>域名</strong>，便于大家访问网站；\n<ul>\n<li>域名越直白越好；</li>\n<li>越短越好；</li>\n<li>可以参考：\n<ul>\n<li><strong>AI悦创</strong>：<code>bornforthis.cn</code>；</li>\n<li>谷歌：<code>google.com</code>；</li>\n<li>淘宝：<code>taobao.com</code>；</li>\n<li>飞书：<code>feishu.cn</code>；</li>\n<li>抖音：<code>douyin.com</code>；</li>\n<li>京东：<code>jd.com</code>；</li>\n<li>微博：<code>weibo.com</code>；</li>\n</ul>\n</li>\n<li>域名是可以随时修改，但是我们一般不推荐修改，为什么？——身份标识，例子：大家都知道淘宝域名（<a href=\"http://taobao.com\" target=\"_blank\" rel=\"noopener noreferrer\">taobao.com</a>），突然有一天淘宝换域名了，很多人都只停留在原本的域名，而不知道最新域名。</li>\n</ul>\n</li>\n</ul>\n\n<h2>2. 购买域名</h2>\n<ul>\n<li>\n<p><strong>Step 1</strong>：访问阿里云万网：<a href=\"https://wanwang.aliyun.com/\" target=\"_blank\" rel=\"noopener noreferrer\">https://wanwang.aliyun.com/</a></p>\n</li>\n<li>\n<p><strong>Step 2</strong>：注册阿里云账号；</p>\n</li>\n<li>\n<p><strong>Step 3</strong>：🔍搜索你想要的域名，看是否🉑买；</p>\n<figure><figcaption></figcaption></figure>\n</li>\n<li>\n<p><strong>Step 4</strong>：购买时会提示需要“<strong>创建信息模版</strong>”，按指引创建即可：</p>\n<figure><figcaption></figcaption></figure>\n</li>\n<li>\n<p><strong>Step 5</strong>：选择立即实名认证即可，按指引操作即可：</p>\n<figure><figcaption></figcaption></figure>\n<figure><figcaption></figcaption></figure>\n</li>\n<li>\n<p><strong>Step 6</strong>：等待审核通过即可；</p>\n</li>\n</ul>\n<h2>3. 本地网站初始化</h2>\n<h3>3.1 启动终端</h3>\n<p>使用终端进入到目标路径，也就是你想把网站放在哪里。（换句话说：哪个磁盘、哪个文件夹。）</p>\n\n<h3>3.2 在终端初始化网站</h3>\n<ul>\n<li>\n<p>我们使用的是开源主题：<a href=\"https://theme-hope.vuejs.press/zh/\" target=\"_blank\" rel=\"noopener noreferrer\">https://theme-hope.vuejs.press/zh/</a></p>\n</li>\n<li>\n<p>点击：快速上手</p>\n<figure><figcaption></figcaption></figure>\n</li>\n<li>\n<p>点击：<a href=\"https://theme-hope.vuejs.press/zh/get-started/create.html\" target=\"_blank\" rel=\"noopener noreferrer\">创建项目</a></p>\n<figure><figcaption></figcaption></figure>\n</li>\n<li>\n<p>在终端输入主题文档提供的命令进行初始化网站：<code>pnpm create vuepress-theme-hope my-docs</code></p>\n<figure><figcaption></figcaption></figure>\n</li>\n<li>\n<p>终端界面（上一步启动的终端），把命令改成：<code>pnpm create vuepress-theme-hope .</code>：</p>\n<p>键盘上下键选择“简体中文”，随后回车↩︎键：</p>\n<figure><figcaption></figcaption></figure>\n<p>选择 pnpm：</p>\n<figure><figcaption></figcaption></figure>\n<p>选择 vite：</p>\n<figure><figcaption></figcaption></figure>\n<p>按下图进行设置即可：</p>\n<ul>\n<li><strong>应用名称</strong>：需要使用纯英文编写，自己的网站名称；</li>\n<li><strong>设置应用描述</strong>：自己的网站信息介绍，自己编写；</li>\n<li>其它按图片编写即可；</li>\n</ul>\n<figure><figcaption></figcaption></figure>\n</li>\n<li>\n<p>按照下面继续设置即可：</p>\n<figure><figcaption></figcaption></figure>\n</li>\n<li>\n<p>自己选择是否查看 demo 示例：</p>\n<figure><figcaption></figcaption></figure>\n</li>\n<li>\n<p>如何停止：使用 <code>Ctrl + C</code> 进行停止🤚</p>\n<figure><figcaption></figcaption></figure>\n</li>\n</ul>\n<h3>3.3 使用 Vscode 打开本网站项目</h3>\n<p>启动终端，使终端在网站文件夹下。使用前面的终端也是可以的，需要停止运行网站。</p>\n<details class=\"hint-container details\"><summary>操作方法</summary>\n<p>鼠标选中新创建的文件夹（WebSite），<strong>鼠标右键</strong>——&gt;最底部的“<strong>服务</strong>”——&gt;选择“<strong>新建位于文件夹位置的终端窗口</strong>”：</p>\n<figure><figcaption></figcaption></figure>\n</details>\n<p>直接输入：<code>code .</code> 这样就可以直接启动 VScode。</p>\n<p>已经成功使用 VScode 启动网站项目：</p>\n<figure><figcaption></figcaption></figure>\n<h3>3.4 网站启动本地预览（网站本地启动）</h3>\n\n<h3>3.5 关闭本地启动的网站</h3>\n<ul>\n<li><strong>方法一</strong>：直接叉掉终端，但是需要又得启动终端；</li>\n<li><strong>方法二</strong>：在目标终端使用 <code>Ctrl + C</code> 即可退出。</li>\n</ul>\n<h3>3.6 配置网站</h3>\n<h4>3.6.1 设置网站基本信息</h4>\n<p>文件路径：<code>src/.vuepress/config.ts</code></p>\n<figure><figcaption></figcaption></figure>\n\n<figure><figcaption>修改之前</figcaption></figure>\n<figure><figcaption>修改之后</figcaption></figure>\n<h2>4. 网站部署</h2>\n<h3>4.1 GitHub 创建特定仓库</h3>\n<p><strong>Step 1</strong>：新建仓库</p>\n<figure><figcaption></figcaption></figure>\n<ul>\n<li>\n<p>输入仓库名称：<code>huangjiarongbao.github.io</code>；</p>\n<blockquote>\n<p>一个 GitHub 账号，只能创建一个这样的特定仓库，不过有其它方法绕开限制，后期分享。</p>\n</blockquote>\n</li>\n<li>\n<p>仓库介绍；</p>\n</li>\n<li>\n<p>仓库必须公开，不能私有。如果想要私有，得用其它方法保护源代码。</p>\n<blockquote>\n<p>原因很简单：因为免费版必须公开。</p>\n</blockquote>\n</li>\n<li>\n<p>随后点击： Create repository 即可；</p>\n</li>\n</ul>\n<figure><figcaption></figcaption></figure>\n<p>切换到 SSH：</p>\n<figure><figcaption></figcaption></figure>\n<h3>4.2 本地电脑网站，绑定远程 GitHub 仓库（首次推送）</h3>\n<div class=\"hint-container tip\">\n<p class=\"hint-container-title\">补充：主题目前初始化自带 GitHub 部署脚本存在问题，需要使用如下内容直接覆盖。路径：<code>.github/workflows/deploy-docs.yml</code></p>\n<div class=\"language-yaml line-numbers-mode has-collapsed-lines collapsed\" data-highlighter=\"shiki\" data-ext=\"yaml\" style=\"--vp-collapsed-lines:15;--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-yaml\"><span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">name</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">部署文档</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">on</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">  push</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">    branches</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">      - </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">main</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">permissions</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">  contents</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">write</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">jobs</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">  deploy-gh-pages</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">    runs-on</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">ubuntu-latest</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">    steps</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">      - </span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">name</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">Checkout</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">        uses</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">actions/checkout@v3</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">        with</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">          fetch-depth</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">          # 如果你文档需要 Git 子模块，取消注释下一行</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">          # submodules: true</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">      - </span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">name</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">安装 pnpm</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">        uses</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">pnpm/action-setup@v2</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">        with</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">          run_install</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">true</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">          version</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">10.5.2</span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"> # 指定 pnpm 版本，可以修改为最新的稳定版本</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">      - </span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">name</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">设置 Node.js</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">        uses</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">actions/setup-node@v3</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">        with</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">          node-version</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">20</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">          cache</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">pnpm</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">      - </span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">name</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">构建文档</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">        env</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">          NODE_OPTIONS</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">--max_old_space_size=8192</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">        run</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">|-</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">          pnpm run docs:build</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">          &gt; src/.vuepress/dist/.nojekyll</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">      - </span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">name</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">部署文档</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">        uses</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">JamesIves/github-pages-deploy-action@v4</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">        with</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">          branch</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">gh-pages</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">          folder</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">src/.vuepress/dist</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div><div class=\"collapsed-lines\"></div></div></div>\n<figure><figcaption></figcaption></figure>\n<p>打开网站终端（终端所在路径需要在网站当中），输入如下命令：</p>\n<div class=\"language-bash line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"bash\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-bash\"><span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">git</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> init</span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">  # 初始化仓库</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">git</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> add</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> .</span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"> # . 代表添加所有文件夹、文件</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">git</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> commit</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> -m</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> \"first commit\"</span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">  # \"first commit\" 可以随便改，代表本次做了哪些修改，做个备注。不改，一直用这个也是可以的。</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">git</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> branch</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> -M</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> main</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">git</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> remote</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> add</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> origin</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> git@github.com:huangjiarongbao/huangjiarongbao.github.io.git</span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">  # 用你自己的，每个 GitHub 都有自己的 </span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">git</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> push</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> -u</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> origin</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> main</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>一条一条执行命令，即可。提交成功参考：</p>\n<div class=\"language-bash line-numbers-mode has-collapsed-lines collapsed\" data-highlighter=\"shiki\" data-ext=\"bash\" style=\"--vp-collapsed-lines:15;--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-bash\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">base</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">) </span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">➜</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">  WebSite</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> git</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> init</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">Initialized</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> empty</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> Git</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> repository</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> in</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> /Users/huangjiabao/Desktop/WebSite/.git/</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">base</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">) </span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">➜</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">  WebSite</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> git:</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">main</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">) </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">✗</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> git</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> add</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> .</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">base</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">) </span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">➜</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">  WebSite</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> git:</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">main</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">) </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">✗</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> git</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> commit</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> -m</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> \"first commit\"</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">[main (</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">root</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">commit</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">) 2051f89] first commit</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> 47</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> files</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> changed,</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 5661</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> insertions</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">+</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> create</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> mode</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 100644</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> .DS_Store</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> create</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> mode</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 100644</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> .github/workflows/deploy-docs.yml</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> create</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> mode</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 100644</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> .gitignore</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> create</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> mode</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 100644</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> package.json</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> create</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> mode</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 100644</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> pnpm-lock.yaml</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> create</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> mode</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 100644</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> src/.vuepress/config.ts</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> create</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> mode</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 100644</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> src/.vuepress/navbar.ts</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> create</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> mode</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 100644</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> src/.vuepress/public/CNAME</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> create</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> mode</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 100644</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> src/.vuepress/public/assets/icon/apple-icon-152.png</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> create</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> mode</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 100644</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> src/.vuepress/public/assets/icon/chrome-192.png</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> create</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> mode</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 100644</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> src/.vuepress/public/assets/icon/chrome-512.png</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> create</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> mode</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 100644</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> src/.vuepress/public/assets/icon/chrome-mask-192.png</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> create</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> mode</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 100644</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> src/.vuepress/public/assets/icon/chrome-mask-512.png</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> create</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> mode</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 100644</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> src/.vuepress/public/assets/icon/guide-maskable.png</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> create</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> mode</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 100644</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> src/.vuepress/public/assets/icon/ms-icon-144.png</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> create</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> mode</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 100644</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> src/.vuepress/public/assets/images/cover1.jpg</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> create</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> mode</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 100644</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> src/.vuepress/public/assets/images/cover2.jpg</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> create</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> mode</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 100644</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> src/.vuepress/public/assets/images/cover3.jpg</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> create</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> mode</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 100644</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> src/.vuepress/public/favicon.ico</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> create</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> mode</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 100644</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> src/.vuepress/public/logo.png</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> create</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> mode</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 100644</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> src/.vuepress/public/logo.svg</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> create</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> mode</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 100644</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> src/.vuepress/sidebar.ts</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> create</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> mode</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 100644</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> src/.vuepress/styles/config.scss</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> create</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> mode</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 100644</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> src/.vuepress/styles/index.scss</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> create</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> mode</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 100644</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> src/.vuepress/styles/palette.scss</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> create</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> mode</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 100644</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> src/.vuepress/theme.ts</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> create</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> mode</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 100644</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> src/README.md</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> create</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> mode</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 100644</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> src/demo/README.md</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> create</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> mode</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 100644</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> src/demo/disable.md</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> create</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> mode</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 100644</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> src/demo/encrypt.md</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> create</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> mode</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 100644</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> src/demo/layout.md</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> create</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> mode</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 100644</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> src/demo/markdown.md</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> create</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> mode</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 100644</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> src/demo/page.md</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> create</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> mode</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 100644</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> src/intro.md</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> create</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> mode</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 100644</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> src/posts/apple/1.md</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> create</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> mode</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 100644</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> src/posts/apple/2.md</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> create</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> mode</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 100644</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> src/posts/apple/3.md</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> create</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> mode</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 100644</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> src/posts/apple/4.md</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> create</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> mode</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 100644</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> src/posts/banana/1.md</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> create</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> mode</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 100644</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> src/posts/banana/2.md</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> create</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> mode</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 100644</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> src/posts/banana/3.md</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> create</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> mode</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 100644</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> src/posts/banana/4.md</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> create</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> mode</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 100644</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> src/posts/cherry.md</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> create</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> mode</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 100644</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> src/posts/dragonfruit.md</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> create</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> mode</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 100644</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> src/posts/strawberry.md</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> create</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> mode</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 100644</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> src/posts/tomato.md</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> create</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> mode</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 100644</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> tsconfig.json</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">base</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">) </span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">➜</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">  WebSite</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> git:</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">main</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">) </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">git</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> branch</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> -M</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> main</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">base</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">) </span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">➜</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">  WebSite</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> git:</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">main</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">) </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">git</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> remote</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> add</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> origin</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> git@github-work:huangjiarongbao/huangjiarongbao.github.io.git</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">base</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">) </span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">➜</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">  WebSite</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> git:</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">main</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">) </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">git</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> remote</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> add</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> origin</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> git@github-work:huangjiarongbao/huangjiarongbao.github.io.git</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">base</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">) </span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">➜</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">  WebSite</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> git:</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">main</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">) </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">git</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> push</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> -u</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> origin</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> main</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">Enumerating</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> objects:</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> 62,</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> done.</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">Counting</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> objects:</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> 100%</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> (62/62), done.</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">Delta</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> compression</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> using</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> up</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> to</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 10</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> threads</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">Compressing</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> objects:</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> 100%</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> (57/57), done.</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">Writing</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> objects:</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> 100%</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> (62/62), 591.97 KiB | </span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">1.93</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> MiB/s,</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> done.</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">Total</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 62</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> (delta </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">6</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">), reused 0 (</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">delta</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">), pack-reused 0 (</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">from</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">remote:</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> Resolving</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> deltas:</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> 100%</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> (6/6), done.</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">To</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> github-work:huangjiarongbao/huangjiarongbao.github.io.git</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> *</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> [new </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">branch]</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">      main</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> -&gt; </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">main</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">branch</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> 'main'</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> set</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> up</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> to</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> track</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> 'origin/main'.</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">base</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">) </span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">➜</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">  WebSite</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> git:</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">main</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div><div class=\"collapsed-lines\"></div></div><blockquote>\n<p>Tips：github-work 是我自己一台电脑，配置多个 SSH 的标记，无需 care。</p>\n</blockquote>\n<h3>4.3 激活 GitHub 部署</h3>\n<h4>4.3.1 第一步：点击 Setting</h4>\n<figure><figcaption></figcaption></figure>\n<h4>4.3.2 第二步：点击 Pages</h4>\n<figure><figcaption></figcaption></figure>\n<h4>4.3.3 第三步：选择 gh-pages 并 Save</h4>\n<figure><figcaption></figcaption></figure>\n<h4>4.3.4 尝试访问部署网站</h4>\n<p>域名已经给出：<a href=\"https://huangjiarongbao.github.io/\" target=\"_blank\" rel=\"noopener noreferrer\">https://huangjiarongbao.github.io/</a></p>\n<figure><figcaption></figcaption></figure>\n<figure><figcaption></figcaption></figure>\n<h3>4.4 更新网站</h3>\n<h4>4.4.1 方法一「推荐」</h4>\n<p>使用 VScode 进行提交即可，点击 VScode 左侧的 git 管理按钮：</p>\n<figure><figcaption></figcaption></figure>\n<figure><figcaption>首次使用会弹出提示，选择：始终</figcaption></figure>\n<p>省略一张图片，</p>\n<h4>4.4.2 方法二</h4>\n<div class=\"language-bash line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"bash\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-bash\"><span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">git</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> add</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> .</span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"> # . 代表添加所有文件夹、文件</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">git</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> commit</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> -m</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> \"first commit\"</span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">  # \"first commit\" 可以随便改，代表本次做了哪些修改，做个备注。不改，一直用这个也是可以的。</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">git</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> push</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> -u</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> origin</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> main</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><h3>4.5 查看是否部署成功</h3>\n<p>先进到自己的 GitHub 仓库，点击 Action：</p>\n<figure><figcaption></figcaption></figure>\n<h3>4.6 域名解析</h3>\n<h4>4.6.1 阿里云解析 GitHub 网站</h4>\n<p><strong>Step 1</strong>：访问阿里云域名解析网站：<a href=\"https://dnsnext.console.aliyun.com/authoritative\" target=\"_blank\" rel=\"noopener noreferrer\">https://dnsnext.console.aliyun.com/authoritative</a></p>\n<figure><figcaption></figcaption></figure>\n<p><strong>Step 2</strong>：点击：添加记录</p>\n<figure><figcaption>image-20260206113932437</figcaption></figure>\n<p><strong>Step 3</strong>：添加解析 1</p>\n<figure><figcaption></figcaption></figure>\n<p><strong>Step 4</strong>：添加解析 2</p>\n<figure><figcaption></figcaption></figure>\n<p>上面完成了阿里云域名要做的，现在我们来完成 GitHub 要做的。</p>\n<h4>4.6.2 创建域名解析文件「<code>CNAME</code>」</h4>\n<p>在<strong>路径</strong>：<code>src/.vuepress/public</code> 下创建 <code>CNAME</code> 。</p>\n<figure><figcaption></figcaption></figure>\n<figure><figcaption>写入你自己的域名</figcaption></figure>\n<p>保存后，推送到 GitHub 仓库。</p>\n<p>推送到 GitHub 后，会自动执行更新部署。</p>\n<figure><figcaption></figcaption></figure>\n<p>等待检测完成后，点击：</p>\n<figure><figcaption></figcaption></figure>\n<h2>5. 网站更多配置</h2>\n<h3>5.1 更新属于自己的 logo</h3>\n<p>可以借助 AI 设计生成属于自己的网站 logo，并把 logo 放入 <code>src/.vuepress/public</code>。MacOS 记得使用快捷键：<code>Command + Shift + 。</code> 即可显示隐藏文件、文件夹。</p>\n<figure><figcaption></figcaption></figure>\n<p>接着我们需要在 VScode 中进行配置 logo，配置文件路径：<code>src/.vuepress/theme.ts</code>。</p>\n<figure><figcaption></figcaption></figure>\n<div class=\"hint-container warning\">\n<p class=\"hint-container-title\">注意：在我们的网站当中，所有 <code>/</code> 代表从 <code>public</code> 开始。</p>\n<p>也就是：<code>/my-logo.png</code> 其实网站会执行成：<code>src/.vuepress/public/my-logo.png</code></p>\n</div>\n<h2>FAQ</h2>\n<h3>Q1：修改网站未生效</h3>\n<p>一般我们所做的任何修改，Vuepress 主题都能自动热重载（重新加载运行，实在理解不了，可以理解成：自动重启。）但是在某些情况下：新建文章、修改侧边栏图标等情况下，最新的效果无法在网页上体现出来。此时，解决的方法就是：手动关闭和启动一下。</p>\n<p>如果手动关闭与启动之后，问题依然存在。表明所做的修改存在问题，需要撤销修改，试一试别的。</p>\n<p>要取消时，弹出的优惠</p>\n<figure><figcaption></figcaption></figure>\n<details class=\"hint-container details\"><summary>公众号：AI悦创【二维码】</summary>\n<figure><img src=\"/gzh.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n</details>\n<div class=\"hint-container info\">\n<p class=\"hint-container-title\">AI悦创·编程一对一</p>\n<p>AI悦创·推出辅导班啦，包括「Python 语言辅导班、C++ 辅导班、java 辅导班、算法/数据结构辅导班、少儿编程、pygame 游戏开发、Web、Linux」，招收学员面向国内外，国外占 80%。全部都是一对一教学：一对一辅导 + 一对一答疑 + 布置作业 + 项目实践等。当然，还有线下线上摄影课程、Photoshop、Premiere 一对一教学、QQ、微信在线，随时响应！微信：Jiabcdefh</p>\n<p>C++ 信息奥赛题解，长期更新！长期招收一对一中小学信息奥赛集训，莆田、厦门地区有机会线下上门，其他地区线上。微信：Jiabcdefh</p>\n<p>方法一：<a href=\"http://wpa.qq.com/msgrd?v=3&amp;uin=1432803776&amp;site=qq&amp;menu=yes\" target=\"_blank\" rel=\"noopener noreferrer\">QQ</a></p>\n<p>方法二：微信：Jiabcdefh</p>\n</div>\n<figure><img src=\"/zsxq.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n",
      "date_published": "2026-01-31T14:20:34.000Z",
      "date_modified": "2026-02-06T04:24:56.000Z",
      "authors": [
        {
          "name": "AI悦创"
        }
      ],
      "tags": []
    },
    {
      "title": "08-文科生学 AI，一定要 Learn in public「AI转行的破局密钥」",
      "url": "https://bornforthis.cn/column/Python-Programming-Course/P09-FAQ/FAQ08.html",
      "id": "https://bornforthis.cn/column/Python-Programming-Course/P09-FAQ/FAQ08.html",
      "summary": "你好，我是悦创。 如果你是非技术背景，然后想转行到 AI 行业，现在在努力学 AI 的话，一定要 learn in public。什么叫 learn in public？就是你不仅要学，你还得让所有人都知道你在学，千万不要偷偷学。比如说你看到好的资料，可以给其他人共享这个资源，或者你用了一个好的 AI 产品，可以把你的感想分享到社交媒体。 为什么要这么...",
      "content_html": "<p>你好，我是悦创。</p>\n<p>如果你是非技术背景，然后想转行到 AI 行业，现在在努力学 AI 的话，一定要 learn in public。什么叫 learn in public？就是你不仅要学，你还得让所有人都知道你在学，千万不要偷偷学。比如说你看到好的资料，可以给其他人共享这个资源，或者你用了一个好的 AI 产品，可以把你的感想分享到社交媒体。</p>\n<p>为什么要这么做呢？因为我们现在在职场里不是学生了。你在学生时代，学完之后会有考试来检验你，但是你步入职场之后，学完之后如果没有人知道你学了，你就跟没有学一样。举个例子，如果你是文科商科背景，简历上没有任何 AI 相关的工作经验，但是你又想跳槽去 AI 公司，你怎么能跟你未来的雇主展示出你对 AI 技术的理解？怎么能展示出你是 AI 工具的深度使用者？怎么能展示出你甚至能自己开发出一些 AI 工具？</p>\n<p>即使你花过无数个小时上网看各种 AI 课程，如果你没有输出的话，就跟没有学一样，因为根本没有人知道你学过，它也没有办法用一个可以展示的方式体现出来。但是如果你日常就有这种记录、分享输出的习惯，你就慢慢地能建立一个自己的个人品牌和 audience。包括你以后在面试求职的时候，你可以直接把你的作品发给你的面试官，这就是对你能力最好的展示。</p>\n<p>其实内容是我们每个人在职场里的名片。</p>\n<p>你怎么让你未来的老板知道你对一个行业和一个技术的理解？——就是靠这些作品。</p>\n<p>并且这种输出的习惯也会驱使你更多的输入，就像费曼学习法说的，用输出来倒逼输入。当你有能力把一个东西给其他人讲明白的时候，这个东西你就真正的内化了，学会了。</p>\n<details class=\"hint-container details\"><summary>公众号：AI悦创【二维码】</summary>\n<figure><img src=\"/gzh.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n</details>\n<div class=\"hint-container info\">\n<p class=\"hint-container-title\">AI悦创·编程一对一</p>\n<p>AI悦创·推出辅导班啦，包括「Python 语言辅导班、C++ 辅导班、java 辅导班、算法/数据结构辅导班、少儿编程、pygame 游戏开发、Web、Linux」，招收学员面向国内外，国外占 80%。全部都是一对一教学：一对一辅导 + 一对一答疑 + 布置作业 + 项目实践等。当然，还有线下线上摄影课程、Photoshop、Premiere 一对一教学、QQ、微信在线，随时响应！微信：Jiabcdefh</p>\n<p>C++ 信息奥赛题解，长期更新！长期招收一对一中小学信息奥赛集训，莆田、厦门地区有机会线下上门，其他地区线上。微信：Jiabcdefh</p>\n<p>方法一：<a href=\"http://wpa.qq.com/msgrd?v=3&amp;uin=1432803776&amp;site=qq&amp;menu=yes\" target=\"_blank\" rel=\"noopener noreferrer\">QQ</a></p>\n<p>方法二：微信：Jiabcdefh</p>\n</div>\n<figure><img src=\"/zsxq.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n",
      "image": "https://bornforthis.cn/gzh.jpg",
      "date_published": "2026-01-23T18:37:55.000Z",
      "date_modified": "2026-01-23T15:11:55.000Z",
      "authors": [
        {
          "name": "AI悦创"
        }
      ],
      "tags": []
    },
    {
      "title": "08-2026 跨年烟花",
      "url": "https://bornforthis.cn/column/Python-Programming-Course/P10-Share/Interesting-project/08-newyear2026.html",
      "id": "https://bornforthis.cn/column/Python-Programming-Course/P10-Share/Interesting-project/08-newyear2026.html",
      "summary": "版本 1 公众号：AI悦创【二维码】 AI悦创·编程一对一 AI悦创·推出辅导班啦，包括「Python 语言辅导班、C++ 辅导班、java 辅导班、算法/数据结构辅导班、少儿编程、pygame 游戏开发、Web、Linux」，招收学员面向国内外，国外占 80%。全部都是一对一教学：一对一辅导 + 一对一答疑 + 布置作业 + 项目实践等。当然，还有线...",
      "content_html": "<h2>版本 1</h2>\n\n",
      "date_published": "2025-12-31T15:00:07.000Z",
      "date_modified": "2026-01-03T13:29:57.000Z",
      "authors": [
        {
          "name": "AI悦创"
        }
      ],
      "tags": []
    },
    {
      "title": "15-姜母鸭",
      "url": "https://bornforthis.cn/column/cookdinner/P01-%E8%8D%A4%E8%8F%9C%E7%B1%BB/04-%E9%85%B1%E9%A6%99%E7%94%9C%E5%8F%A3%E7%B1%BB/15-%E5%A7%9C%E6%AF%8D%E9%B8%AD.html",
      "id": "https://bornforthis.cn/column/cookdinner/P01-%E8%8D%A4%E8%8F%9C%E7%B1%BB/04-%E9%85%B1%E9%A6%99%E7%94%9C%E5%8F%A3%E7%B1%BB/15-%E5%A7%9C%E6%AF%8D%E9%B8%AD.html",
      "summary": "公众号：AI悦创【二维码】 AI悦创·编程一对一 AI悦创·推出辅导班啦，包括「Python 语言辅导班、C++ 辅导班、java 辅导班、算法/数据结构辅导班、少儿编程、pygame 游戏开发、Web、Linux」，招收学员面向国内外，国外占 80%。全部都是一对一教学：一对一辅导 + 一对一答疑 + 布置作业 + 项目实践等。当然，还有线下线上摄影...",
      "content_html": "\n",
      "image": "https://bornforthis.cn/gzh.jpg",
      "date_published": "2025-12-24T10:20:45.000Z",
      "date_modified": "2026-02-16T04:16:55.000Z",
      "authors": [
        {
          "name": "AI悦创"
        }
      ],
      "tags": []
    },
    {
      "title": "06-Gemini 实现圣诞树🎄",
      "url": "https://bornforthis.cn/column/Python-Programming-Course/P10-Share/Interesting-project/06-Christmas-tree.html",
      "id": "https://bornforthis.cn/column/Python-Programming-Course/P10-Share/Interesting-project/06-Christmas-tree.html",
      "summary": "1. 初代提示词 Gemini 聊天分享：https://gemini.google.com/share/aa96289aa318 https://gemini.google.com/share/013228923ddb 2. 代码迭代 3. 发布版本 https://gemini.google.com/share/7518f4f9a6ac 公众号：A...",
      "content_html": "<h2>1. 初代提示词</h2>\n<ul>\n<li>Gemini 聊天分享：<a href=\"https://gemini.google.com/share/aa96289aa318\" target=\"_blank\" rel=\"noopener noreferrer\">https://gemini.google.com/share/aa96289aa318</a></li>\n<li><a href=\"https://gemini.google.com/share/013228923ddb\" target=\"_blank\" rel=\"noopener noreferrer\">https://gemini.google.com/share/013228923ddb</a></li>\n</ul>\n<div class=\"language-txt line-numbers-mode has-collapsed-lines collapsed\" data-highlighter=\"shiki\" data-ext=\"txt\" style=\"--vp-collapsed-lines:15;--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-txt\"><span class=\"line\"><span>角色设定：你是一位精通Three.js、WebGL和计算机视觉的创意前端开发专家。</span></span>\n<span class=\"line\"><span>任务：编写一个包含HTML、CSS和JavaScript的单文件应用。该应用需要结合 Three.js 和 MediaPipe Hands 来创建一个基于手势控制的3D粒子特效系统。</span></span>\n<span class=\"line\"><span>要求：（此处大家根据想法扩展）</span></span>\n<span class=\"line\"><span>参考以下内容</span></span>\n<span class=\"line\"><span>#角色设定：</span></span>\n<span class=\"line\"><span>你是一位精通Three.js、WebGL和视觉设计前端开发。</span></span>\n<span class=\"line\"><span>##任务目标</span></span>\n<span class=\"line\"><span>编写一个包含HTML、CSS和JavaScript的单文件应用。该应用需要结合 Three.js 和 MediaPipe Hands 来创建一个基于手势控制的3D粒子+照片云构成的圣诞树。</span></span>\n<span class=\"line\"><span>##要求</span></span>\n<span class=\"line\"><span>1、&lt;整体内容:&gt;</span></span>\n<span class=\"line\"><span>-主色系:哑光绿 + 金属金+圣诞红色；</span></span>\n<span class=\"line\"><span>-有电影感的辉光与光晕效果，整体金碧辉煌有高级感</span></span>\n<span class=\"line\"><span>-圣诞树由 若干球、正方体、糖果棍和照片云等元素构成，照片通过上传获取。</span></span>\n<span class=\"line\"><span>2、&lt;交互逻辑和状态:&gt;</span></span>\n<span class=\"line\"><span>1、圣诞树状态</span></span>\n<span class=\"line\"><span>- 合拢态（初始状态）：所有元素收拢、聚合为一个圣诞树圆锥体。</span></span>\n<span class=\"line\"><span>- 散开态：所有元素在空间中无序漂浮、散落</span></span>\n<span class=\"line\"><span>- 照片放大态：在背景保持散开态的同时，放大单张照片</span></span>\n<span class=\"line\"><span>3、&lt;手势动作:&gt;</span></span>\n<span class=\"line\"><span>- 握拳表示回到合拢态</span></span>\n<span class=\"line\"><span>- 打开五指表示进入到散开态</span></span>\n<span class=\"line\"><span>- 手旋转表示在散开态的状态下，对画面进行旋转，根据手的移动调整相机角度</span></span>\n<span class=\"line\"><span>- 抓的动作表示抓住一张照片，进入照片放大态</span></span>\n<span class=\"line\"><span>4、&lt;交互要求:&gt;</span></span>\n<span class=\"line\"><span>需要根据手势，在几个状态之间平滑切换，带有过渡动画。</span></span>\n<span class=\"line\"><span>##包括但不限于使用以下技术栈 Three.js、WebGL、instanced Mesh、Shaders / GLSL、MediaPipe Hands</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div><div class=\"collapsed-lines\"></div></div><h2>2. 代码迭代</h2>\n\n",
      "image": "https://bornforthis.cn/gzh.jpg",
      "date_published": "2025-12-21T21:31:34.000Z",
      "date_modified": "2025-12-24T11:42:20.000Z",
      "authors": [
        {
          "name": "AI悦创"
        }
      ],
      "tags": []
    },
    {
      "title": "白嫖Gemini Pro 12 个月！教你过大部分Sheerid简单难度认证",
      "url": "https://bornforthis.cn/column/Python-Programming-Course/P10-Share/Interesting-project/02-sheerid-guide-google-ai-one-easy-verification.html",
      "id": "https://bornforthis.cn/column/Python-Programming-Course/P10-Share/Interesting-project/02-sheerid-guide-google-ai-one-easy-verification.html",
      "summary": "[Sheerid 通用教程] [google ai one +] 教你过大部分Sheerid简单难度认证 你好，我是悦创。 本教程适用于大部分 Sheerid 简单难度认证。 1. 注册教育邮箱📮 如果要方便，或者轻松。可以找我购买教育邮箱，添加微信：Jiabcdefh。 Step 1：访问 PennState 访问链接：https://accoun...",
      "content_html": "<div style=\"text-align:center\">\n<h3>[Sheerid 通用教程] [google ai one +] 教你过大部分Sheerid简单难度认证</h3>\n</div>\n<p>你好，我是悦创。</p>\n<p>本教程适用于大部分 Sheerid 简单难度认证。</p>\n<h2>1. 注册教育邮箱📮</h2>\n<p>如果要方便，或者轻松。可以找我购买教育邮箱，添加微信：Jiabcdefh。</p>\n<h3>Step 1：访问 PennState</h3>\n<p>访问链接：<a href=\"https://accounts.psu.edu\" target=\"_blank\" rel=\"noopener noreferrer\">https://accounts.psu.edu</a>，并点击创建 <code>CREATE MY ACCOUNT</code>。</p>\n<figure><figcaption></figcaption></figure>\n<h3>Step 2：开始创建</h3>\n<h4>1. 勾选接受，并点击下一步：Next：</h4>\n<figure><figcaption></figcaption></figure>\n<h4>2. 填写个人信息</h4>\n<p>随便填写信息，除了邮箱正确之外其余可以随便乱填，然后一分钟你就拿到一个专门用于过 sheerid 的 <code>@psu.edu</code> 账号（无邮箱）</p>\n<figure><figcaption></figcaption></figure>\n<h4>3. 填写个人信息「2」</h4>\n<p>Personal Information - Part 2</p>\n<figure><figcaption></figcaption></figure>\n<h4>4. Contact Details</h4>\n<figure><figcaption></figcaption></figure>\n<h4>5. 有可能会出现地址问题，可以随意：</h4>\n<figure><figcaption></figcaption></figure>\n<h4>6. 点击 Next</h4>\n<figure><figcaption></figcaption></figure>\n<h4>7. Verifying It's You</h4>\n<p>会给你的邮箱发送验证码，自己查收填写：</p>\n<figure><figcaption></figcaption></figure>\n<h4>8. Policy Agreement</h4>\n<p>勾选，并点击下一步即可：</p>\n<figure><figcaption></figcaption></figure>\n<h4>9. 设置密码，完成！</h4>\n<figure><figcaption></figcaption></figure>\n<h4>10. 当你看见如下界面，表明注册成功！</h4>\n<figure><figcaption></figcaption></figure>\n<h2>2. 领取谷歌教育优惠</h2>\n<p>Sheerid 认证：以Google为例。</p>\n<h3>2.1 访问 Google 学生优惠网站</h3>\n<p>链接：<a href=\"https://gemini.google/students/\" target=\"_blank\" rel=\"noopener noreferrer\">https://gemini.google/students/</a></p>\n<p>访问链接后，点击 Get offer：</p>\n<figure><figcaption></figcaption></figure>\n<h3>2.2 填写信息</h3>\n<p>按下面截图来填即可，最后的邮箱按照前面注册得到的邮箱来使用即可！</p>\n<blockquote>\n<p>在 20+ 个 PSU 校区中随机选取一个即可，搜索出来一页都是 PSU，意味着你申请一个 PSU 可以用 20 多次。</p>\n</blockquote>\n<p><strong>提示</strong>：名字生日随便乱填，邮箱填你刚才拿到的 <code>@psu.edu</code> 账号，然后继续完成 <code>SSO流程</code>：</p>\n<figure><figcaption></figcaption></figure>\n<h3>2.3 完成 SSO 流程</h3>\n<figure><figcaption></figcaption></figure>\n<figure><figcaption></figcaption></figure>\n<figure><figcaption></figcaption></figure>\n<h3>2.4 验证成功！</h3>\n<figure><figcaption></figcaption></figure>\n<h2>3. 绑定支付方式，自己用自己的国内 Visa 卡就可以</h2>\n<details class=\"hint-container details\"><summary>公众号：AI悦创【二维码】</summary>\n<figure><img src=\"/gzh.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n</details>\n<div class=\"hint-container info\">\n<p class=\"hint-container-title\">AI悦创·编程一对一</p>\n<p>AI悦创·推出辅导班啦，包括「Python 语言辅导班、C++ 辅导班、java 辅导班、算法/数据结构辅导班、少儿编程、pygame 游戏开发、Web、Linux」，招收学员面向国内外，国外占 80%。全部都是一对一教学：一对一辅导 + 一对一答疑 + 布置作业 + 项目实践等。当然，还有线下线上摄影课程、Photoshop、Premiere 一对一教学、QQ、微信在线，随时响应！微信：Jiabcdefh</p>\n<p>C++ 信息奥赛题解，长期更新！长期招收一对一中小学信息奥赛集训，莆田、厦门地区有机会线下上门，其他地区线上。微信：Jiabcdefh</p>\n<p>方法一：<a href=\"http://wpa.qq.com/msgrd?v=3&amp;uin=1432803776&amp;site=qq&amp;menu=yes\" target=\"_blank\" rel=\"noopener noreferrer\">QQ</a></p>\n<p>方法二：微信：Jiabcdefh</p>\n</div>\n<figure><img src=\"/zsxq.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n<details class=\"hint-container details\"><summary>.</summary>\n<ul>\n<li>Name：Bornforthis Bornforthis</li>\n<li>User ID：bbb5969</li>\n<li>Penn State ID：981305446</li>\n<li><code>bbb5969@psu.edu</code></li>\n</ul>\n</details>\n",
      "date_published": "2025-12-04T16:51:54.000Z",
      "date_modified": "2025-12-06T08:08:35.000Z",
      "authors": [
        {
          "name": "AI悦创"
        }
      ],
      "tags": []
    },
    {
      "title": "01-Gemini3 手势跟踪实现「含：提示词」",
      "url": "https://bornforthis.cn/column/Python-Programming-Course/P10-Share/Interesting-project/01-Gemini3-jarvis-holographic-ui.html",
      "id": "https://bornforthis.cn/column/Python-Programming-Course/P10-Share/Interesting-project/01-Gemini3-jarvis-holographic-ui.html",
      "summary": "你好，我是悦创。 最近在短视频平台上无意刷到，Gemini3 实现手部动态跟踪的项目，效果图如下： 在线访问使用链接：https://gemini.bornforthis.cn/jarvis-holographic-ui/ 1. 提示词 2. 相关链接 在线体验：https://gemini.bornforthis.cn/jarvis-holograp...",
      "content_html": "<p>你好，我是悦创。</p>\n<p>最近在短视频平台上无意刷到，Gemini3 实现手部动态跟踪的项目，效果图如下：</p>\n<figure><figcaption></figcaption></figure>\n<figure><figcaption></figcaption></figure>\n<p>在线访问使用链接：<a href=\"https://gemini.bornforthis.cn/jarvis-holographic-ui/\" target=\"_blank\" rel=\"noopener noreferrer\">https://gemini.bornforthis.cn/jarvis-holographic-ui/</a></p>\n<h2>1. 提示词</h2>\n\n<h2>2. 相关链接</h2>\n<ul>\n<li>在线体验：<a href=\"https://gemini.bornforthis.cn/jarvis-holographic-ui/\" target=\"_blank\" rel=\"noopener noreferrer\">https://gemini.bornforthis.cn/jarvis-holographic-ui/</a></li>\n<li>Google AI 项目链接：<a href=\"https://ai.studio/apps/drive/18Qn9o31ppMAO0xhiE5IX3JqFjNf_pHdv?fullscreenApplet=true\" target=\"_blank\" rel=\"noopener noreferrer\">https://ai.studio/apps/drive/18Qn9o31ppMAO0xhiE5IX3JqFjNf_pHdv?fullscreenApplet=true</a></li>\n<li>Github 源代码分享：<a href=\"https://github.com/AndersonHJB/jarvis-holographic-ui\" target=\"_blank\" rel=\"noopener noreferrer\">https://github.com/AndersonHJB/jarvis-holographic-ui</a></li>\n</ul>\n<h2>3. 福利</h2>\n<p>学习编程相关，可以添加我。年底书籍上市，不一定只找我学私教。可以提前加入微信群，等待年底新书上市购买学习，以及诸多福利。</p>\n<p><strong>微信：Jiabcdefh</strong></p>\n<p>现在关注公众号：AI悦创，即可领取 31 天的梯子～</p>\n<details class=\"hint-container details\"><summary>公众号：AI悦创【二维码】</summary>\n<figure><img src=\"/gzh.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n</details>\n<div class=\"hint-container info\">\n<p class=\"hint-container-title\">AI悦创·编程一对一</p>\n<p>AI悦创·推出辅导班啦，包括「Python 语言辅导班、C++ 辅导班、java 辅导班、算法/数据结构辅导班、少儿编程、pygame 游戏开发、Web、Linux」，招收学员面向国内外，国外占 80%。全部都是一对一教学：一对一辅导 + 一对一答疑 + 布置作业 + 项目实践等。当然，还有线下线上摄影课程、Photoshop、Premiere 一对一教学、QQ、微信在线，随时响应！微信：Jiabcdefh</p>\n<p>C++ 信息奥赛题解，长期更新！长期招收一对一中小学信息奥赛集训，莆田、厦门地区有机会线下上门，其他地区线上。微信：Jiabcdefh</p>\n<p>方法一：<a href=\"http://wpa.qq.com/msgrd?v=3&amp;uin=1432803776&amp;site=qq&amp;menu=yes\" target=\"_blank\" rel=\"noopener noreferrer\">QQ</a></p>\n<p>方法二：微信：Jiabcdefh</p>\n</div>\n<figure><img src=\"/zsxq.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n",
      "date_published": "2025-12-01T10:51:10.000Z",
      "date_modified": "2025-12-05T11:18:29.000Z",
      "authors": [
        {
          "name": "AI悦创"
        }
      ],
      "tags": []
    },
    {
      "title": "00-01-课前热身｜10道题帮你测试 AI “安全分”",
      "url": "https://bornforthis.cn/column/Python-Programming-Course/P12-llm-security-hands-on-course/00-1-keqian-reshen-10-ti-ce-shi-ai-anquan-fen.html",
      "id": "https://bornforthis.cn/column/Python-Programming-Course/P12-llm-security-hands-on-course/00-1-keqian-reshen-10-ti-ce-shi-ai-anquan-fen.html",
      "summary": "你好，我是悦创。 在开篇词我曾提到，大模型安全不是一个“选修课”，而是行业落地绕不开的必答题。那么在正式开始课程之前，我们不妨来简单测试一下你的 AI 产品 / 服务的“安全分”是多少。 我准备了十道题目，你可以记录一下每道题的选项，再结合最后的计分规则看看得了多少分。 Question 1 第一题：你的企业正在准备将大模型部署到智能客服系统中，与用户...",
      "content_html": "<figure><figcaption></figcaption></figure>\n<p>你好，我是悦创。</p>\n<p>在开篇词我曾提到，大模型安全不是一个“<strong>选修课</strong>”，而是行业落地绕不开的必答题。那么在正式开始课程之前，我们不妨来简单测试一下你的 AI 产品 / 服务的“安全分”是多少。</p>\n<p>我准备了十道题目，你可以记录一下每道题的选项，再结合最后的计分规则看看得了多少分。</p>\n<h2>Question 1</h2>\n<p><strong>第一题：你的企业正在准备将大模型部署到智能客服系统中，与用户进行直接交互。你希望对用户输入的提示内容做安全防护以避免触发模型违规响应。在提示词过滤机制上，你们的设计更接近哪种方式？</strong></p>\n<p>A. 模型内置关键词过滤系统，敏感词库通过人工定期维护，并可结合上下文关系做一定程度的模糊匹配。</p>\n<p>B. 使用语义理解模型识别提示意图，覆盖多类变体表达，过滤规则较为通用，适配不同业务场景。</p>\n<p>C. 构建了多层级提示词过滤机制，融合关键词、语义匹配与上下文语境分析，具备实时自更新能力。</p>\n<p>D. 主要采用关键词过滤与规则模板判断，过滤范围明确，覆盖典型高风险场景，配置稳定性较强。</p>\n<h2>Question 2</h2>\n<p><strong>第二题：你们团队准备将大模型用于生成财务、人事、合规等敏感场景的文案。面对这些高风险任务，你们系统中的防护设计更接近哪种方式？</strong></p>\n<p>A. 系统通过接口识别当前业务类型，动态加载相关风控策略和输出模板。</p>\n<p>B. 针对这些话题配置了统一的回答模板，避免生成自由扩展内容。</p>\n<p>C. 模型在响应前对内容做规则评估，不区分业务语境，采用同一套输出规则。</p>\n<p>D. 默认允许模型生成完整答案，只在出现指定关键词时触发屏蔽逻辑。</p>\n<h2>Question 3</h2>\n<p><strong>第三题：你注意到最近模型偶尔会出现短时间内的响应异常，比如延迟、崩溃或输出中断。你认为以下哪种做法最有助于识别并防范 Prompt DoS（提示词拒绝服务）攻击？</strong></p>\n<p>A. 我们建立了提示词行为画像，监控嵌套结构、提问频率与上下文突变，以识别可疑请求。</p>\n<p>B. 我们设置了接口调用速率和响应时间阈值，只要超出即中断处理流程。</p>\n<p>C. 我们使用关键词白名单与模型温度限制来降低生成不确定性，减少系统负载</p>\n<p>D. 我们通过日志分析定位异常会话，对可疑账号追加冷却时间，并同时优化硬件配置提升稳定性。</p>\n<h2>Question 4</h2>\n<p><strong>第四题：你的团队希望模型具备一定的“越狱防护”能力，以避免用户通过提示词诱导模型输出本不该说的内容。以下哪种做法最具实效性，能主动识别此类绕过行为？</strong></p>\n<p>A. 引入关键词联动审查机制，并设置风险等级，超过阈值触发人工审核。</p>\n<p>B. 通过正则表达式识别提示中是否包含绕过或角色扮演的暗示意图。</p>\n<p>C. 使用多模态语义匹配 + 上下文语义一致性分析，识别提示是否试图“扮演第三方”以实现越权目标。</p>\n<p>D. 在模型输出前强制追加“请勿违规输出”的系统提示词，以提醒模型保持中立和规范。</p>\n<h2>Question 5</h2>\n<p><strong>第五题：你的模型已经正式上线，公司要求对用户行为与模型响应过程保留审计日志，以便后续进行问题追踪与安全溯源。以下哪种做法最符合“可审计性”和“合规溯源”的安全要求？</strong></p>\n<p>A. 对用户输入提示词进行存档，但不记录模型响应内容，以节省存储。</p>\n<p>B. 保留用户请求日志和部分模型响应片段，重要事件由人工截图存证。</p>\n<p>C. 仅对高风险场景（如涉政、涉黄）记录日志，其余请求不做记录以保护隐私。</p>\n<p>D. 对全部请求与响应进行结构化归档，并可结合时间戳、用户 ID 快速检索回溯。</p>\n<h2>Question 6</h2>\n<p><strong>第六题：你们的团队发现，当前大模型在处理一些行业术语和专业逻辑时，偶尔会生成编造的数据或张冠李戴的事实（即“幻觉”）。你希望建立一套机制来降低这类问题的风险。以下哪种做法在现阶段更具有实操性与安全防控效能？</strong></p>\n<p>A. 依赖用户反馈标记错误样例，并定期通过精调来修复模型行为。</p>\n<p>B. 在模型输出阶段，加入基于规则与置信度阈值的内容过滤与二次确认机制。</p>\n<p>C. 提前在预训练语料中加入更多真实资料，让模型“记牢”正确内容。</p>\n<p>D. 允许模型输出自由生成内容，但在显著场景下添加免责声明即可规避风险。</p>\n<h2>Question 7</h2>\n<p><strong>第七题：你的团队负责上线后大语言模型的安全运营，现在已发布多个版本。在面对策略调整与模型更新时，哪种管理方式最能体现“动态安全能力”的理念？</strong></p>\n<p>A. 我们每个版本都配置有默认规则集，并允许业务团队进行参数微调来适配使用场景。</p>\n<p>B. 目前团队稳定运行已有三个月，尚未遇到安全问题，因此暂未开启更新机制。</p>\n<p>C. 每次迭代发布前，工程团队会参考历史数据回顾，必要时调整部分提示语与响应策略。</p>\n<p>D. 模型版本发布流程中，默认嵌入安全策略回归、行为验证与审计流程，确保每次更新后的策略一致性与鲁棒性。</p>\n<h2>Question 8</h2>\n<p><strong>第八题：你所在的团队计划将大模型用于客户支持系统，模型将直接与外部用户交互。考虑到潜在的品牌舆情风险（如谈及竞品、公众人物等），你们主要采取哪类防控手段？</strong></p>\n<p>A. 设计了一套用于敏感话题绕开的通用回答模版，尽可能避免争议话题。</p>\n<p>B. 将用户输入与模型输出同时纳入语义风险识别，构建品牌词和敏感对象的动态响应策略。</p>\n<p>C. 设置品牌领域的专业问答数据微调模型，以确保内容更聚焦且符合品牌立场。</p>\n<p>D. 结合提示词限制、用户画像分析和多轮对话上下文，制定适配的内容生成边界策略。</p>\n<h2>Question 9</h2>\n<p>第九题：你的团队计划将大模型集成进智能问答平台，面向终端用户提供法律、财税等咨询服务。考虑到“答案可信度”和“可解释性”的重要性，你们目前在输出解释性方面采取了什么措施？</p>\n<p>A. 模型输出后附带参考内容的来源链接与生成理由摘要。</p>\n<p>B. 为所有高风险内容附加预警标识，并通过用户交互获取反馈。</p>\n<p>C. 利用训练数据的来源信息构建文档索引供后台追溯，但前端不显示。</p>\n<p>D. 将提示词与输出记录全部留档，便于内部内容溯源与后期优化。</p>\n<h2>Question 10</h2>\n<p><strong>第十题：你所在的企业已经上线了一个大模型问答平台，服务于客服、法务、财务等多个敏感业务场景。为确保系统在面对攻击性提示词、恶意上下文操控等威胁时的稳健性，你们目前采取了什么方式来开展安全评估？</strong></p>\n<p>A. 日常运营中由产品团队定期进行功能测试，发现问题后及时修复。</p>\n<p>B. 建立了一套 QA 用例库，主要覆盖正常业务流程与基本异常场景。</p>\n<p>C. 与业务部门协同开展用户测试，但未涉及提示词操控或越狱演练。</p>\n<p>D. 定期组织红队对抗演练，并引入第三方安全机构进行外部评估。</p>\n<h2>答案计分参照表</h2>\n<figure><figcaption></figcaption></figure>\n<h2>总得分评估结果</h2>\n<figure><figcaption></figcaption></figure>\n<figure><figcaption></figcaption></figure>\n<figure><figcaption></figcaption></figure>\n<figure><figcaption></figcaption></figure>\n<p>这十道热身题，不是为了考核你，而是帮助你发现盲点。如果你愿意，我们接下来的课程将逐一解答这些问题，并带你完成一场从感知、识别到体系建设的安全进阶之旅。</p>\n\n<details class=\"hint-container details\"><summary>公众号：AI悦创【二维码】</summary>\n<figure><img src=\"/gzh.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n</details>\n<div class=\"hint-container info\">\n<p class=\"hint-container-title\">AI悦创·编程一对一</p>\n<p>AI悦创·推出辅导班啦，包括「Python 语言辅导班、C++ 辅导班、java 辅导班、算法/数据结构辅导班、少儿编程、pygame 游戏开发、Web、Linux」，招收学员面向国内外，国外占 80%。全部都是一对一教学：一对一辅导 + 一对一答疑 + 布置作业 + 项目实践等。当然，还有线下线上摄影课程、Photoshop、Premiere 一对一教学、QQ、微信在线，随时响应！微信：Jiabcdefh</p>\n<p>C++ 信息奥赛题解，长期更新！长期招收一对一中小学信息奥赛集训，莆田、厦门地区有机会线下上门，其他地区线上。微信：Jiabcdefh</p>\n<p>方法一：<a href=\"http://wpa.qq.com/msgrd?v=3&amp;uin=1432803776&amp;site=qq&amp;menu=yes\" target=\"_blank\" rel=\"noopener noreferrer\">QQ</a></p>\n<p>方法二：微信：Jiabcdefh</p>\n</div>\n<figure><img src=\"/zsxq.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n",
      "date_published": "2025-11-27T08:01:31.000Z",
      "date_modified": "2025-11-27T02:32:16.000Z",
      "authors": [
        {
          "name": "AI悦创"
        }
      ],
      "tags": []
    },
    {
      "title": "18-梅花小酥肉",
      "url": "https://bornforthis.cn/column/cookdinner/P07-%E7%89%B9%E8%89%B2%E7%94%9C%E9%A3%9F%E5%B0%8F%E5%90%83/18-%E6%A2%85%E8%8A%B1%E5%B0%8F%E9%85%A5%E8%82%89.html",
      "id": "https://bornforthis.cn/column/cookdinner/P07-%E7%89%B9%E8%89%B2%E7%94%9C%E9%A3%9F%E5%B0%8F%E5%90%83/18-%E6%A2%85%E8%8A%B1%E5%B0%8F%E9%85%A5%E8%82%89.html",
      "summary": "公众号：AI悦创【二维码】 AI悦创·编程一对一 AI悦创·推出辅导班啦，包括「Python 语言辅导班、C++ 辅导班、java 辅导班、算法/数据结构辅导班、少儿编程、pygame 游戏开发、Web、Linux」，招收学员面向国内外，国外占 80%。全部都是一对一教学：一对一辅导 + 一对一答疑 + 布置作业 + 项目实践等。当然，还有线下线上摄影...",
      "content_html": "\n",
      "image": "https://bornforthis.cn/gzh.jpg",
      "date_published": "2025-11-26T09:26:13.000Z",
      "date_modified": "2025-11-26T14:52:59.000Z",
      "authors": [
        {
          "name": "AI悦创"
        }
      ],
      "tags": []
    },
    {
      "title": "01-为什么要用花雕酒",
      "url": "https://bornforthis.cn/column/cookdinner/P13-%E5%BF%83%E5%BE%97/01-%E4%B8%BA%E4%BB%80%E4%B9%88%E8%A6%81%E7%94%A8%E8%8A%B1%E9%9B%95%E9%85%92.html",
      "id": "https://bornforthis.cn/column/cookdinner/P13-%E5%BF%83%E5%BE%97/01-%E4%B8%BA%E4%BB%80%E4%B9%88%E8%A6%81%E7%94%A8%E8%8A%B1%E9%9B%95%E9%85%92.html",
      "summary": "料酒是厨房去腥增香的常用调味品，但选择哪一种，却直接影响菜肴的最终风味。市面上不少料酒实为香辛料与劣质黄酒的勾兑产物，用于炒菜、拌馅或酱肉时，不仅难以去除腥气，有时甚至会带来酸涩等异味。 相比之下，花雕酒则是数千年黄酒文化的沉淀。它本是饮用之物，如著名的女儿红、状元红皆属此类。花雕酒遵循古法，选用粮食与鉴湖水，仅在冬季酿造一茬，酒香醇厚。入菜后能真正达...",
      "content_html": "<p>料酒是厨房去腥增香的常用调味品，但选择哪一种，却直接影响菜肴的最终风味。市面上不少料酒实为香辛料与劣质黄酒的勾兑产物，用于炒菜、拌馅或酱肉时，不仅难以去除腥气，有时甚至会带来酸涩等异味。</p>\n<p>相比之下，花雕酒则是数千年黄酒文化的沉淀。它本是饮用之物，如著名的女儿红、状元红皆属此类。花雕酒遵循古法，选用粮食与鉴湖水，仅在冬季酿造一茬，酒香醇厚。入菜后能真正达到去腥增香的效果，且不留杂味。</p>\n<p>作为一名业余“厨师”，我亲历了从使用大坛黄酒到专注于花雕酒的过程。尤其在粤菜烹饪中，花雕酒因其独特的焦糖香气备受青睐。</p>\n<p>选择花雕酒亦有讲究。</p>\n<p>我家常备的是一款五年陈酿，香气饱满，既可入菜，也可温热饮用，冬日小酌还有暖胃之效。一酒两用，既提升了菜肴层次，也增添了一份生活意趣。将普通料酒升级为花雕酒，无疑是提升烹饪水平的一个简单而有效的选择。</p>\n<details class=\"hint-container details\"><summary>公众号：AI悦创【二维码】</summary>\n<figure><img src=\"/gzh.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n</details>\n<div class=\"hint-container info\">\n<p class=\"hint-container-title\">AI悦创·编程一对一</p>\n<p>AI悦创·推出辅导班啦，包括「Python 语言辅导班、C++ 辅导班、java 辅导班、算法/数据结构辅导班、少儿编程、pygame 游戏开发、Web、Linux」，招收学员面向国内外，国外占 80%。全部都是一对一教学：一对一辅导 + 一对一答疑 + 布置作业 + 项目实践等。当然，还有线下线上摄影课程、Photoshop、Premiere 一对一教学、QQ、微信在线，随时响应！微信：Jiabcdefh</p>\n<p>C++ 信息奥赛题解，长期更新！长期招收一对一中小学信息奥赛集训，莆田、厦门地区有机会线下上门，其他地区线上。微信：Jiabcdefh</p>\n<p>方法一：<a href=\"http://wpa.qq.com/msgrd?v=3&amp;uin=1432803776&amp;site=qq&amp;menu=yes\" target=\"_blank\" rel=\"noopener noreferrer\">QQ</a></p>\n<p>方法二：微信：Jiabcdefh</p>\n</div>\n<figure><img src=\"/zsxq.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n",
      "image": "https://bornforthis.cn/gzh.jpg",
      "date_published": "2025-11-18T21:53:00.000Z",
      "date_modified": "2025-11-18T14:30:10.000Z",
      "authors": [
        {
          "name": "AI悦创"
        }
      ],
      "tags": []
    },
    {
      "title": "时间复杂度的讲解及总结",
      "url": "https://bornforthis.cn/1v1/101-Sallymisty/Exam/time-complexity-python-examples.html",
      "id": "https://bornforthis.cn/1v1/101-Sallymisty/Exam/time-complexity-python-examples.html",
      "summary": "你好，我是悦创。 时间复杂度是衡量一个算法执行效率的重要指标，它表示随着输入数据规模的增加，算法执行时间增长的速度。时间复杂度通常以大 O 记法表示，关注最坏情况的时间增长趋势。 以下是常见的时间复杂度类型及其对应的 Python 代码示例，涵盖了常见的操作和算法，帮助你更好地理解每种时间复杂度。 1. 时间复杂度的讲解 1.1 O(1) - 常数时间...",
      "content_html": "<p>你好，我是悦创。</p>\n<p>时间复杂度是衡量一个算法执行效率的重要指标，它表示随着输入数据规模的增加，算法执行时间增长的速度。时间复杂度通常以大 O 记法表示，关注最坏情况的时间增长趋势。</p>\n<p>以下是常见的时间复杂度类型及其对应的 Python 代码示例，涵盖了常见的操作和算法，帮助你更好地理解每种时间复杂度。</p>\n<h2>1. 时间复杂度的讲解</h2>\n<h3>1.1 O(1) - 常数时间复杂度</h3>\n<p>常数时间复杂度意味着无论输入数据的规模多大，算法的执行时间都不会改变。</p>\n<p><strong>示例</strong>：</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> constant_time_example</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">arr</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> arr[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]  </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 只访问了第一个元素，时间复杂度是 O(1)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 示例</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">arr </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">4</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">constant_time_example</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(arr))</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p><strong>时间复杂度分析</strong>：该算法访问数组的第一个元素，操作次数不随数组大小变化，因此时间复杂度为 <strong>O(1)</strong>。</p>\n<h3>1.2 O(n) - 线性时间复杂度</h3>\n<p>线性时间复杂度意味着算法的执行时间随着输入数据规模的增加而线性增长。</p>\n<p><strong>示例</strong>：</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> linear_time_example</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">arr</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    total </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 0</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> num </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> arr:  </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 遍历数组每个元素</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">        total </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> num</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> total</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 示例</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">arr </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">4</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">5</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">linear_time_example</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(arr))</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p><strong>时间复杂度分析</strong>：算法需要遍历数组的每个元素，因此执行次数与数组的大小 <strong>n</strong> 成正比，时间复杂度为 <strong>O(n)</strong>。</p>\n<h3>1.3 <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><msup><mi>n</mi><mn>2</mn></msup><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(n^2)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1.0641em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord\"><span class=\"mord mathnormal\">n</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8141em;\"><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span></span></span></span></span><span class=\"mclose\">)</span></span></span></span> - 平方时间复杂度</h3>\n<p>平方时间复杂度通常出现在嵌套循环中，意味着算法的执行时间随着数据规模的增加呈平方增长。</p>\n<p><strong>示例</strong>：</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> quadratic_time_example</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">arr</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> i </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> range</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(arr)):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> j </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> range</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(arr)):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">            print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(arr[i], arr[j])  </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 双重循环</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 示例</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">arr </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">quadratic_time_example</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(arr)</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p><strong>时间复杂度分析</strong>：该算法包含两个嵌套的循环，每个循环都执行 <strong>n</strong> 次，因此时间复杂度为 <strong><span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><msup><mi>n</mi><mn>2</mn></msup><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(n^2)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1.0641em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord\"><span class=\"mord mathnormal\">n</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8141em;\"><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span></span></span></span></span><span class=\"mclose\">)</span></span></span></span></strong>。</p>\n<h3>1.4 O(log n) - 对数时间复杂度</h3>\n<p>对数时间复杂度通常出现在递归算法中，例如二分查找。它表示算法的执行时间随数据规模的增加呈对数增长。</p>\n<p><strong>示例</strong>：</p>\n<div class=\"language-python line-numbers-mode has-collapsed-lines collapsed\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--vp-collapsed-lines:15;--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> binary_search</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">arr</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> target</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    left, right </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(arr) </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 1</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    while</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> left </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&lt;=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> right:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">        mid </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> (left </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> right) </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">//</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 2</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> arr[mid] </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">==</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> target:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">            return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> mid</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        elif</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> arr[mid] </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&lt;</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> target:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">            left </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> mid </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 1</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        else</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">            right </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> mid </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 1</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> -</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 示例</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">arr </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">4</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">5</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">6</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">7</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">8</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">9</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">target </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 5</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">binary_search</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(arr, target))</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div><div class=\"collapsed-lines\"></div></div><p><strong>时间复杂度分析</strong>：每次查找都将问题规模减半，因此时间复杂度为 <strong>O(log n)</strong>。</p>\n<h3>1.5 O(n log n) - 线性对数时间复杂度</h3>\n<p>常见的 <strong>O(n log n)</strong> 时间复杂度出现在高效的排序算法中，例如归并排序、快速排序等。</p>\n<p><strong>示例（快速排序）</strong>：</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> quick_sort</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">arr</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    if</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(arr) </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&lt;=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> arr</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    pivot </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> arr[</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(arr) </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">//</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    left </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> [x </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> x </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> arr </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> x </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&lt;</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> pivot]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    middle </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> [x </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> x </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> arr </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> x </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">==</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> pivot]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    right </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> [x </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> x </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> arr </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> x </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&gt;</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> pivot]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> quick_sort</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(left) </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> middle </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> quick_sort</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(right)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 示例</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">arr </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">6</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">8</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">10</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">quick_sort</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(arr))</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p><strong>时间复杂度分析</strong>：快速排序的时间复杂度是 <strong>O(n log n)</strong>，因为每次分割数组为两部分，然后对每部分递归排序，分割的过程是 <strong>O(log n)</strong>，每次分割需要处理 <strong>n</strong> 个元素。</p>\n<h3>1.6 <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><msup><mn>2</mn><mi>n</mi></msup><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(2^n)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord\"><span class=\"mord\">2</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.6644em;\"><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\">n</span></span></span></span></span></span></span></span><span class=\"mclose\">)</span></span></span></span> - 指数时间复杂度</h3>\n<p>指数时间复杂度通常出现在递归算法中，意味着算法的执行时间随着输入数据规模的增加呈指数增长。</p>\n<p><strong>示例（斐波那契数列）</strong>：</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> fibonacci</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">n</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> n </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&lt;=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> n</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> fibonacci</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(n</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">) </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> fibonacci</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(n</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 示例</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">fibonacci</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">6</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">))</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p><strong>时间复杂度分析</strong>：斐波那契数列的递归算法的时间复杂度为 <strong><span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><msup><mn>2</mn><mi>n</mi></msup><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(2^n)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord\"><span class=\"mord\">2</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.6644em;\"><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\">n</span></span></span></span></span></span></span></span><span class=\"mclose\">)</span></span></span></span></strong>，因为每个递归调用会生成两个子问题，递归树的大小以指数方式增长。</p>\n<h3>1.7 <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mi>n</mi><mo stretchy=\"false\">!</mo><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(n!)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">n</span><span class=\"mclose\">!)</span></span></span></span> - 阶乘时间复杂度</h3>\n<p>阶乘时间复杂度常出现在排列组合相关问题中，如暴力破解的排列问题。</p>\n<p><strong>示例（全排列）</strong>：</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">import</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> itertools</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> generate_permutations</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">arr</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    return</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> list</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(itertools.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">permutations</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(arr))</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 示例</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">arr </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">generate_permutations</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(arr))</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p><strong>时间复杂度分析</strong>：全排列的数量是 <strong>n!</strong>，即输入数据的所有可能排列组合，因此时间复杂度为 <strong>O(n!)</strong>。</p>\n<h3>1.8 总结</h3>\n<p>| 时间复杂度类型 | 示例               | 时间复杂度分析                                         |<br>\n|</p>\n",
      "image": "https://bornforthis.cn/gzh.jpg",
      "date_published": "2025-11-04T07:31:26.000Z",
      "date_modified": "2025-11-04T07:31:00.000Z",
      "authors": [
        {
          "name": "AI悦创"
        }
      ],
      "tags": []
    },
    {
      "title": "Excel IF 入门教学",
      "url": "https://bornforthis.cn/blog/2025/10month/Excel-IF.html",
      "id": "https://bornforthis.cn/blog/2025/10month/Excel-IF.html",
      "summary": "你好，我是悦创。 Excel 中的 IF 函数用于根据给定的条件返回不同的值。 1. 基本语法 示例： 2. 常见逻辑比较符号 3. 嵌套 IF（多条件判断） 当需要判断多个等级时，可以嵌套使用： 👉 从左到右依次判断条件，一旦满足，就不会继续判断后面的条件。 4. IF 结合其他函数的高级用法 与 AND 组合（多个条件都要满足） ➤ 当 A1 和...",
      "content_html": "<p>你好，我是悦创。</p>\n<p>Excel 中的 <code>IF</code> 函数用于根据给定的条件返回不同的值。</p>\n<h2>1. 基本语法</h2>\n<div class=\"language-excel line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"excel\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-excel\"><span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">IF(逻辑测试,</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> 真值,</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> 假值</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div></div></div><p>| 参数     | 说明                                 |<br>\n|</p>\n",
      "image": "https://bornforthis.cn/gzh.jpg",
      "date_published": "2025-10-26T10:28:52.000Z",
      "date_modified": "2025-10-26T11:01:26.000Z",
      "authors": [
        {
          "name": "bornforthis"
        }
      ],
      "tags": []
    },
    {
      "title": "Excel MID 入门学习",
      "url": "https://bornforthis.cn/blog/2025/10month/Excel-MID.html",
      "id": "https://bornforthis.cn/blog/2025/10month/Excel-MID.html",
      "summary": "你好，我是悦创。 Excel 中的 MID 函数用于从一个文本字符串的中间提取指定数量的字符。它的语法如下： 1. 参数说明 text：这是你要从中提取字符的文本字符串。 start_num：从文本字符串的哪个位置开始提取。第一个字符的位置是 1。 num_chars：你希望提取的字符数。 2. 示例 2.1 示例 1 假设单元格 A1 的内容是 \"E...",
      "content_html": "<p>你好，我是悦创。</p>\n<p>Excel 中的 <strong>MID</strong> 函数用于从一个文本字符串的中间提取指定数量的字符。它的语法如下：</p>\n<div class=\"language-excel line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"excel\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-excel\"><span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">MID(text,</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> start_num,</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> num_chars</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div></div></div><h2>1. 参数说明</h2>\n<ul>\n<li><strong>text</strong>：这是你要从中提取字符的文本字符串。</li>\n<li><strong>start_num</strong>：从文本字符串的哪个位置开始提取。第一个字符的位置是 1。</li>\n<li><strong>num_chars</strong>：你希望提取的字符数。</li>\n</ul>\n<h2>2. 示例</h2>\n<h3>2.1 示例 1</h3>\n<p>假设单元格 A1 的内容是 <code>\"Excel1234\"</code>，你想从第 6 个字符开始提取 4 个字符。</p>\n<div class=\"language-excel line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"excel\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-excel\"><span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">=MID</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">A1,</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> 6,</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 4</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div></div></div><p><strong>结果</strong>：<code>1234</code></p>\n<h3>2.2 示例 2</h3>\n<p>如果 A2 中是 <code>\"Hello World\"</code>，你想提取从第 7 个字符开始的 5 个字符：</p>\n<div class=\"language-excel line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"excel\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-excel\"><span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">=MID</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">A2,</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> 7,</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 5</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div></div></div><p><strong>结果</strong>：<code>World</code></p>\n<h2>3. 注意</h2>\n<ul>\n<li><code>start_num</code> 的位置是基于字符串的字符位置。</li>\n<li>如果 <code>start_num</code> 超出了文本的总长度，或者 <code>num_chars</code> 的字符数超过了文本的剩余字符数，<code>MID</code> 会返回剩余的字符。</li>\n</ul>\n<p>这样，你可以根据需求灵活使用 <strong>MID</strong> 函数来提取不同位置的字符。</p>\n<h2>4. 实操</h2>\n<ul>\n<li><a href=\"https://github.com/AndersonHJB/BornforthisData/blob/main/bornforthis.cn/blog/2025/10month/Excel-MID/MID%20%E5%87%BD%E6%95%B0%E7%BB%83%E4%B9%A0.xlsx\" target=\"_blank\" rel=\"noopener noreferrer\">https://github.com/AndersonHJB/BornforthisData/blob/main/bornforthis.cn/blog/2025/10month/Excel-MID/MID%20%E5%87%BD%E6%95%B0%E7%BB%83%E4%B9%A0.xlsx</a></li>\n</ul>\n<details class=\"hint-container details\"><summary>公众号：AI悦创【二维码】</summary>\n<figure><img src=\"/gzh.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n</details>\n<div class=\"hint-container info\">\n<p class=\"hint-container-title\">AI悦创·编程一对一</p>\n<p>AI悦创·推出辅导班啦，包括「Python 语言辅导班、C++ 辅导班、java 辅导班、算法/数据结构辅导班、少儿编程、pygame 游戏开发、Web、Linux」，招收学员面向国内外，国外占 80%。全部都是一对一教学：一对一辅导 + 一对一答疑 + 布置作业 + 项目实践等。当然，还有线下线上摄影课程、Photoshop、Premiere 一对一教学、QQ、微信在线，随时响应！微信：Jiabcdefh</p>\n<p>C++ 信息奥赛题解，长期更新！长期招收一对一中小学信息奥赛集训，莆田、厦门地区有机会线下上门，其他地区线上。微信：Jiabcdefh</p>\n<p>方法一：<a href=\"http://wpa.qq.com/msgrd?v=3&amp;uin=1432803776&amp;site=qq&amp;menu=yes\" target=\"_blank\" rel=\"noopener noreferrer\">QQ</a></p>\n<p>方法二：微信：Jiabcdefh</p>\n</div>\n<figure><img src=\"/zsxq.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n",
      "image": "https://bornforthis.cn/gzh.jpg",
      "date_published": "2025-10-26T10:16:03.000Z",
      "date_modified": "2025-10-26T02:42:45.000Z",
      "authors": [
        {
          "name": "AI悦创"
        }
      ],
      "tags": []
    },
    {
      "title": "Excel TRIM 入门学习",
      "url": "https://bornforthis.cn/blog/2025/10month/Excel-TRIM.html",
      "id": "https://bornforthis.cn/blog/2025/10month/Excel-TRIM.html",
      "summary": "1. TRIM 函数的作用 TRIM 函数 用来删除文本中的多余空格，只保留单词之间的一个空格。 1.1 功能总结： 去掉文本开头和结尾的所有空格； 将文本中连续的多个空格变成一个空格。 1.2 语法 参数说明： 1.3 示例讲解 1.4 注意事项 TRIM 只删除普通空格（ASCII 32），不能删除一些特殊空格（例如网页中的不间断空格 CHAR(1...",
      "content_html": "<h2>1. TRIM 函数的作用</h2>\n<p><strong>TRIM 函数</strong> 用来<strong>删除文本中的多余空格</strong>，只保留单词之间的一个空格。</p>\n<h3>1.1 功能总结：</h3>\n<ul>\n<li>去掉文本<strong>开头</strong>和<strong>结尾</strong>的所有空格；</li>\n<li>将文本中<strong>连续的多个空格</strong>变成<strong>一个空格</strong>。</li>\n</ul>\n<h3>1.2 语法</h3>\n<div class=\"language-excel line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"excel\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-excel\"><span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">=TRIM</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">text</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div></div></div><p><strong>参数说明：</strong></p>\n<p>| 参数 | 说明                                             |<br>\n|</p>\n",
      "image": "https://bornforthis.cn/gzh.jpg",
      "date_published": "2025-10-26T10:04:35.000Z",
      "date_modified": "2025-10-26T02:42:45.000Z",
      "authors": [
        {
          "name": "bornforthis"
        }
      ],
      "tags": []
    },
    {
      "title": "Excel FIND 函数入门",
      "url": "https://bornforthis.cn/blog/2025/10month/Excel-FIND.html",
      "id": "https://bornforthis.cn/blog/2025/10month/Excel-FIND.html",
      "summary": "你好，我是悦创。 下面我来系统讲解 Excel 的 FIND 函数，并配上示例和练习思路。 1. FIND 函数的作用 功能： 在一个文本字符串中，查找指定字符或字符串首次出现的位置，并返回其位置（数字）。 ✅ FIND区分大小写。 ✅ 如果找不到目标字符，会返回错误值 #VALUE! 2. 语法 3. 例子讲解 4. 常见用法组合 配合 LEFT 或...",
      "content_html": "<p>你好，我是悦创。</p>\n<p>下面我来<strong>系统讲解 Excel 的 FIND 函数</strong>，并配上示例和练习思路。</p>\n<h2>1. FIND 函数的作用</h2>\n<p><strong>功能：</strong> 在一个文本字符串中，<strong>查找指定字符或字符串首次出现的位置</strong>，并返回其位置（数字）。</p>\n<blockquote>\n<p>✅ FIND区分大小写。</p>\n<p>✅ 如果找不到目标字符，会返回错误值 <code>#VALUE!</code></p>\n</blockquote>\n<h2>2. 语法</h2>\n<div class=\"language-excel line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"excel\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-excel\"><span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">=FIND</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">find_text,</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> within_text,</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> [start_num])</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div></div></div><p>| 参数                   | 说明                             |<br>\n|</p>\n",
      "image": "https://bornforthis.cn/gzh.jpg",
      "date_published": "2025-10-25T20:27:57.000Z",
      "date_modified": "2025-10-25T12:58:01.000Z",
      "authors": [
        {
          "name": "AI悦创"
        }
      ],
      "tags": []
    },
    {
      "title": "Excel LEFT 函数入门",
      "url": "https://bornforthis.cn/blog/2025/10month/Excel-LEFT.html",
      "id": "https://bornforthis.cn/blog/2025/10month/Excel-LEFT.html",
      "summary": "你好，我是悦创。 我来一步步教你认识并使用 Excel 的 LEFT 函数。 1. LEFT 函数的作用 LEFT 函数用于从文本字符串的左侧开始，提取指定数量的字符。 2. 基本语法 3. 举例说明 3.1 示例 1：提取前两个字符 假设单元格 A1 内容是： 你想提取前两个数字： ✅ 结果：12 3.2 示例 2：只取第一个字符 ✅ 结果：1 （因...",
      "content_html": "<p>你好，我是悦创。</p>\n<p>我来一步步教你认识并使用 <strong>Excel 的 <code>LEFT</code> 函数</strong>。</p>\n<h2>1. LEFT 函数的作用</h2>\n<p><code>LEFT</code> 函数用于<strong>从文本字符串的左侧开始，提取指定数量的字符</strong>。</p>\n<h2>2. 基本语法</h2>\n<div class=\"language-excel line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"excel\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-excel\"><span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">=LEFT</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">text,</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> [num_chars])</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div></div></div><p>| 参数          | 说明                                                         |<br>\n|</p>\n",
      "image": "https://bornforthis.cn/gzh.jpg",
      "date_published": "2025-10-25T20:08:08.000Z",
      "date_modified": "2025-10-25T12:58:01.000Z",
      "authors": [
        {
          "name": "AI悦创"
        }
      ],
      "tags": []
    },
    {
      "title": "09-豆角烧土豆焖饭",
      "url": "https://bornforthis.cn/column/cookdinner/P05-%E9%A5%AD%E7%B1%BB%E4%B8%BB%E9%A3%9F%E9%9D%A2%E7%82%B9/09-%E8%B1%86%E8%A7%92%E7%83%A7%E5%9C%9F%E8%B1%86%E7%84%96%E9%A5%AD.html",
      "id": "https://bornforthis.cn/column/cookdinner/P05-%E9%A5%AD%E7%B1%BB%E4%B8%BB%E9%A3%9F%E9%9D%A2%E7%82%B9/09-%E8%B1%86%E8%A7%92%E7%83%A7%E5%9C%9F%E8%B1%86%E7%84%96%E9%A5%AD.html",
      "summary": "豆角烧土豆焖饭 原料：五花肉 400 克，豆角 300 克，土豆 400 克，八角 2 克，桂皮 2 克，干辣椒 2 个，姜 5 克，大葱 20 克，花雕酒 20 克，酱油 50 克，开水 1.5 千克，盐 3 克，白胡椒粉 1 克，老抽 10 克，米饭 1 千克，葱花 10 克，白芝麻3克。 1. 食材 2. 步骤 提前蒸好干饭、烧好开水； 个人感觉...",
      "content_html": "<blockquote>\n<p>豆角烧土豆焖饭 原料：五花肉 400 克，豆角 300 克，土豆 400 克，八角 2 克，桂皮 2 克，干辣椒 2 个，姜 5 克，大葱 20 克，花雕酒 20 克，酱油 50 克，开水 1.5 千克，盐 3 克，白胡椒粉 1 克，老抽 10 克，米饭 1 千克，葱花 10 克，白芝麻3克。</p>\n</blockquote>\n<h2>1. 食材</h2>\n<p>| 五花肉     | 豆角                 | 土豆     | 八角   | 桂皮       | 干辣椒   | 姜       | 大葱       |<br>\n|</p>\n",
      "image": "https://bornforthis.cn/gzh.jpg",
      "date_published": "2025-10-23T08:40:13.000Z",
      "date_modified": "2025-10-24T00:50:45.000Z",
      "authors": [
        {
          "name": "AI悦创"
        }
      ],
      "tags": []
    },
    {
      "title": "Excel vlookup函数零基础入门",
      "url": "https://bornforthis.cn/blog/2025/10month/excel-vlookup.html",
      "id": "https://bornforthis.cn/blog/2025/10month/excel-vlookup.html",
      "summary": "你好，我是悦创。 为私教学员编写教程： VLOOKUP 是 Excel 中非常常用的查找函数，用来纵向查找某个值，并返回同一行中其他列的数据。它的名字也来自于这个功能：Vertical Lookup（纵向查找）。 1. 基础教程 1.1 VLOOKUP 函数语法 各参数解释如下： 语法结构拆解 1. 基础拆解 Sheet2：工作表名称（也可能是“员工数...",
      "content_html": "<p>你好，我是悦创。</p>\n<p>为私教学员编写教程：</p>\n\n<p><code>VLOOKUP</code> 是 Excel 中非常常用的查找函数，用来<strong>纵向查找某个值，并返回同一行中其他列的数据</strong>。它的名字也来自于这个功能：<strong>Vertical Lookup（纵向查找）</strong>。</p>\n<h2>1. 基础教程</h2>\n<h3>1.1 VLOOKUP 函数语法</h3>\n<figure><figcaption></figcaption></figure>\n<div class=\"language-excel line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"excel\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-excel\"><span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">=VLOOKUP</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">lookup_value,</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> table_array,</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> col_index_num,</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> [range_lookup])</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div></div></div><p>各参数解释如下：</p>\n<p>| 参数             | 含义                                                         | 示例         |<br>\n|</p>\n",
      "date_published": "2025-10-21T18:44:30.000Z",
      "date_modified": "2025-10-24T13:40:55.000Z",
      "authors": [
        {
          "name": "bornforthis"
        }
      ],
      "tags": []
    },
    {
      "title": "08-抱蛋豆腐",
      "url": "https://bornforthis.cn/column/cookdinner/P05-%E9%A5%AD%E7%B1%BB%E4%B8%BB%E9%A3%9F%E9%9D%A2%E7%82%B9/08-%E6%8A%B1%E8%9B%8B%E8%B1%86%E8%85%90.html",
      "id": "https://bornforthis.cn/column/cookdinner/P05-%E9%A5%AD%E7%B1%BB%E4%B8%BB%E9%A3%9F%E9%9D%A2%E7%82%B9/08-%E6%8A%B1%E8%9B%8B%E8%B1%86%E8%85%90.html",
      "summary": "1. 食材 2. 步骤 老豆腐切块，正方形块； 准备大蒜，拍碎； 大葱切小圈、洋葱切丝、小葱头、葱花； 碗中打入鸡蛋+白胡椒粉+鸡粉； 料汁：适量白胡椒粉、适量盐、一勺鸡粉、两勺黄酒、一勺香油、半勺老抽、一小勺蚝油、两勺生抽、一大碗水； 锅中：凉水+盐+生抽——>下入：豆腐，烧开 3 分钟；（煮到产生蜂窝状） 锅热，加多一些油：把一面煎制金黄，翻面继续...",
      "content_html": "<h2>1. 食材</h2>\n<p>| 老豆腐       | 大蒜     | 大葱 | 小葱 | 洋葱 | 鸡蛋 |<br>\n|</p>\n",
      "image": "https://bornforthis.cn/gzh.jpg",
      "date_published": "2025-10-21T11:56:24.000Z",
      "date_modified": "2025-11-02T14:36:59.000Z",
      "authors": [
        {
          "name": "bornforthis"
        }
      ],
      "tags": []
    },
    {
      "title": "Homework 4-Sentiment Analysis",
      "url": "https://bornforthis.cn/1v1/93-LiquidLeon/Homework-4-Sentiment-Analysis.html",
      "id": "https://bornforthis.cn/1v1/93-LiquidLeon/Homework-4-Sentiment-Analysis.html",
      "summary": "https://github.com/AndersonHJB/BornforthisData/tree/main/bornforthis.cn/1v1/93-LiquidLeon/Homework-4-Sentiment-Analysishttps://github.com/AndersonHJB/BornforthisData/tree/main/b...",
      "content_html": "<figure><figcaption><a href=\"https://github.com/AndersonHJB/BornforthisData/tree/main/bornforthis.cn/1v1/93-LiquidLeon/Homework-4-Sentiment-Analysis\" target=\"_blank\" rel=\"noopener noreferrer\">https://github.com/AndersonHJB/BornforthisData/tree/main/bornforthis.cn/1v1/93-LiquidLeon/Homework-4-Sentiment-Analysis</a></figcaption></figure>\n<p>This is a <strong>partner</strong> homework. You may complete it individually if you choose, but know that it was designed to be done in partnerships.</p>\n<ul>\n<li>\n<p>Late passes:</p>\n<ul>\n<li>\n<p>If both partners have a late pass, you may turn in late with no questions asked/permission required.</p>\n</li>\n<li>\n<p>If one partner has a late pass and one does not, you may turn this work in up to 24 hrs late with no questions asked (formal extensions required for 48 hours).</p>\n</li>\n<li>\n<p>If no partners have late passes, a formal extension must be requested following the syllabus in the case of needing extra time.</p>\n</li>\n</ul>\n</li>\n</ul>\n<p><strong>Please watch this video before you get started with the homework:</strong><br>\n<a href=\"https://northeastern.hosted.panopto.com/Panopto/Pages/Viewer.aspx?id=178d4e3f-56ba-466f-85c9-b10f001d5a4a\" target=\"_blank\" rel=\"noopener noreferrer\">https://northeastern.hosted.panopto.com/Panopto/Pages/Viewer.aspx?id=178d4e3f-56ba-466f-85c9-b10f001d5a4a</a></p>\n<p>Starter files:</p>\n<ul>\n<li>Skeleton notebooks: sentiment_task015.ipynb、sentiment_task2.ipynb、sentiment_task3.ipynb、sentiment_task4.ipynb</li>\n<li>Skeleton python utilities file: sentiment_utils_starter_skeletons.py</li>\n</ul>\n<p>Data files:</p>\n<ul>\n<li>Movie training and dev sets: movie_reviews_train.txt、movie_reviews_dev.txt</li>\n</ul>\n<p>Turn in these files:</p>\n<ul>\n<li>Your 4 completed notebooks</li>\n<li>Your <code>sentiment_utils.py</code></li>\n<li>Nine graphs (3 for each of the classifiers: NB, LR, NN)</li>\n</ul>\n<div style=\"text-align:center\">\n<h3>Homework 4: Sentiment Analysis - Task 0, Task 1, Task 5 (all primarily written tasks)</h3>\n</div>\n<p>The following instructions are only written in this notebook but apply to all notebooks and <code>.py</code> files you submit for this homework.</p>\n<p><strong>Due date: October 22nd, 2025 @ 9:00 PM</strong></p>\n<p>Points:</p>\n<ul>\n<li>Task 0: 5 points</li>\n<li>Task 1: 10 points</li>\n<li>Task 2: 30 points</li>\n<li>Task 3: 20 points</li>\n<li>Task 4: 20 points</li>\n<li>Task 5: 15 points</li>\n</ul>\n<p>Goals:</p>\n<ul>\n<li>understand the difficulties of counting and probablities in NLP applications</li>\n<li>work with real world data to build a functioning language model</li>\n<li>stress test your model (to some extent)</li>\n</ul>\n<p>Complete in groups of: <strong>two (pairs)</strong>. If you prefer to work on your own, you may, but be aware that this homework has been designed as a partner project.</p>\n<p>Allowed python modules:</p>\n<ul>\n<li><code>numpy</code>, <code>matplotlib</code>, <code>keras</code>, <code>pytorch</code>, <code>nltk</code>, <code>pandas</code>, <code>sci-kit learn</code> (<code>sklearn</code>), <code>seaborn</code>, and all built-in python libraries (e.g. <code>math</code> and <code>string</code>)</li>\n<li>if you would like to use a library not on this list, post on piazza to request permission</li>\n<li>all <em>necessary</em> imports have been included for you (all imports that we used in our solution)</li>\n</ul>\n<p>Instructions:</p>\n<ul>\n<li>Complete outlined problems in this notebook.</li>\n<li>When you have finished, <strong>clear the kernel</strong> and <strong>run</strong> your notebook \"fresh\" from top to bottom. Ensure that there are <strong>no errors</strong>.\n<ul>\n<li>If a problem asks for you to write code that does result in an error (as in, the answer to the problem is an error), leave the code in your notebook but commented out so that running from top to bottom does not result in any errors.</li>\n</ul>\n</li>\n<li>Double check that you have completed Task 0.</li>\n<li>Submit your work on Gradescope.</li>\n<li>Double check that your submission on Gradescope looks like you believe it should <strong>and</strong> that all partners are included (for partner work).</li>\n</ul>\n<h2>Task 0: Name, References, Reflection (5 points)</h2>\n<h3>Names</h3>\n<p>Names: <strong>YOUR NAMES HERE</strong> (Write these in every notebook you submit.)</p>\n<h3>References</h3>\n<p><strong>If you used AI tools (like ChatGPT, Claude, Gemini, Copilot, etc.) at any stage of your work, you must explicitly mention them and acknowledge their role. Please also state that you take full responsibility for the final content.</strong></p>\n<p>Example AI acknowledgment:</p>\n<p>\"The author acknowledges the use of Claude AI (Anthropic) for assistance with content organization and executive summary structure. All final interpretations and conclusions remain the author’s responsibility.\"</p>\n<p><strong>List the resources you consulted to complete this homework here. Write one sentence per resource about what it provided to you. If you consulted no references to complete your assignment, write a brief sentence stating that this is the case and why it was the case for you.</strong></p>\n<p>(Example)</p>\n<ul>\n<li><a href=\"https://docs.python.org/3/tutorial/datastructures.html\" target=\"_blank\" rel=\"noopener noreferrer\">https://docs.python.org/3/tutorial/datastructures.html</a>\n<ul>\n<li>Read about the the basics and syntax for data structures in python.</li>\n</ul>\n</li>\n</ul>\n<h3>Reflection</h3>\n<p>Answer the following questions <strong>after</strong> you complete this assignment (no more than 1 sentence per question required, this section is graded on completion):</p>\n<ol>\n<li>Does this work reflect your best effort?</li>\n<li>What was/were the most challenging part(s) of the assignment?</li>\n<li>If you want feedback, what function(s) or problem(s) would you like feedback on and why?</li>\n<li>Briefly reflect on how your partnership functioned--who did which tasks, how was the workload on each of you individually as compared to the previous homeworks, etc.</li>\n</ol>\n<h2>Task 1: Provided Data Write-Up (10 points)</h2>\n<p>Every time you use a data set in an NLP application (or in any software application), you should be able to answer a set of questions about that data. Answer these now. Default to no more than 1 sentence per question needed. If more explanation is necessary, do give it.</p>\n<p>This is about the <strong>provided</strong> movie review data set.</p>\n<ol>\n<li>\n<p>Where did you get the data from? The provided dataset(s) were sub-sampled from <a href=\"https://www.kaggle.com/datasets/lakshmi25npathi/imdb-dataset-of-50k-movie-reviews\" target=\"_blank\" rel=\"noopener noreferrer\">https://www.kaggle.com/datasets/lakshmi25npathi/imdb-dataset-of-50k-movie-reviews</a></p>\n<blockquote>\n<p>数据来自Kaggle网站上的IMDB电影评论数据集，链接为：<a href=\"https://www.kaggle.com/datasets/lakshmi25npathi/imdb-dataset-of-50k-movie-reviews\" target=\"_blank\" rel=\"noopener noreferrer\">https://www.kaggle.com/datasets/lakshmi25npathi/imdb-dataset-of-50k-movie-reviews</a></p>\n</blockquote>\n</li>\n<li>\n<p>(1 pt) How was the data collected (where did the people acquiring the data get it from and how)?</p>\n<blockquote>\n<p>数据是从IMDB网站上收集的，评论者提供了对电影的评价和反馈，涵盖了不同种类的电影，数据通过网页抓取或通过API访问获取。</p>\n</blockquote>\n</li>\n<li>\n<p>(2 pts) How large is the dataset (answer for both the train and the dev set, separately)? (# reviews, # tokens in both the train and dev sets)</p>\n<blockquote>\n<p>训练集包含1600条评论，验证集包含200条评论。</p>\n<p>训练集和验证集的评论每条大致包含230到235个词汇。</p>\n<p>训练集和验证集的词汇表大小分别为47,638和11,709，二者有7,245个词汇是重叠的。</p>\n</blockquote>\n<details class=\"hint-container details\"><summary>详情</summary>\n<div class=\"language-python line-numbers-mode has-collapsed-lines collapsed\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--vp-collapsed-lines:15;--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 导入必要的库</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">import</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> pandas </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">as</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> pd</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 读取训练集和验证集文件</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">train_file </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> 'movie_reviews_train.txt'</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">dev_file </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> 'movie_reviews_dev.txt'</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 读取数据</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">train_data </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> pd.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">read_csv</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(train_file, </span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">sep</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">\\t</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">header</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">None</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">names</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">[</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"ID\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"Review\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"Label\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">])</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">dev_data </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> pd.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">read_csv</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(dev_file, </span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">sep</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">\\t</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">header</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">None</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">names</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">[</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"ID\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"Review\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"Label\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">])</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 计算训练集和验证集的评论数和每条评论的词汇数</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">train_num_reviews </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(train_data)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">dev_num_reviews </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(dev_data)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 计算每条评论的词汇数</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">train_token_counts </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> train_data[</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'Review'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">].</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">apply</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">lambda</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> x</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: </span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(x.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">split</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()))</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">dev_token_counts </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> dev_data[</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'Review'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">].</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">apply</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">lambda</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> x</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: </span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(x.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">split</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()))</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 计算训练集和验证集的词汇数量</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">train_vocab_size </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">set</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\" \"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">join</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(train_data[</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'Review'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]).</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">split</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()))</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">dev_vocab_size </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">set</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\" \"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">join</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(dev_data[</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'Review'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]).</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">split</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()))</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 计算训练集和验证集的词汇表重叠</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">train_vocab </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> set</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\" \"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">join</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(train_data[</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'Review'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]).</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">split</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">())</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">dev_vocab </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> set</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\" \"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">join</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(dev_data[</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'Review'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]).</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">split</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">())</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">vocab_overlap </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(train_vocab.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">intersection</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(dev_vocab))</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 输出结果</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">train_num_reviews, dev_num_reviews, train_token_counts.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">describe</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(), dev_token_counts.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">describe</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(), train_vocab_size, dev_vocab_size, vocab_overlap</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div><div class=\"collapsed-lines\"></div></div></details>\n</li>\n<li>\n<p>(1 pt) What is your data? (i.e. newswire, tweets, books, blogs, etc)</p>\n<blockquote>\n<p>数据是关于电影的评论，属于影评数据集。</p>\n</blockquote>\n</li>\n<li>\n<p>(1 pt) Who produced the data? (who were the authors of the text? Your answer might be a specific person or a particular group of people)</p>\n<blockquote>\n<p>数据的作者是 IMDB 网站上的用户（Lakshmipathi N、arunmohan_003、Co-learning Lounge），这些评论是由全球影迷和观众根据他们对电影的看法和评价写的。</p>\n</blockquote>\n</li>\n<li>\n<p>(2 pts) What is the distribution of labels in the data (answer for both the train and the dev set, separately)?</p>\n<blockquote>\n<p>训练集和验证集的标签分布大致均衡。标签是二分类的（0 代表负面评价，1 代表正面评价），训练集和验证集的正负评价大致相同。</p>\n</blockquote>\n<details class=\"hint-container details\"><summary>详情</summary>\n<ul>\n<li><strong>训练集标签分布</strong>：\n<ul>\n<li>正面评价（Label=1）：804条</li>\n<li>负面评价（Label=0）：796条</li>\n</ul>\n</li>\n<li><strong>验证集标签分布</strong>：\n<ul>\n<li>正面评价（Label=1）：105条</li>\n<li>负面评价（Label=0）：95条</li>\n</ul>\n</li>\n</ul>\n<p>因此，训练集和验证集的标签分布是大致均衡的。</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 计算训练集和验证集标签的分布</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">train_label_distribution </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> train_data[</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'Label'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">].</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">value_counts</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">dev_label_distribution </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> dev_data[</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'Label'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">].</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">value_counts</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">train_label_distribution, dev_label_distribution</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div></details>\n</li>\n<li>\n<p>(2 pts) How large is the vocabulary (answer for both the train and the dev set, separately)?</p>\n<blockquote>\n<p>训练集的词汇表大小为 47,638。</p>\n<p>验证集的词汇表大小为 11,709。</p>\n</blockquote>\n<details class=\"hint-container details\"><summary>详情</summary>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 重新计算独立词汇数量</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">train_vocab_unique </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> set</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\" \"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">join</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(train_data[</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'Review'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]).</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">split</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">())</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">dev_vocab_unique </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> set</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\" \"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">join</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(dev_data[</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'Review'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]).</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">split</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">())</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 输出训练集和验证集的独立词汇表大小</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(train_vocab_unique), </span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(dev_vocab_unique)</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div></details>\n</li>\n<li>\n<p>(1 pt) How big is the overlap between the vocabulary for the train and dev set?</p>\n<blockquote>\n<p>训练集和验证集的词汇表之间有一定的重叠，约为 6132 左右，表示很多常见的词汇在两个数据集中都有出现。</p>\n</blockquote>\n<details class=\"hint-container details\"><summary>详情</summary>\n<div class=\"language-python line-numbers-mode has-collapsed-lines collapsed\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--vp-collapsed-lines:15;--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">import</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> nltk</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">from</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> nltk.tokenize </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">import</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> word_tokenize</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">from</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> collections </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">import</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> Counter</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 下载punkt分词模型（如果尚未下载）</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">nltk.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">download</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'punkt'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">nltk.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">download</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'punkt_tab'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 读取并分词的函数</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> load_and_tokenize</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">file_path</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    with</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> open</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(file_path, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'r'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">encoding</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'utf8'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">) </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">as</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\"> file</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">        reviews </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\"> file</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">readlines</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">    # 提取评论文本（去除电影ID和评分）</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    reviews_text </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> [line.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">split</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">\\t</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">] </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> line </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> reviews </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">if</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(line.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">strip</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()) </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&gt;</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">    # 分词</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    tokenized_reviews </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> [</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">word_tokenize</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(review.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">lower</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()) </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> review </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> reviews_text]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> tokenized_reviews</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 读取并分词训练集和验证集的评论</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">train_file_path </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> 'movie_reviews_train.txt'</span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">  # 修改为您训练集的文件路径</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">dev_file_path </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> 'movie_reviews_dev.txt'</span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">      # 修改为您验证集的文件路径</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">train_reviews </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> load_and_tokenize</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(train_file_path)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">dev_reviews </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> load_and_tokenize</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(dev_file_path)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 获取训练集和验证集的词汇表（唯一词汇）</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">train_vocab </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> set</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">([word </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> review </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> train_reviews </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> word </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> review])</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">dev_vocab </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> set</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">([word </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> review </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> dev_reviews </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> word </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> review])</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 计算训练集和验证集词汇表之间的重叠</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">overlap_vocab </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> train_vocab.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">intersection</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(dev_vocab)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">overlap_size </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(overlap_vocab)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 输出词汇重叠的大小</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">f</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"词汇表重叠的大小: </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">{</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">overlap_size</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">}</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div><div class=\"collapsed-lines\"></div></div></details>\n</li>\n</ol>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># our utility functions</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># RESTART your jupyter notebook kernel if you make changes to this file</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">import</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> sentiment_utils </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">as</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> sutils</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># Feel free to write code to help answer the above questions</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><h2>Task 2: Train a Naive Bayes Model (30 points)</h2>\n<p>Using <code>nltk</code>'s <code>NaiveBayesClassifier</code> class, train a Naive Bayes classifier using a Bag of Words as features.</p>\n<p>You will be implementing <strong>binarized</strong> (presence/absence of word) and <strong>multinomial</strong> (counts of word) BoW representations of your data</p>\n<p>Learn more about Naive Bayes here: <a href=\"https://www.nltk.org/_modules/nltk/classify/naivebayes.html\" target=\"_blank\" rel=\"noopener noreferrer\">https://www.nltk.org/_modules/nltk/classify/naivebayes.html</a></p>\n<p>Naive Bayes classifiers use Bayes’ theorem for predictions. Naive Bayes can be a good baseline for NLP applications in particular. You can use it as a baseline for your project!</p>\n<p><strong>10 points in Task 5 will be allocated for all 9 graphs (including the one generated here in Task 4 for Naive Bayes Classifier) being:</strong></p>\n<ul>\n<li>Legible</li>\n<li>Present below</li>\n<li>Properly labeled\n<ul>\n<li>x and y axes labeled</li>\n<li>Legend for accuracy measures plotted</li>\n<li>Plot Title with which model and run number the graph represents</li>\n</ul>\n</li>\n</ul>\n<div class=\"language-python line-numbers-mode has-collapsed-lines collapsed\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--vp-collapsed-lines:15;--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># our utility functions</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># RESTART your jupyter notebook kernel if you make changes to this file</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">import</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> sentiment_utils </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">as</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> sutils</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># nltk for Naive Bayes and metrics</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">import</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> nltk</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">import</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> nltk.classify.util</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">from</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> nltk.metrics.scores </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">import</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> (precision, recall, f_measure, accuracy)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">from</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> nltk.classify </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">import</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> NaiveBayesClassifier</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># some potentially helpful data structures from collections</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">from</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> collections </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">import</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> defaultdict, Counter</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># so that we can make plots</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">import</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> matplotlib.pyplot </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">as</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> plt</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># if you want to use seaborn to make plots</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">#import seaborn as sns</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># define constants for the files we are using</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">TRAIN_FILE</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> =</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> \"movie_reviews_train.txt\"</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">DEV_FILE</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> =</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> \"movie_reviews_dev.txt\"</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># load in your data and make sure you understand the format</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># Do not print out too much so as to impede readability of your notebook</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">train_tups </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> sutils.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">generate_tuples_from_file</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">TRAIN_FILE</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">dev_tups </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> sutils.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">generate_tuples_from_file</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">DEV_FILE</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># set up a sentiment classifier using NLTK's NaiveBayesClassifier and </span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># a bag of words as features</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># take a look at the function in lecture notebook 7 (feel free to copy + paste that function)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># the nltk classifier expects a dictionary of features as input where the key is the feature name</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># and the value is the feature value</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># need to return a dict to work with the NLTK classifier</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># Possible problem for students: evaluate the difference </span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># between using binarized features and using counts (non binarized features)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> word_feats</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-dark:#ABB2BF\">PARAMETERS ARE UP TO </span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">YOU</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">) -&gt; </span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">dict</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:    </span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">    # STUDENTS IMPLEMENT</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    pass</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">         </span></span>\n<span class=\"line\"></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># set up &amp; train a sentiment classifier using NLTK's NaiveBayesClassifier and</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># classify the first example in the dev set as an example</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># make sure your output is well-labeled</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># test to make sure that you can train the classifier and use it to classify a new example</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div><div class=\"collapsed-lines\"></div></div><p><span style=\"color: red;\"><strong>Expected Behavior</strong> </span></p>\n<p><strong>Naive Bayes</strong>:<br>\nNaive Bayes relies on word counts or feature frequencies to compute probabilities. Since it does not involve random initialization, it is a deterministic algorithm: meaning it will always produce identical results given the same data and preprocessing steps. So, if your Naive Bayes graphs are identical across runs, this is expected and completely fine!</p>\n<p><span style=\"color: red;\"><strong>Note on Training Data Increments</strong> </span></p>\n<p>When varying the amount of training data, choose increments that are meaningful and reasonable, you should be able to observe clear trends without making the experiment unnecessarily long. You may increment the training data percentage by <strong>5%</strong>, <strong>10%</strong> or <strong>20%</strong>.</p>\n<p><strong>Make sure that one of your experiments includes 10% of the training data, as you will need this result to answer a question in Task 5.</strong></p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># Using the provided dev set, evaluate your model with precision, recall, and f1 score as well as accuracy</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># You may use nltk's implemented `precision`, `recall`, `f_measure`, and `accuracy` functions</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># (make sure to look at the documentation for these functions!)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># you will be creating a similar graph for logistic regression and neural nets, so make sure</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># you use functions wisely so that you do not have excessive repeated code</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># write any helper functions you need in sentiment_utils.py (functions that you'll use in your other notebooks as well)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># create a graph of your classifier's performance on the dev set as a function of the amount of training data</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># the x-axis should be the amount of training data (as a percentage of the total training data)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># </span><span style=\"--shiki-light:#A626A4;--shiki-light-font-style:italic;--shiki-dark:#C678DD;--shiki-dark-font-style:italic\">NOTE</span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"> : make sure one of your experiments uses 10% of the data, you will need this to answer the first question in task 5</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># the y-axis should be the performance of the classifier on the dev set</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># the graph should have 4 lines, one for each of precision, recall, f1, and accuracy</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># the graph should have a legend, title, and axis labels</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>Test your model using both a <strong>binarized</strong> (bag of words representation where we put 1 [true] if the word is there and 0 [false] otherwise) and a <strong>multinomial</strong> (bag of words representation where we put the count of the word if the word occurs, and 0 otherwise). Use whichever one gives you a better final f1 score on the dev set to produce your graphs.</p>\n<ul>\n<li>f1 score binarized: <strong>YOUR ANSWER HERE</strong></li>\n<li>f1 score multinomial: <strong>YOUR ANSWER HERE</strong></li>\n</ul>\n<h2>Task 3: Train a Logistic Regression Model (20 points)</h2>\n<p>Using <code>sklearn</code>'s implementation of <code>LogisticRegression</code>, conduct a similar analysis on the performance of a Logistic Regression classifier on the provided data set.</p>\n<p>Using the <code>time</code> module, you'll compare and contrast how long it takes your <strong>home-grown BoW vectorizing function vs. <code>sklearn</code>'s <code>CountVectorizer</code>.</strong></p>\n<p>You will be implementing <strong>multinomial</strong> (counts of word) BoW representations of your data</p>\n<p>Logistic regression is used for binary classification, but can be extended for multi-class classification</p>\n<p>Read more about logistic regression here - <a href=\"https://www.analyticsvidhya.com/blog/2021/08/conceptual-understanding-of-logistic-regression-for-data-science-beginners/\" target=\"_blank\" rel=\"noopener noreferrer\">https://www.analyticsvidhya.com/blog/2021/08/conceptual-understanding-of-logistic-regression-for-data-science-beginners/</a>.</p>\n<p>Recall from task 2 what binarized and multinomial mean here: a <strong>binarized</strong> bag of words representation is one where we put 1 [true] if the word is there and 0 [false] otherwise, and a <strong>multinomial</strong> bag of words representation is one where we put the count of the word if the word occurs, and 0 otherwise.</p>\n<p><strong>10 points in Task 5 will be allocated for all 9 graphs (including the one generated here in Task 3 for Logistic Regression) being:</strong></p>\n<ul>\n<li>Legible</li>\n<li>Present below</li>\n<li>Properly labeled\n<ul>\n<li>x and y axes labeled</li>\n<li>Legend for accuracy measures plotted</li>\n<li>Plot Title with which model and run number the graph represents</li>\n</ul>\n</li>\n</ul>\n<div class=\"language-python line-numbers-mode has-collapsed-lines collapsed\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--vp-collapsed-lines:15;--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">from</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> sklearn.linear_model </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">import</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> LogisticRegression</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># https://scikit-learn.org/stable/modules/generated/sklearn.feature_extraction.text.CountVectorizer.html</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">from</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> sklearn.feature_extraction.text </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">import</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> CountVectorizer</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">from</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> collections </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">import</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> Counter</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">import</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> time</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">import</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> sentiment_utils </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">as</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> sutils</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># define constants for the files we are using</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">TRAIN_FILE</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> =</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> \"movie_reviews_train.txt\"</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">DEV_FILE</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> =</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> \"movie_reviews_dev.txt\"</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># load in your data and make sure you understand the format</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># Do not print out too much so as to impede readability of your notebook</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">train_tups </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> sutils.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">generate_tuples_from_file</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">TRAIN_FILE</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">dev_tups </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> sutils.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">generate_tuples_from_file</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">DEV_FILE</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># some variables you may want to use</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># BINARIZED = True</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># USE_COUNT_VECTORIZER = False</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># Write the functions needed (here or in sentiment_utils.py) to create vectorized BoW representations</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># of your data. We recommend starting with a multinomial BoW representation.</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># Each training example should be represented as a sparse vector.</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># how much time does it take to featurize the all data with your implementation?</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">start </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> time.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">time</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># YOUR CODE HERE</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">end </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> time.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">time</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"That took:\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, end </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> start, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"seconds\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># how much time does it take to featurize the all data with sklearn's CountVectorizer?</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">start </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> time.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">time</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># YOUR CODE HERE</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">end </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> time.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">time</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"That took:\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, end </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> start, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"seconds\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div><div class=\"collapsed-lines\"></div></div><ol>\n<li>How big is your vocabulary using your vectorization function(s)? <strong>YOUR ANSWER HERE</strong></li>\n<li>How big is your vocabulary using the <code>CountVectorizer</code>? <strong>YOUR ANSWER HERE</strong></li>\n</ol>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">#  write any code you need analyze the relative sparsity of your vectorized representations of the data</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># YOUR CODE HERE</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># Print out the average % of entries that are zeros in each vector in the vectorized training data</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># YOUR CODE HERE</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p><span style=\"color: red;\"><strong>Expected Behavior</strong> </span></p>\n<p><strong>Logistic Regression</strong>:<br>\nLogistic Regression can behave either deterministically or non-deterministically depending on whether random initialization is involved. On small datasets, results often converge to the same optimum, producing identical graphs. However, when a random seed affects initialization, minor variation may or <strong>may not</strong> appear between runs. Either case is acceptable!</p>\n<p><span style=\"color: red;\"><strong>Note on Training Data Increments</strong> </span></p>\n<p>When varying the amount of training data, choose increments that are meaningful and reasonable, you should be able to observe clear trends without making the experiment unnecessarily long. You may increment the training data percentage by <strong>5%</strong>, <strong>10%</strong> or <strong>20%</strong>.</p>\n<p><strong>Make sure that one of your experiments includes 10% of the training data, as you will need this result to answer a question in Task 5.</strong></p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># Using the provided dev set, evaluate your model with precision, recall, and f1 score as well as accuracy</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># You may use nltk's implemented `precision`, `recall`, `f_measure`, and `accuracy` functions</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># (make sure to look at the documentation for these functions!)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># you will be creating a similar graph for logistic regression and neural nets, so make sure</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># you use functions wisely so that you do not have excessive repeated code</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># write any helper functions you need in sentiment_utils.py (functions that you'll use in your other notebooks as well)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># create a graph of your classifier's performance on the dev set as a function of the amount of training data</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># the x-axis should be the amount of training data (as a percentage of the total training data)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># </span><span style=\"--shiki-light:#A626A4;--shiki-light-font-style:italic;--shiki-dark:#C678DD;--shiki-dark-font-style:italic\">NOTE</span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"> : make sure one of your experiments uses 10% of the data, you will need this to answer the first question in task 5</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># the y-axis should be the performance of the classifier on the dev set</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># the graph should have 4 lines, one for each of precision, recall, f1, and accuracy</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># the graph should have a legend, title, and axis labels</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>Test the following 4 combinations to determine which has the best final f1 score for your Logistic Regression model:</p>\n<ul>\n<li>your vectorized features, multinomial: <strong>enter your final f1 score here</strong></li>\n<li>CountVectorizer features, multinomial: <strong>enter your final f1 score here</strong></li>\n<li>your vectorized features, binarized: <strong>enter your final f1 score here</strong></li>\n<li>CountVectorizer features, binarized: <strong>enter your final f1 score here</strong></li>\n</ul>\n<p>Produce your graph(s) for the combination with the best final f1 score.</p>\n<h2>Task 4: Neural Networks (20 points)</h2>\n<p>Next, we'll train a feedforward neural net to work with this data. You'll train one neural net which takes the same input as your Logistic Regression model - a sparse vector representing documents as bags of words.</p>\n<p>Take a look at these videos to understand forward and backward propagation in neural networks -</p>\n<ul>\n<li><a href=\"https://www.youtube.com/watch?v=HHbjpDHcJVw\" target=\"_blank\" rel=\"noopener noreferrer\">https://www.youtube.com/watch?v=HHbjpDHcJVw</a></li>\n<li><a href=\"https://youtu.be/-Lavz_I4l2U?si=zi20DB3qKPLMEPt1\" target=\"_blank\" rel=\"noopener noreferrer\">https://youtu.be/-Lavz_I4l2U?si=zi20DB3qKPLMEPt1</a></li>\n</ul>\n<p>You will be implementing <strong>binarized</strong> (presence/absence of word) and <strong>multinomial</strong> (counts of word) BoW representations of your data</p>\n<p><strong>10 points in Task 5 will be allocated for all 9 graphs (including the one generated here in Task 4 for Neural Networks) being:</strong></p>\n<ul>\n<li>Legible</li>\n<li>Present below</li>\n<li>Properly labeled\n<ul>\n<li>x and y axes labeled</li>\n<li>Legend for accuracy measures plotted</li>\n<li>Plot Title with which model and run number the graph represents</li>\n</ul>\n</li>\n</ul>\n<div class=\"language-python line-numbers-mode has-collapsed-lines collapsed\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--vp-collapsed-lines:15;--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">import</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> sentiment_utils </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">as</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> sutils</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">import</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> numpy </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">as</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> np</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">from</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> keras.models </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">import</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> Sequential</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">from</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> keras.layers </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">import</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> Dense</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># you can experiment with having some Dropout layers if you'd like to</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># this is not required</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">from</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> keras.layers </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">import</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> Dropout</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># if you want to use this again</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">from</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> sklearn.feature_extraction.text </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">import</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> CountVectorizer</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># define constants for the files we are using</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">TRAIN_FILE</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> =</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> \"movie_reviews_train.txt\"</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">DEV_FILE</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> =</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> \"movie_reviews_dev.txt\"</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># load in your data and make sure you understand the format</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># Do not print out too much so as to impede readability of your notebook</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">train_tups </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> sutils.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">generate_tuples_from_file</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">TRAIN_FILE</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">dev_tups </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> sutils.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">generate_tuples_from_file</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">DEV_FILE</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># you may use either your sparse vectors or sklearn's CountVectorizer's sparse vectors</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># you will experiment with multinomial and binarized representations later</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># Create a feedforward neural network model</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># that takes a sparse BoW representation of the data as input</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># and makes a binary classification of positive/negative sentiment as output</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># you may use any number of hidden layers &gt;= 1 and any number of units in each hidden layer (we recommend between 50-200)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># you may use any activation function on the hidden layers </span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># you should use a sigmoid activation function on the output layer</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># you should use binary cross-entropy as your loss function</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># sgd is an appropriate optimizer for this task</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># you should report accuracy as your metric</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># you may add Dropout layers if you'd like to</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># create/compile your model in this cell</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">model </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> Sequential</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># put in an output layer</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">model.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">summary</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># call compile here</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div><div class=\"collapsed-lines\"></div></div><p>How many trainable parameters does your model have? <strong>YOUR ANSWER HERE</strong></p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># train your model</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># Failed to find data adapter that can handle input: &lt;class 'numpy.ndarray'&gt;, (&lt;class 'list'&gt; containing values of types {\"&lt;class 'int'&gt;\"})</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># indicates you should change a list into a numpy array</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># make a prediction on the dev set</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># then make a classification decision based on that prediction</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># use the model.evaluate function to report the loss and accuracy on the dev set</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p><span style=\"color: red;\"><strong>Expected Behavior</strong> </span></p>\n<p><strong>Neural Networks</strong>:<br>\nNeural networks initialize their weights randomly and learn through iterative stochastic optimization, which introduces non-determinism by design. Even with the same data and parameters, different runs may lead to slightly different learned weights and therefore different graphs. In this case, variation between your three runs is expected and desired, it shows how the model’s training process can vary due to randomness.</p>\n<p><span style=\"color: red;\"><strong>Note on Training Data Increments</strong> </span></p>\n<p>When varying the amount of training data, choose increments that are meaningful and reasonable, you should be able to observe clear trends without making the experiment unnecessarily long. You may increment the training data percentage by <strong>5%</strong>, <strong>10%</strong> or <strong>20%</strong>.</p>\n<p><strong>Make sure that one of your experiments includes 10% of the training data, as you will need this result to answer a question in Task 5.</strong></p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># create the same graph as with NB and LR, with your neural network model instead!</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># make sure to re-create your model each time you train it — you don't want to start with</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># an already trained network!</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># you should experiment with different numbers of epochs to see how performance varies</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># you need not create an experiment that takes &gt; 10 min to run (gradescope will run out of computing resources and give you a 0)</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>Report the f1 scores for your model with the following settings, using the same number of epochs to train in both cases:</p>\n<ul>\n<li>number of epochs used: <strong>YOUR ANSWER HERE</strong></li>\n<li>multinomial features: <strong>YOUR ANSWER HERE</strong></li>\n<li>binarized features: <strong>YOUR ANSWER HERE</strong></li>\n</ul>\n<h2>Task 5: Model Evaluation (15 points)</h2>\n<p>Save your three graph files for the <strong>best</strong> configurations that you found with your models using the <code>plt.savefig(filename)</code> command. The <code>bbox_inches</code> optional parameter will help you control how much whitespace outside of the graph is in your resulting image.</p>\n<p><span style=\"color: red;\"><strong>NOTE ABOUT THE GRAPHS:</strong> </span></p>\n<p>Run each notebook containing the <strong>best classifier</strong> three times, saving the output graphs separately each time. This should result in a total of <strong>NINE</strong> distinct graphs (three per notebook, e.g. for the three Naive Bayes model graphs you would have Naive_Bayes_run1.png, Naive_Bayes_run2.png, Naive_Bayes_run3.png, etc.). Ensure you do not overwrite previous graphs when you save the graphs as images.</p>\n<ul>\n<li>\n<p>The goal of running the notebook three times is to check if your model's performance is consistent, confirming that your results are reliable and not due to randomness.</p>\n</li>\n<li>\n<p>If all your graphs look identical, remove the random seed parameter (for logistic regression) and re-run the notebook. The absence of a seed <em>might</em> introduce variation between runs.</p>\n</li>\n<li>\n<p>Should the graphs remain identical even after removing the seed, you may proceed with submitting the three identical graphs for the model.</p>\n</li>\n<li>\n<p>Repeat this process for each of the three notebooks.</p>\n</li>\n</ul>\n<p>You will turn in all of these files.</p>\n<p><span style=\"color: red;\"><strong>Additional Clarifications</strong> </span></p>\n<ul>\n<li>\n<p><strong>Naive Bayes</strong>:<br>\nNaive Bayes relies on word counts or feature frequencies to compute probabilities. Since it does not involve random initialization, it is a deterministic algorithm: meaning it will always produce identical results given the same data and preprocessing steps. So, if your Naive Bayes graphs are identical across runs, this is expected and completely fine!</p>\n</li>\n<li>\n<p><strong>Logistic Regression</strong>:<br>\nLogistic Regression can behave either deterministically or non-deterministically depending on whether random initialization is involved. On small datasets, results often converge to the same optimum, producing identical graphs. However, when a random seed affects initialization, minor variation may or <strong>may not</strong> appear between runs. Either case is acceptable!</p>\n</li>\n<li>\n<p><strong>Neural Networks</strong>:<br>\nNeural networks initialize their weights randomly and learn through iterative stochastic optimization, which introduces non-determinism by design. Even with the same data and parameters, different runs may lead to slightly different learned weights and therefore different graphs. In this case, variation between your three runs is expected and desired, it shows how the model’s training process can vary due to randomness.</p>\n</li>\n</ul>\n<p><span style=\"color: red;\"><strong>Note on Training Data Increments</strong> </span></p>\n<p>When varying the amount of training data, choose increments that are meaningful and reasonable, you should be able to observe clear trends without making the experiment unnecessarily long. You may increment the training data percentage by <strong>5%</strong>, <strong>10%</strong> or <strong>20%</strong>.</p>\n<p><strong>Make sure that one of your experiments includes 10% of the training data, as you will need this result to answer a question in Task 5.</strong></p>\n<p><strong>10 points in this section are allocated for all 9 graphs being:</strong></p>\n<ul>\n<li>Legible</li>\n<li>Present below</li>\n<li>Properly labeled\n<ul>\n<li>x and y axes labeled</li>\n<li>Legend for accuracy measures plotted</li>\n<li>Plot Title with which model and run number the graph represents</li>\n</ul>\n</li>\n</ul>\n<div class=\"language-python line-numbers-mode has-collapsed-lines collapsed\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--vp-collapsed-lines:15;--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">## YOUR CODE</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">## Please insert filepaths to the 9 plot images you created with your code below</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">import</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> matplotlib.image </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">as</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> mpimg</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">import</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> matplotlib.pyplot </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">as</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> plt</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">import</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> numpy </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">as</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> np</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">fig, axs </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> plt.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">subplots</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">figsize</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">10</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">10</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">))</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">placeholder_paths </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> [</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    \"path/to/image1.png\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"path/to/image2.png\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"path/to/image3.png\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">## paths for the three Naive Bayes model graphs</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    \"path/to/image4.png\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"path/to/image5.png\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"path/to/image6.png\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">## paths for the three Logistic Regression model graphs</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    \"path/to/image7.png\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"path/to/image8.png\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"path/to/image9.png\"</span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"> ## paths for the three Neural Network model graphs</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> i, ax </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> enumerate</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(axs.flat):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    try</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">        img </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> mpimg.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">imread</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(placeholder_paths[i])</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">        ax.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">imshow</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(img)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    except</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#ABB2BF\"> FileNotFoundError</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">        ax.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">text</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0.5</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0.5</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">f</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"Missing Image</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">\\n</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">{</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">placeholder_paths[i]</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">}</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span></span>\n<span class=\"line\"><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">                ha</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'center'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">va</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'center'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">fontsize</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">12</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">color</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'red'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">        ax.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">set_facecolor</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'lightgray'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    ax.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">set_title</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">f</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"Image </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">{</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">i</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1}</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    ax.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">set_xticks</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">([]) </span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    ax.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">set_yticks</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">([]) </span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">plt.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">tight_layout</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">plt.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">show</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div><div class=\"collapsed-lines\"></div></div><ol>\n<li>(1 pt) When using <strong>10%</strong> of your data, which model had the highest f1 score?</li>\n<li>(1 pt) Which classifier had the most <strong>consistent</strong> performance (that is, which classifier had the least variation across all three graphs you have for it -- no need to mathematically calculate this, you can just look at the graphs)?</li>\n<li>(1 pt) For each model, what percentage of training data resulted in the highest f1 score?\n<ol>\n<li>Naive Bayes:</li>\n<li>Logistic Regression:</li>\n<li>Neural Net:</li>\n</ol>\n</li>\n<li>(2 pts) Which model, if any, appeared to overfit the training data the most? Why?</li>\n</ol>\n<h2>sentiment_utils_starter_skeletons.py</h2>\n<div class=\"language-python line-numbers-mode has-collapsed-lines collapsed\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--vp-collapsed-lines:15;--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># FIRST: RENAME THIS FILE TO sentiment_utils.py </span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># YOUR NAMES HERE:</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"\"\"</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">CS 4120</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">Homework 4</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">Fall 2025</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">Utility functions for HW 4, to be imported into the corresponding notebook(s).</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">Add any functions to this file that you think will be useful to you in multiple notebooks.</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"\"\"</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># fancy data structures</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">from</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> collections </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">import</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> defaultdict, Counter</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># for tokenizing and precision, recall, f_measure, and accuracy functions</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">import</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> nltk</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># for plotting</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">import</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> matplotlib.pyplot </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">as</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> plt</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># so that we can indicate a function in a type hint</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">from</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> typing </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">import</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> Callable</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">nltk.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">download</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'punkt'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> generate_tuples_from_file</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">training_file_path</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> str</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">) -&gt; </span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">list</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    \"\"\"</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    Generates data from file formated like:</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    tokenized text from file: [[word1, word2, ...], [word1, word2, ...], ...]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    labels: [0, 1, 0, 1, ...]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    </span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    Parameters:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">        training_file_path - str path to file to read in</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    Return:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">        a list of lists of tokens and a list of int labels</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    \"\"\"</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">    # PROVIDED</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    f </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> open</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(training_file_path, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"r\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">encoding</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"utf8\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    X </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> []</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    y </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> []</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> review </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> f:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        if</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(review.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">strip</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()) </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">==</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">            continue</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">        dataInReview </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> review.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">strip</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">().</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">split</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">\\t</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        if</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(dataInReview) </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">!=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">            continue</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        else</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">            t </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> tuple</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(dataInReview)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">            if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> (</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">not</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> t[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">] </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">==</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> '0'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">) </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">and</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> (</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">not</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> t[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">] </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">==</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> '1'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">                print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"WARNING\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">                continue</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">            X.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">append</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(nltk.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">word_tokenize</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(t[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]))</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">            y.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">append</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">int</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(t[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]))</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    f.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">close</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()  </span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> X, y</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"\"\"</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">NOTE</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">: for all of the following functions, we have provided the function signature and docstring, *that we used*, as a guide.</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">You are welcome to implement these functions as they are, change their function signatures as needed, or not use them at all.</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">Make sure that you properly update any docstrings as needed.</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"\"\"</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> get_prfa</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">dev_y</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> list</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> preds</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> list</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> verbose</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">False</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">) -&gt; </span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">tuple</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    \"\"\"</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    Calculate precision, recall, f1, and accuracy for a given set of predictions and labels.</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    Args:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">        dev_y: list of labels</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">        preds: list of predictions</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">        verbose: whether to print the metrics</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    Returns:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">        tuple of precision, recall, f1, and accuracy</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    \"\"\"</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">    #</span><span style=\"--shiki-light:#A626A4;--shiki-light-font-style:italic;--shiki-dark:#C678DD;--shiki-dark-font-style:italic\">TODO</span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">: implement this function</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    pass</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> create_training_graph</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">metrics_fun</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span><span style=\"--shiki-light:#986801;--shiki-dark:#ABB2BF\"> Callable</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> train_feats</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> list</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> dev_feats</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> list</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> kind</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> str</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> savepath</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> str</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> =</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> None</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> verbose</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> bool</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> =</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> False</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">) -&gt; </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">None</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    \"\"\"</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    Create a graph of the classifier's performance on the dev set as a function of the amount of training data.</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    Args:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">        metrics_fun: a function that takes in training data and dev data and returns a tuple of metrics</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">        train_feats: a list of training data in the format [(feats, label), ...]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">        dev_feats: a list of dev data in the format [(feats, label), ...]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">        kind: the kind of model being used (will go in the title)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">        savepath: the path to save the graph to (if None, the graph will not be saved)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">        verbose: whether to print the metrics</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    \"\"\"</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">    #</span><span style=\"--shiki-light:#A626A4;--shiki-light-font-style:italic;--shiki-dark:#C678DD;--shiki-dark-font-style:italic\">TODO</span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">: implement this function</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    pass</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> create_index</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">all_train_data_X</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> list</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">) -&gt; </span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">list</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    \"\"\"</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    Given the training data, create a list of all the words in the training data.</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    Args:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">        all_train_data_X: a list of all the training data in the format [[word1, word2, ...], ...]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    Returns:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">        vocab: a list of all the unique words in the training data</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    \"\"\"</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">    # figure out what our vocab is and what words correspond to what indices</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">    #</span><span style=\"--shiki-light:#A626A4;--shiki-light-font-style:italic;--shiki-dark:#C678DD;--shiki-dark-font-style:italic\">TODO</span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">: implement this function</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    pass</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> featurize</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">vocab</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> list</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> data_to_be_featurized_X</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> list</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> binary</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> bool</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> =</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> False</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> verbose</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> bool</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> =</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> False</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">) -&gt; </span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">list</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    \"\"\"</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    Create vectorized BoW representations of the given data.</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    Args:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">        vocab: a list of words in the vocabulary</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">        data_to_be_featurized_X: a list of data to be featurized in the format [[word1, word2, ...], ...]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">        binary: whether or not to use binary features</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">        verbose: boolean for whether or not to print out progress</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    Returns:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">        a list of sparse vector representations of the data in the format [[count1, count2, ...], ...]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    \"\"\"</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">    # using a Counter is essential to having this not take forever</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">    #</span><span style=\"--shiki-light:#A626A4;--shiki-light-font-style:italic;--shiki-dark:#C678DD;--shiki-dark-font-style:italic\">TODO</span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">: implement this function</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    pass</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div><div class=\"collapsed-lines\"></div></div><details class=\"hint-container details\"><summary>公众号：AI悦创【二维码】</summary>\n<figure><img src=\"/gzh.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n</details>\n<div class=\"hint-container info\">\n<p class=\"hint-container-title\">AI悦创·编程一对一</p>\n<p>AI悦创·推出辅导班啦，包括「Python 语言辅导班、C++ 辅导班、java 辅导班、算法/数据结构辅导班、少儿编程、pygame 游戏开发、Web、Linux」，招收学员面向国内外，国外占 80%。全部都是一对一教学：一对一辅导 + 一对一答疑 + 布置作业 + 项目实践等。当然，还有线下线上摄影课程、Photoshop、Premiere 一对一教学、QQ、微信在线，随时响应！微信：Jiabcdefh</p>\n<p>C++ 信息奥赛题解，长期更新！长期招收一对一中小学信息奥赛集训，莆田、厦门地区有机会线下上门，其他地区线上。微信：Jiabcdefh</p>\n<p>方法一：<a href=\"http://wpa.qq.com/msgrd?v=3&amp;uin=1432803776&amp;site=qq&amp;menu=yes\" target=\"_blank\" rel=\"noopener noreferrer\">QQ</a></p>\n<p>方法二：微信：Jiabcdefh</p>\n</div>\n<figure><img src=\"/zsxq.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n",
      "image": "https://github.com/AndersonHJB/BornforthisData/tree/main/bornforthis.cn/1v1/93-LiquidLeon/Homework-4-Sentiment-Analysis",
      "date_published": "2025-10-18T21:21:08.000Z",
      "date_modified": "2025-10-22T14:40:01.000Z",
      "authors": [
        {
          "name": "bornforthis"
        }
      ],
      "tags": []
    },
    {
      "title": "Lab 10：Practice exam-type questions (weeks 11 and 12)",
      "url": "https://bornforthis.cn/1v1/101-Sallymisty/Lab/11-lab10-practice-exam-type-questions-for-weeks-11-and-12.html",
      "id": "https://bornforthis.cn/1v1/101-Sallymisty/Lab/11-lab10-practice-exam-type-questions-for-weeks-11-and-12.html",
      "summary": "1. Objectives 相关信息 Recall that the final exam will be performed in the lab using the lab computers. If you have never logged into the lab computers before, you must try to do so...",
      "content_html": "<h2>1. Objectives</h2>\n<div class=\"hint-container info\">\n<p class=\"hint-container-title\">相关信息</p>\n<p>Recall that the final exam will be performed in the lab using the lab computers. If you have never logged into the lab computers before, you must try to do so successfully in advance, such as in your weekly labs. Otherwise, you may experience some important delays the day of the exam in order to be able to login into the lab computers. <strong>We will NOT consider this as a reason to extend your exam beyond the established 3 hours and 15 minutes.</strong></p>\n</div>\n<p>This lab contains some examples of the types of problems you may encounter on the final exam. The exam will in general cover all topics covered in lectures and labs, for example, to check your ability to (<em>but not limited to</em>):</p>\n<ul>\n<li>Improve the quality of certain code</li>\n<li>Propose \"good\" test cases for some function without needing to know the code</li>\n<li>Read, understand, and debug certain code</li>\n<li>Analyse time complexity</li>\n<li>Write Python code to solve certain programming problems</li>\n</ul>\n<p>Problems are presented in no particular order. Don't assume that the first is easier than the second, and so on.</p>\n<p>Tutors will be busy talking with students about the project assignment during week 11, but you can ask them during week 12 if you have any questions.</p>\n<h2>2. Improve Code Quality</h2>\n<p>Good code quality is essential for a successful development of a large program. Aspects of good code quality include: good docstrings/comments, good variable/function names, good code organisation, and code efficiency (when necessary). In the following you will exercise how to improve the quality of certain code.</p>\n<h3>Question 1</h3>\n<p>The following function splits a string into a list of substrings, where each substring consists of only letters, and returns the list. For example: <code>my_func(\"hello everONE 12 hh3\")</code> returns <code>['hello', 'everONE', 'hh']</code>.</p>\n<div class=\"language-python line-numbers-mode has-collapsed-lines collapsed\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--vp-collapsed-lines:15;--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> my_func</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">astring</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    l </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> []</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    s </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> \"\"</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> i </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> range</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(astring)):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        if</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> \"a\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> &lt;=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> astring[i] </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&lt;=</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> \"z\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># lower-case letter</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">            s </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> s </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> astring[i]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">            # do special thing with first element</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">            if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> i </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">==</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(astring)</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">               l </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> l</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">[s]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        elif</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> \"A\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> &lt;=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> astring[i] </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&lt;=</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> \"Z\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># character is a number</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">            s </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> s </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> astring[i]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">            # do special thing with first element</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">            if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> i </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">==</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(astring)</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">               l </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> l</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">[s]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        else</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">            # upper-case letter</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">            if</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(s) </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">==</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">               i </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> i</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">            else</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">               l</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">l</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">[s]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">               </span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">            s</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"\"</span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"> # set s to empty string</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> l</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div><div class=\"collapsed-lines\"></div></div><p>Describe all <strong>distinct</strong> ways in which the quality of the code above can be improved without affecting to its functional correctness.</p>\n<p>To gain marks, your suggested improvements must be specific. For example, if you think that naming should be improved, you must give at least one specific example of which names should be changed and to what; just answering \"better names\" is not enough. Do not simply write your suggested improvements as comments inside the function. Writing a new function or rewriting the function is not an acceptable answer, regardless of whether it is correct or not.</p>\n<details class=\"hint-container details\"><summary>详情</summary>\n<p>针对给定 <code>my_func(astring)</code>，在<strong>不改变功能</strong>的前提下，可改进之处（<strong>具体</strong>）：</p>\n<ol>\n<li>\n<p><strong>函数名与文档</strong></p>\n<ul>\n<li>\n<p>将 <code>my_func</code> 改为更语义化的 <code>split_alpha_runs</code>。</p>\n</li>\n<li>\n<p>添加清晰 docstring：说明参数/返回值/示例与边界（空串、全非字母、混合等）。</p>\n</li>\n</ul>\n</li>\n<li>\n<p><strong>变量命名</strong></p>\n<ul>\n<li><code>l</code> → <code>parts</code>（避免与内置 <code>list</code> 混淆，且表达含义）。</li>\n<li><code>s</code> → <code>current</code>（当前累计子串）。</li>\n<li><code>i</code> → <code>idx</code>（提升可读性）。</li>\n</ul>\n</li>\n<li>\n<p><strong>去除重复逻辑</strong></p>\n<ul>\n<li>\n<p>两段完全相同的拼接代码：</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">if</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> \"a\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> &lt;=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> astring[i] </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&lt;=</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> \"z\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: </span><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">...</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">elif</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> \"A\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> &lt;=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> astring[i] </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&lt;=</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> \"Z\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: </span><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">...</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div></li>\n</ul>\n<p>可以先用统一的<strong>字母判断</strong>，减少重复分支；例如使用 <code>str.isalpha()</code>（功能等价，且覆盖非英文字母会改变行为——若必须保持仅 A–Z/a–z，可用 <code>('a'&lt;=ch&lt;='z') or ('A'&lt;=ch&lt;='Z')</code> 封装成 <code>_is_ascii_alpha(ch)</code> 辅助函数）。</p>\n</li>\n<li>\n<p><strong>边界处理位置</strong></p>\n<ul>\n<li>目前用 <code>if i == len(astring)-1: l = l+[s]</code> 在循环内部多处收尾；更好的方式是<strong>循环结束后</strong>统一判断 <code>current</code> 非空再追加一次，减少分支与重复。</li>\n<li>移除“占位无效语句”：</li>\n</ul>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">if</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(s) </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">==</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    i </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> i</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>对逻辑无任何效果（死代码），应删除。</p>\n</li>\n<li>\n<p><strong>效率</strong></p>\n<ul>\n<li>多次使用 <code>l = l + [s]</code> 会创建新列表，建议改为 <code>parts.append(current)</code>。</li>\n<li>逐字符用 <code>s = s + astring[i]</code> 每次复制字符串，建议使用 <code>list</code> 收集字符后 <code>''.join()</code>，或保留但可接受（输入通常较短）。</li>\n</ul>\n</li>\n<li>\n<p><strong>注释准确性</strong></p>\n<p>注释与代码不符</p>\n<ul>\n<li><code># character is a number</code> 写在了大写字母分支上；</li>\n<li><code># upper-case letter</code> 出现在 <code>else</code> 分支。</li>\n</ul>\n<p>需修正注释，使注释与逻辑一致。</p>\n</li>\n<li>\n<p><strong>避免魔法数字/表达式重复</strong></p>\n<ul>\n<li><code>len(astring)</code> 多次调用，可在循环前存入 <code>n = len(astring)</code>。</li>\n</ul>\n</li>\n<li>\n<p><strong>类型与输入健壮性（可选）</strong></p>\n<ul>\n<li>可在 docstring 或开头断言/早退：<code>if not isinstance(astring, str): raise TypeError(...)</code>（若课程风格允许）。</li>\n</ul>\n</li>\n</ol>\n<blockquote>\n<p>小结：主要集中在<strong>命名、重复逻辑合并、边界统一收尾、注释改正、append 替代拼接</strong>与<strong>删除死代码</strong>。</p>\n</blockquote>\n</details>\n<h3>Question 2</h3>\n<p>In a sequence of numbers, we say that there is a <em>peak</em> at index <em>i</em> if the value at <em>i</em> is greater than both the neighbouring values, at <em>i-1</em> and at <em>i+1</em>. The first and last number in the sequence are also peaks, if they are greater than their one neighbouring value. For example, in the sequence</p>\n<p>[13.0, 9.6, 14.2, 17.5, 8.9, 9.7, 15.7, 20.4, 14.8, 13.2, 13.6, 15.6, 17.9, 24.1, 19.2]</p>\n<p>there are peaks at indices 0 (because <code>13.0 &gt; 9.6</code>), 3 (because <code>14.2 &lt; 17.5 &gt; 8.9</code>), 7 (because <code>15.7 &lt; 20.4 &gt; 14.8</code>) and 13 (because <code>17.9 &lt; 24.1 &gt; 19.2</code>).</p>\n<p>The following function takes as argument a numeric sequence and returns average distance between all the peaks in it. The distance between two peaks at indices <code>i</code> and <code>j</code> is defined as <code>abs(i-j)</code>.</p>\n<div class=\"language-python line-numbers-mode has-collapsed-lines collapsed\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--vp-collapsed-lines:15;--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> my_func</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">s</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    x </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> [] </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># sets x to empty list</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> i </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> range</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(s)):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> i </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> &gt;=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 0</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> and</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> i </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> &lt;</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(s):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">            if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> s[i] </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&gt;</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> s[i</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">] </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">and</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> s[i] </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&gt;</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> s[i</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">                x.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">append</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(i)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        elif</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> i </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> &gt;=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 0</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> and</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> i </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> &gt;=</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(s):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">            # i is the first element</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">            if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> s[i] </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&gt;</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> s[i</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">                x.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">append</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(i)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        elif</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> i </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> &lt;</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 0</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> and</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> i </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> &lt;</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(s):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">            # i is the last element</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">            if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> s[i] </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&gt;</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> s[i</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">                x.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">append</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(i)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    if</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(x) </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&lt;</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        return</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 0.0</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    else</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">        count </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 0</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">        t </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 0</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> i </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> range</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(x)):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">            for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> j </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> range</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(i </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(x)):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">                count </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 1</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">                t </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+=</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> abs</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(x[i] </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> x[j])</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> t </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">/</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> count</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div><div class=\"collapsed-lines\"></div></div><p>Describe all <strong>distinct</strong> ways in which the quality of the code above can be improved without affecting to its functional correctness.</p>\n<p>To gain marks, your suggested improvements must be specific. For example, if you think that naming should be improved, you must give at least one specific example of which names should be changed and to what; just answering \"better names\" is not enough. Do not simply write your suggested improvements as comments inside the function. Writing a new function or rewriting the function is not an acceptable answer, regardless of whether it is correct or not.</p>\n<details class=\"hint-container details\"><summary>详情</summary>\n<p>针对“峰值平均距离”函数：</p>\n<ol>\n<li>\n<p><strong>函数与变量命名</strong></p>\n<ul>\n<li><code>my_func</code> → <code>average_peak_distance</code></li>\n<li><code>s</code> → <code>seq</code>；<code>x</code> → <code>peak_indices</code>；<code>t</code> → <code>total_distance</code>；<code>count</code> → <code>pair_count</code>。</li>\n</ul>\n</li>\n<li>\n<p><strong>注释与分支语义修正</strong></p>\n<ul>\n<li>分支注释颠倒：</li>\n</ul>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">elif</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> i </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> &gt;=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 0</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> and</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> i </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> &gt;=</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(s):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">    # i is the first element  # ❌ 实为“最后一个元素”</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">elif</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> i </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> &lt;</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 0</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> and</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> i </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> &lt;</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(s):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">    # i is the last element   # ❌ 实为“第一个元素”</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>需把注释改正，避免误导。</p>\n</li>\n<li>\n<p><strong>边界判断更清晰</strong></p>\n<ul>\n<li>使用结构：\n<ul>\n<li>若 <code>i == 0</code>：检查 <code>s[0] &gt; s[1]</code>（长度&gt;1时）；</li>\n<li>若 <code>i == n-1</code>：检查 <code>s[n-1] &gt; s[n-2]</code>；</li>\n<li>否则：常规两侧比较。<br>\n这样避免复杂复合条件并减少索引越界风险。</li>\n</ul>\n</li>\n</ul>\n</li>\n<li>\n<p><strong>空与长度为 1 的输入</strong>：现在若 <code>len(s)==1</code>，循环中不会添加峰值，返回 0.0；与定义（“首尾也算峰，如果比唯一邻居大”）一致，但<strong>单元素</strong>按常见约定通常也可视为峰（因无邻居）。这里至少应<strong>在 docstring 中明确</strong>约束或在代码顶端<strong>特判</strong>：长度 1 → 峰数 &lt;2 则返回 0.0（与现实现一致）。</p>\n</li>\n<li>\n<p><strong>复杂度与实现</strong>：寻找峰值 O(n)；平均距离双重循环 O(p²)（p 为峰个数）。如需要提升效率，可仅统计<strong>两两距离和</strong>的等价线性公式（对有序下标 <code>x[0..p-1]</code>，<br>\n<code>sum_{i&lt;j} (x[j]-x[i]) = Σ_j (2j-p+1)*x[j]</code>），把 O(p²) 降为 O(p)。若不改变功能，此为<strong>可选优化建议</strong>。</p>\n</li>\n<li>\n<p><strong>一致的返回类型与浮点除法</strong>：当前 <code>t / count</code> 在 Python3 为浮点除法，返回 <code>float</code>，符合题意。为明确可写 <code>return float(total_distance) / pair_count</code>。</p>\n</li>\n<li>\n<p><strong>避免重复 <code>len(s)</code> 计算</strong>：赋值 <code>n = len(s)</code>，统一使用。</p>\n</li>\n<li>\n<p><strong>Docstring 完善</strong>：指明：输入要求（数值序列）、返回定义（无或一个峰 → 返回 0.0）、复杂度与示例。</p>\n</li>\n</ol>\n</details>\n<h2>3. Testing</h2>\n<p>Testing is an important skill. Software testers usually need to think about designing a small enough set of good test cases that still cover a large spectrum of parameters to ensure that the code runs correctly for most or all parameters. In the following you will exercise how to carefully design good test cases for some function without even knowing the code of the function.</p>\n<h3>Question 1</h3>\n<p>We want to write tests for a function with signature and docstring defined as follows:</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> smallest_non_negative</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">number_list</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    \"\"\"</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    Argument is a list of numeric values (integer or float).</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    Returns the smallest non-negative value in the list,</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    and zero if there is no such value.</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    \"\"\"</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>Write <strong>at most</strong> <strong>4</strong> test cases for this function (every test case after the first four will be ignored). For each test case, you must write down the input (argument to the function) and the expected return value. Each test case should specify valid arguments for the function (e.g., an input list with elements of different types is not a valid argument). Your test cases should cover relevant corner cases.</p>\n<details class=\"hint-container details\"><summary>详情</summary>\n<p>最多 4 个用例，覆盖：无非负、含 0、多浮点、重复与顺序。</p>\n<ol>\n<li>输入：<code>[-5, -1, -0.1]</code> → 期望：<code>0</code>（无非负）</li>\n<li>输入：<code>[0, 3, 2, 0.5]</code> → 期望：<code>0</code>（最小非负为 0）</li>\n<li>输入：<code>[1.2, 3.4, 0.1, 0.1]</code> → 期望：<code>0.1</code>（浮点&amp;重复）</li>\n<li>输入：<code>[5, 2, 3, 4]</code> → 期望：<code>2</code>（最小正数）</li>\n</ol>\n</details>\n<h3>Question 2</h3>\n<p>We want to write tests for a function with signature and docstring defined as follows:</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> sequence_similarity</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">s1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> s2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    \"\"\"</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    s1 and s2 are two sequences of the same length.</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    Returns the number of i-th elements that are equal </span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    between two sequences, i.e., where s1[i] == s2[i]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    \"\"\"</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>Write <strong>at most</strong> <strong>4</strong> test cases for this function (every test case after the first four will be ignored). For each test case, you must write down the input (argument to the function) and the expected return value. Each test case should specify valid arguments for the function (e.g., an input list with elements of different types is not a valid argument). Your test cases should cover relevant corner cases.</p>\n<details class=\"hint-container details\"><summary>详情</summary>\n<p>覆盖：全等、全不等、空序列、含不同类型但可比较。</p>\n<ol>\n<li>输入：<code>([1,2,3], [1,2,3])</code> → 期望：<code>3</code></li>\n<li>输入：<code>([1,2,3], [3,2,1])</code> → 期望：<code>1</code>（仅中间相等）</li>\n<li>输入：<code>([], [])</code> → 期望：<code>0</code></li>\n<li>输入：<code>(('a','b','c'), ('a','x','c'))</code> → 期望：<code>2</code></li>\n</ol>\n</details>\n<h3>Question 3</h3>\n<p>For a sequence of strings and an integer k, we want to find a substring of length k that is common to the most strings and must occur at least twice. For example, for the sequence <code>['honestness', 'honestly', 'dishonest', 'fairly']</code> and <code>k=6</code>, the answer is <code>'honest'</code> because it appears in 3 strings and no substring of length 6 appears in all 4 strings. For the same list of strings and <code>k=5</code>, the answer is <code>'hones'</code> or <code>onest</code>. When there is more than one solution like this, it is OK to report one of them. For <code>k=7</code>, the answer is <code>''</code> (empty string) because there is no substring of length 7 that occurs in 2 or more strings.</p>\n<p>Here is a function with its docstring which aims to implement this:</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> most_common_substr</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">seq_strings</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> k</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    \"\"\"</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    seq_strings is a sequence of strings with at least 2 elements.</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    k is a positive integer.</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    Returns a string of length exactly k which appears as a </span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    sub-string in the most elements of seq_strings. </span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    If no substrings of length k exist in 2 or more elements </span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    of seq_strings, the empty string is returned.</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    If two or more substrings of length k appear in the same number </span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    of elements of seq_strings only one will be returned.    </span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    \"\"\"</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>Write <strong>at most</strong> 5 test cases for this function (every test case after the first four will be ignored). For each test case, you must write down the input (argument to the function) and the expected return value. Each test case should specify valid arguments for the function (e.g., an input list with elements of different types is not a valid argument). Your test cases should cover relevant corner cases.</p>\n<details class=\"hint-container details\"><summary>详情</summary>\n<p>题干已有示例，接着补全覆盖：无解、唯一解、并列解、大小写/重复、边界 k=1。</p>\n<ol>\n<li>输入：<code>(['honestness','honestly','dishonest','fairly'], 7)</code> → 期望：<code>''</code>（无长度 7 的公共子串≥2 次）</li>\n<li>输入：<code>(['ababa','babab','aba'], 3)</code> → 期望：<code>'aba'</code> 或 <code>'bab'</code>（并列解，返回其一）</li>\n<li>输入：<code>(['xxx','xx','xxxx'], 2)</code> → 期望：<code>'xx'</code>（出现于 3 个字符串）</li>\n<li>输入：<code>(['a','b','c','a'], 1)</code> → 期望：<code>'a'</code>（最常见字符，出现 2 次）</li>\n</ol>\n<blockquote>\n<p>说明：若判题需要<strong>唯一答案</strong>，应在说明中接受“任一并列最优”。</p>\n</blockquote>\n</details>\n<h2>4. Debugging</h2>\n<p>Debugging is also an important skill. In a complex software, developers may find themselves spend more time to find mistakes in their codes than writing them in the first place. In the following you will exercise how to find errors and bugs in prewritten codes.</p>\n<h3>Question 1</h3>\n<p>We call a dictionary invertible if every key in it maps to a unique value, or in other words, for every value appearing in the dictionary, there is only one key that maps to that value. Below are three attempts to define a function <code>is_invertible(adict)</code>, which takes as argument a dictionary and returns <code>True</code> if the dictionary is invertible, and <code>False</code> otherwise.</p>\n<p>For example, <code>is_invertible({ 'a' : 'b', 'b' : 'e', 'c' : 'f' })</code> should return <code>True</code>, but <code>is_invertible({ 'a' : 'b', 'b' : 'e', 'c' : 'b' })</code> should return <code>False</code>, because keys <code>'a'</code> and <code>'c'</code> both map to the same value, <code>'b'</code>.</p>\n<p>For each of the functions below, determine whether it is correct or not. Correct mean that the function runs without error and returns the right answer for any dictionary. If a function is not correct, explain precisely what is wrong with it.</p>\n<p><strong>(a)</strong></p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> is_invertible</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">adict</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    return</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> sorted</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(adict.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">keys</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()) </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">==</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> sorted</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(adict.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">values</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">())</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p><strong>(b)</strong></p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> is_invertible</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">adict</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    d </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {}</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> value </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> adict.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">values</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">():</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> value </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> d:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">            return</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> False</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        else</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">            d[value] </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 1</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    return</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> True</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p><strong>(c)</strong></p>\n<p>Note: This implementation of the function uses another function, <code>make_inv_dict</code>, which is also defined below.</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> is_invertible</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">adict</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    inv_dict </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> make_inv_dict</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(adict)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> adict </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">==</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> inv_dict</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> make_inv_dict</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">adict</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    if</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(adict) </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&gt;</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">        key, val </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> adict.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">popitem</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">        adict </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> make_inv_dict</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(adict)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> val </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">not</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> in</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> adict.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">values</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">():</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">            adict[key] </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> val</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> adict</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    else</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {}</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><details class=\"hint-container details\"><summary>详情</summary>\n<p><strong>(a)</strong> <code>return sorted(adict.keys()) == sorted(adict.values())</code></p>\n<p><strong>错误</strong>：把“键集合排序”与“值集合排序”比较。可逆要求“值不重复”（值集合大小等于键集合大小），而不是“键的多重集与值的多重集相同”。反例：<code>{'a':1,'b':2}</code>可逆，但键排序 <code>['a','b']</code> 与值排序 <code>[1,2]</code> 不相等。</p>\n<p><strong>(b)</strong> 正确。逻辑：遍历所有值，若某值已出现过则重复→不可逆；否则记录。返回 True。当值是<strong>可哈希</strong>时成立（题设默认字典键/值常用可哈希类型）。时间 O(n)、空间 O(n)。</p>\n<p><strong>(c)</strong> 错误，且有两点：</p>\n<ol>\n<li><code>make_inv_dict</code> 使用 <code>popitem()</code> <strong>就地修改了入参</strong> <code>adict</code>，破坏原字典；调用后 <code>adict</code> 被清空或改变。</li>\n<li><code>is_invertible</code> 返回 <code>adict == inv_dict</code> 比较<strong>原字典</strong>与**“去重值”字典<strong>是否相等，而可逆性的充分必要条件并非两者相等（它试图构造“值不重复”的子字典，但比较对象错误）。此外，若存在重复值，<code>inv_dict</code> 会</strong>丢掉**其中一个键（因为 <code>if val not in adict.values(): adict[key] = val</code> 这段逻辑也混淆了“键/值空间”——这里 <code>adict</code> 在递归后成了“剩余键到值”的映射，<code>val not in adict.values()</code> 不能保证唯一映射构造的正确性）。</li>\n</ol>\n</details>\n<h3>Question 2</h3>\n<p>Here is a function that takes as argument a sequence:</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> funX</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">a_list</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    index </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 0</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    while</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> index </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&lt;</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">sorted</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(a_list)) </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">//</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">        index </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> index </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 1</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    return</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> sorted</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(a_list)[index]</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p><strong>(a)</strong> Explain what <code>funX</code> does <em>in general</em>. A good answer is one that describes the purpose of the function - something you would write in its docstring.</p>\n<p><strong>(b)</strong> <code>funX</code> is unnecessarily inefficient. Rewrite the function so that it does the same thing, but as efficiently as possible.</p>\n<details class=\"hint-container details\"><summary>详情</summary>\n<p><strong>(a) 作用</strong><br>\n返回<strong>已排序后</strong>序列中索引为 <code>len(s)//2</code> 的元素（上中位数；若长度偶数，取右侧那个；若奇数，取中位数）。</p>\n<p><strong>(b) 更高效写法（去冗余排序与无意义循环）</strong></p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> funX</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">a_list</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    s </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> sorted</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(a_list)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> s[</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(s)</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">//</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><blockquote>\n<p>原函数做了两次 <code>sorted(a_list)</code> 且用 while 做“数到一半”的自增，都是冗余。</p>\n</blockquote>\n</details>\n<h3>Question 3</h3>\n<p>Here is another function that takes a sequence as argument:</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> funY</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">x</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    i </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 0</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    while</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> i </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&lt;</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(x):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">        i </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> i </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> x[i] </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">%</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(x)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> i</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p><strong>(a)</strong> Give an example, if possible, of an argument sequence that causes <code>funY</code> to get stuck in an infinite loop, as well as an argument sequence for which the function executes without error and returns a value.</p>\n<p><strong>(b)</strong> What are the runtime errors that can occur in <code>funY</code>, assuming the argument is of type <code>list</code>? For each error, give an example of an argument list that causes the error.</p>\n<details class=\"hint-container details\"><summary>详情</summary>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> funY</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">x</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    i </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 0</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    while</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> i </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&lt;</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(x):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">        i </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> i </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> x[i] </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">%</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(x)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> i</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p><strong>(a)</strong></p>\n<ul>\n<li><strong>会死循环的示例</strong>：<code>[0]</code>（<code>len=1</code>，<code>x[0]%1==0</code>，i 始终为 0）；或 <code>[2, 1]</code>（<code>len=2</code>，起点 <code>i=0</code>，<code>x[0]%2==0</code>，停在 0）。</li>\n<li><strong>能正常返回的示例</strong>：<code>[1,1,1]</code>（依次跳 1、2、3，最后返回 3）。</li>\n</ul>\n<p><strong>(b) 可能的运行时错误</strong></p>\n<ul>\n<li><code>ZeroDivisionError</code>：空列表 <code>[]</code>，因为 <code>len(x)==0</code>，取模除以 0。</li>\n<li><code>TypeError</code>：元素非数值、不可与 <code>int</code> 取模，例如 <code>['a']</code>。</li>\n<li>（一般无 <code>IndexError</code>：因为 <code>i &lt; len(x)</code> 时才取 <code>x[i]</code>，且 <code>i</code> 的更新使用 <code>% len(x)</code>，结果在 <code>[0, len-1]</code> 之间，不会越界。但若把 <code>% len(x)</code> 移除就可能。)</li>\n</ul>\n</details>\n<h3>Question 4</h3>\n<p>A <em>strictly increasing consecutive subsequence</em> is a part of a sequence in which every element is strictly greater than the previous element. Because \"strictly increasing consecutive subsequence\" is a bit long, we will call this a <em>streak</em>. For example, in the sequence <code>(1,5,2,4,7,2)</code>, the subsequences <code>(1,5)</code> and <code>(2,4,7)</code> are streaks. (Of course, by definition, any subsequence of a streak is also a streak.) <code>(2,4,7)</code> is the longest streak among all streaks of that input sequence.</p>\n<p>Below is a function that takes as argument a sequence of numbers, and it aims to return the length of the longest streak of the input sequence:</p>\n<div class=\"language-python line-numbers-mode has-collapsed-lines collapsed\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--vp-collapsed-lines:15;--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> longest_streak</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">seq</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    i</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    counter</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    narray</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">[]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">    #base case</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    if</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(seq)</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">==</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    while</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> i </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&lt;</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(seq)</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> seq[i] </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&lt;</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> seq[i</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">            counter</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">counter</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">            i</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">i</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        else</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">            narray.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">append</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(counter)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">            counter</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">            i</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">i</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    if</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(narray)</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">==</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(counter)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    else</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">max</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(narray))</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div><div class=\"collapsed-lines\"></div></div><p>However, the function above is not correct.</p>\n<p><strong>(a)</strong> Provide an example of argument, of correct types, that makes this function return the wrong answer or that causes a runtime error. The argument must be a sequence of numbers.</p>\n<p><strong>(b)</strong> Explain the cause of the error that you have found, i.e., what is wrong with this function. Your answer must explain what is wrong with the function as given. Writing a new function is not an acceptable answer, regardless of whether it is correct or not.</p>\n<details class=\"hint-container details\"><summary>详情</summary>\n<p><strong>(a) 反例</strong></p>\n<p><code>[1, 2, 0, 1, 2, 3]</code>。</p>\n<p>正确答案应为 4（子序列 <code>0,1,2,3</code>），而给定函数返回 2 或 3（取决于数据），因为<strong>最后一段递增 streak 未被加入 <code>narray</code></strong>。</p>\n<p><strong>(b) 原因说明</strong></p>\n<p>循环在遇到“非递增”时把当前 <code>counter</code> 追加到 <code>narray</code>，但<strong>当序列以递增结束</strong>时，<strong>最后一个递增 streak 没有被 append</strong>。函数结束后若 <code>narray</code> 非空，则直接取 <code>max(narray)</code>，从而忽略了可能<strong>更长</strong>的末尾 streak。应在循环结束后再做一次 <code>narray.append(counter)</code> 或单独比较末尾 <code>counter</code>。</p>\n</details>\n<h2>5. Time Complexity</h2>\n<h3>Question 1</h3>\n<p>Simplify the following big O expressions as much as possible:</p>\n<ul>\n<li><span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mi>n</mi><mo>+</mo><mn>10</mn><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(n + 10)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">n</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord\">10</span><span class=\"mclose\">)</span></span></span></span></li>\n<li><span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mn>100</mn><mo>×</mo><mi>n</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(100 \\times n)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord\">100</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">×</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">n</span><span class=\"mclose\">)</span></span></span></span></li>\n<li><span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mn>25</mn><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(25)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord\">25</span><span class=\"mclose\">)</span></span></span></span></li>\n<li><span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><msup><mi>n</mi><mn>2</mn></msup><mo>+</mo><msup><mi>n</mi><mn>3</mn></msup><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(n^2 + n^3)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1.0641em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord\"><span class=\"mord mathnormal\">n</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8141em;\"><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1.0641em;vertical-align:-0.25em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">n</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8141em;\"><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">3</span></span></span></span></span></span></span></span><span class=\"mclose\">)</span></span></span></span></li>\n<li><span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mi>n</mi><mo>+</mo><mi>n</mi><mo>+</mo><mi>n</mi><mo>+</mo><mi>n</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(n + n + n + n)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">n</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6667em;vertical-align:-0.0833em;\"></span><span class=\"mord mathnormal\">n</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6667em;vertical-align:-0.0833em;\"></span><span class=\"mord mathnormal\">n</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">n</span><span class=\"mclose\">)</span></span></span></span></li>\n<li><span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mn>1000</mn><mo>×</mo><mi>log</mi><mo>⁡</mo><mi>n</mi><mo>+</mo><mi>n</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(1000 \\times \\log n + n)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord\">1000</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">×</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8889em;vertical-align:-0.1944em;\"></span><span class=\"mop\">lo<span style=\"margin-right:0.01389em;\">g</span></span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord mathnormal\">n</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">n</span><span class=\"mclose\">)</span></span></span></span></li>\n<li><span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mn>1000</mn><mo>×</mo><mi>n</mi><mo>×</mo><mi>log</mi><mo>⁡</mo><mi>n</mi><mo>+</mo><mi>n</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(1000 \\times n \\times \\log n + n)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord\">1000</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">×</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6667em;vertical-align:-0.0833em;\"></span><span class=\"mord mathnormal\">n</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">×</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8889em;vertical-align:-0.1944em;\"></span><span class=\"mop\">lo<span style=\"margin-right:0.01389em;\">g</span></span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord mathnormal\">n</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">n</span><span class=\"mclose\">)</span></span></span></span></li>\n<li><span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><msup><mn>2</mn><mi>n</mi></msup><mo>+</mo><msup><mi>n</mi><mn>2</mn></msup><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(2^n + n^2)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord\"><span class=\"mord\">2</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.6644em;\"><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\">n</span></span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1.0641em;vertical-align:-0.25em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">n</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8141em;\"><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span></span></span></span></span><span class=\"mclose\">)</span></span></span></span></li>\n<li><span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><msup><mn>10</mn><mn>12</mn></msup><mo>+</mo><mn>5</mn><mo>+</mo><mn>3</mn><mo>+</mo><mn>1</mn><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(10^{12} + 5 + 3 + 1)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1.0641em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord\">1</span><span class=\"mord\"><span class=\"mord\">0</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8141em;\"><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mtight\">12</span></span></span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.7278em;vertical-align:-0.0833em;\"></span><span class=\"mord\">5</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.7278em;vertical-align:-0.0833em;\"></span><span class=\"mord\">3</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord\">1</span><span class=\"mclose\">)</span></span></span></span></li>\n<li><span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mi>n</mi><mo>+</mo><msqrt><mi>n</mi></msqrt><mo>+</mo><msup><mi>n</mi><mn>2</mn></msup><mo>+</mo><mi>n</mi><mo>×</mo><mi>log</mi><mo>⁡</mo><mi>n</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(n + \\sqrt{n} + n^2 + n \\times \\log n)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">n</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1.04em;vertical-align:-0.2397em;\"></span><span class=\"mord sqrt\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8003em;\"><span class=\"svg-align\" style=\"top:-3em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"mord\" style=\"padding-left:0.833em;\"><span class=\"mord mathnormal\">n</span></span></span><span style=\"top:-2.7603em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"hide-tail\" style=\"min-width:0.853em;height:1.08em;\"><svg xmlns=\"http://www.w3.org/2000/svg\" width=\"400em\" height=\"1.08em\" viewBox=\"0 0 400000 1080\" preserveAspectRatio=\"xMinYMin slice\"><path d=\"M95,702\nc-2.7,0,-7.17,-2.7,-13.5,-8c-5.8,-5.3,-9.5,-10,-9.5,-14\nc0,-2,0.3,-3.3,1,-4c1.3,-2.7,23.83,-20.7,67.5,-54\nc44.2,-33.3,65.8,-50.3,66.5,-51c1.3,-1.3,3,-2,5,-2c4.7,0,8.7,3.3,12,10\ns173,378,173,378c0.7,0,35.3,-71,104,-213c68.7,-142,137.5,-285,206.5,-429\nc69,-144,104.5,-217.7,106.5,-221\nl0 -0\nc5.3,-9.3,12,-14,20,-14\nH400000v40H845.2724\ns-225.272,467,-225.272,467s-235,486,-235,486c-2.7,4.7,-9,7,-19,7\nc-6,0,-10,-1,-12,-3s-194,-422,-194,-422s-65,47,-65,47z\nM834 80h400000v40h-400000z\"></path></svg></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.2397em;\"><span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8974em;vertical-align:-0.0833em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">n</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8141em;\"><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6667em;vertical-align:-0.0833em;\"></span><span class=\"mord mathnormal\">n</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">×</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mop\">lo<span style=\"margin-right:0.01389em;\">g</span></span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord mathnormal\">n</span><span class=\"mclose\">)</span></span></span></span></li>\n</ul>\n<details class=\"hint-container details\"><summary>详情</summary>\n<ul>\n<li><span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mi>n</mi><mo>+</mo><mn>10</mn><mo stretchy=\"false\">)</mo><mo>=</mo><mi>O</mi><mo stretchy=\"false\">(</mo><mi>n</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(n + 10) = O(n)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">n</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord\">10</span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">n</span><span class=\"mclose\">)</span></span></span></span></li>\n<li><span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mn>100</mn><mo>×</mo><mi>n</mi><mo stretchy=\"false\">)</mo><mo>=</mo><mi>O</mi><mo stretchy=\"false\">(</mo><mi>n</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(100 \\times n) = O(n)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord\">100</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">×</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">n</span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">n</span><span class=\"mclose\">)</span></span></span></span></li>\n<li><span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mn>25</mn><mo stretchy=\"false\">)</mo><mo>=</mo><mi>O</mi><mo stretchy=\"false\">(</mo><mn>1</mn><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(25) = O(1)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord\">25</span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord\">1</span><span class=\"mclose\">)</span></span></span></span></li>\n<li><span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><msup><mi>n</mi><mn>2</mn></msup><mo>+</mo><msup><mi>n</mi><mn>3</mn></msup><mo stretchy=\"false\">)</mo><mo>=</mo><mi>O</mi><mo stretchy=\"false\">(</mo><msup><mi>n</mi><mn>3</mn></msup><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(n^2 + n^3) = O(n^3)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1.0641em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord\"><span class=\"mord mathnormal\">n</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8141em;\"><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1.0641em;vertical-align:-0.25em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">n</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8141em;\"><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">3</span></span></span></span></span></span></span></span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1.0641em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord\"><span class=\"mord mathnormal\">n</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8141em;\"><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">3</span></span></span></span></span></span></span></span><span class=\"mclose\">)</span></span></span></span></li>\n<li><span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mi>n</mi><mo>+</mo><mi>n</mi><mo>+</mo><mi>n</mi><mo>+</mo><mi>n</mi><mo stretchy=\"false\">)</mo><mo>=</mo><mi>O</mi><mo stretchy=\"false\">(</mo><mi>n</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(n + n + n + n) = O(n)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">n</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6667em;vertical-align:-0.0833em;\"></span><span class=\"mord mathnormal\">n</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6667em;vertical-align:-0.0833em;\"></span><span class=\"mord mathnormal\">n</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">n</span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">n</span><span class=\"mclose\">)</span></span></span></span></li>\n<li><span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mn>1000</mn><mo>×</mo><mi>log</mi><mo>⁡</mo><mi>n</mi><mo>+</mo><mi>n</mi><mo stretchy=\"false\">)</mo><mo>=</mo><mi>O</mi><mo stretchy=\"false\">(</mo><mi>n</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(1000 \\times \\log n + n) = O(n)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord\">1000</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">×</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8889em;vertical-align:-0.1944em;\"></span><span class=\"mop\">lo<span style=\"margin-right:0.01389em;\">g</span></span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord mathnormal\">n</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">n</span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">n</span><span class=\"mclose\">)</span></span></span></span></li>\n<li><span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mn>1000</mn><mo>×</mo><mi>n</mi><mo>×</mo><mi>log</mi><mo>⁡</mo><mi>n</mi><mo>+</mo><mi>n</mi><mo stretchy=\"false\">)</mo><mo>=</mo><mi>O</mi><mo stretchy=\"false\">(</mo><mi>n</mi><mi>log</mi><mo>⁡</mo><mi>n</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(1000 \\times n \\times \\log n + n) = O(n \\log n)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord\">1000</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">×</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6667em;vertical-align:-0.0833em;\"></span><span class=\"mord mathnormal\">n</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">×</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8889em;vertical-align:-0.1944em;\"></span><span class=\"mop\">lo<span style=\"margin-right:0.01389em;\">g</span></span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord mathnormal\">n</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">n</span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">n</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mop\">lo<span style=\"margin-right:0.01389em;\">g</span></span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord mathnormal\">n</span><span class=\"mclose\">)</span></span></span></span></li>\n<li><span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><msup><mn>2</mn><mi>n</mi></msup><mo>+</mo><msup><mi>n</mi><mn>2</mn></msup><mo stretchy=\"false\">)</mo><mo>=</mo><mi>O</mi><mo stretchy=\"false\">(</mo><msup><mn>2</mn><mi>n</mi></msup><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(2^n + n^2) = O(2^n)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord\"><span class=\"mord\">2</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.6644em;\"><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\">n</span></span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1.0641em;vertical-align:-0.25em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">n</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8141em;\"><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span></span></span></span></span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord\"><span class=\"mord\">2</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.6644em;\"><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\">n</span></span></span></span></span></span></span></span><span class=\"mclose\">)</span></span></span></span></li>\n<li><span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><msup><mn>10</mn><mn>12</mn></msup><mo>+</mo><mn>5</mn><mo>+</mo><mn>3</mn><mo>+</mo><mn>1</mn><mo stretchy=\"false\">)</mo><mo>=</mo><mi>O</mi><mo stretchy=\"false\">(</mo><mn>1</mn><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(10^{12} + 5 + 3 + 1) = O(1)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1.0641em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord\">1</span><span class=\"mord\"><span class=\"mord\">0</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8141em;\"><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mtight\">12</span></span></span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.7278em;vertical-align:-0.0833em;\"></span><span class=\"mord\">5</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.7278em;vertical-align:-0.0833em;\"></span><span class=\"mord\">3</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord\">1</span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord\">1</span><span class=\"mclose\">)</span></span></span></span></li>\n<li><span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mi>n</mi><mo>+</mo><msqrt><mi>n</mi></msqrt><mo>+</mo><msup><mi>n</mi><mn>2</mn></msup><mo>+</mo><mi>n</mi><mi>log</mi><mo>⁡</mo><mi>n</mi><mo stretchy=\"false\">)</mo><mo>=</mo><mi>O</mi><mo stretchy=\"false\">(</mo><msup><mi>n</mi><mn>2</mn></msup><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(n + \\sqrt{n} + n^2 + n \\log n) = O(n^2)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">n</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1.04em;vertical-align:-0.2397em;\"></span><span class=\"mord sqrt\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8003em;\"><span class=\"svg-align\" style=\"top:-3em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"mord\" style=\"padding-left:0.833em;\"><span class=\"mord mathnormal\">n</span></span></span><span style=\"top:-2.7603em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"hide-tail\" style=\"min-width:0.853em;height:1.08em;\"><svg xmlns=\"http://www.w3.org/2000/svg\" width=\"400em\" height=\"1.08em\" viewBox=\"0 0 400000 1080\" preserveAspectRatio=\"xMinYMin slice\"><path d=\"M95,702\nc-2.7,0,-7.17,-2.7,-13.5,-8c-5.8,-5.3,-9.5,-10,-9.5,-14\nc0,-2,0.3,-3.3,1,-4c1.3,-2.7,23.83,-20.7,67.5,-54\nc44.2,-33.3,65.8,-50.3,66.5,-51c1.3,-1.3,3,-2,5,-2c4.7,0,8.7,3.3,12,10\ns173,378,173,378c0.7,0,35.3,-71,104,-213c68.7,-142,137.5,-285,206.5,-429\nc69,-144,104.5,-217.7,106.5,-221\nl0 -0\nc5.3,-9.3,12,-14,20,-14\nH400000v40H845.2724\ns-225.272,467,-225.272,467s-235,486,-235,486c-2.7,4.7,-9,7,-19,7\nc-6,0,-10,-1,-12,-3s-194,-422,-194,-422s-65,47,-65,47z\nM834 80h400000v40h-400000z\"></path></svg></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.2397em;\"><span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8974em;vertical-align:-0.0833em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">n</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8141em;\"><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">n</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mop\">lo<span style=\"margin-right:0.01389em;\">g</span></span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord mathnormal\">n</span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1.0641em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord\"><span class=\"mord mathnormal\">n</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8141em;\"><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span></span></span></span></span><span class=\"mclose\">)</span></span></span></span></li>\n</ul>\n</details>\n<h3>Question 2</h3>\n<p>Given the following function definition statement:</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> elements_at_even_index</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">seq</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">  result</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">[]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">  for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> i </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> range</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(seq)): </span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> i</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">%</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">==</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">        result.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">append</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(seq[i])</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">  return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> seq</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>Write down the time complexity in big-O notation as a function of <em>n</em> being the number of elements in seq. <strong>Explain the reason why.</strong> Correct answers without any explanation will not receive marks.</p>\n<p>Note: complexity of the <code>len()</code> function and <code>append()</code> method is <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mn>1</mn><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(1)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord\">1</span><span class=\"mclose\">)</span></span></span></span></p>\n<details class=\"hint-container details\"><summary>详情</summary>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> elements_at_even_index</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">seq</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">  result</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">[]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">  for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> i </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> range</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(seq)): </span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> i</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">%</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">==</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">        result.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">append</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(seq[i])</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">  return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> seq</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><ul>\n<li>\n<p><strong>时间复杂度</strong>：<span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mi>n</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(n)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">n</span><span class=\"mclose\">)</span></span></span></span>。单一 <code>for</code> 从 0 到 <code>len(seq)-1</code> 一次遍历；<code>len()</code> 与 <code>append()</code> 为 <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mn>1</mn><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(1)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord\">1</span><span class=\"mclose\">)</span></span></span></span>。</p>\n<p>（另外：此函数<strong>应返回 <code>result</code></strong> 才符合语义，但这不影响复杂度结论。）</p>\n</li>\n</ul>\n</details>\n<h3>Question 3</h3>\n<p>Given the following function definition statement:</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> matmul</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">A</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">x</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    assert</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">shape</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(A))</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">==</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    assert</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">shape</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(x))</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">==</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    assert</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> A.shape[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">==</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">A.shape[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    assert</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> A.shape[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">==</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">x.shape[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    y</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">x.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">copy</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> i </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> range</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(A.shape[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">        y[i]</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0.0</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> j </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> range</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(A.shape[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">            y[i]</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">A[i,j]</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">*</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">x[j]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> y</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>Write down the time complexity in big-O notation as a function of <em>n</em> being the number of rows and columns in the 2D Numpy array <code>A</code>. <strong>Explain the reason why.</strong> Correct answers without any explanation will receive zero marks.</p>\n<details class=\"hint-container details\"><summary>详情</summary>\n<p>矩阵-向量乘（方阵 <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>n</mi><mo>×</mo><mi>n</mi></mrow><annotation encoding=\"application/x-tex\">n\\times n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6667em;vertical-align:-0.0833em;\"></span><span class=\"mord mathnormal\">n</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">×</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.4306em;\"></span><span class=\"mord mathnormal\">n</span></span></span></span>）</p>\n<ul>\n<li>外层 <code>i</code> 迭代 (n) 次，内层 <code>j</code> 迭代 (n) 次，常数操作相加乘。</li>\n<li><strong>时间复杂度</strong>：<span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><msup><mi>n</mi><mn>2</mn></msup><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(n^2)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1.0641em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord\"><span class=\"mord mathnormal\">n</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8141em;\"><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span></span></span></span></span><span class=\"mclose\">)</span></span></span></span>。</li>\n</ul>\n</details>\n<h3>Question 4</h3>\n<p>Given the following function definition statement:</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> first_or_last_is_even</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">seq</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">  assert</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(seq)</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&gt;</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">  first_is_even</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">False</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">  if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> seq[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">%</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> ==</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    first_is_even</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">True</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">  last_is_even</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">False</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">  if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> seq[</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">%</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> ==</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    last_is_even</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">True</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> </span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">  </span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">  return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> first_is_even </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">or</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> last_is_even</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>Write down the time complexity in big-O notation as a function of <em>n</em> being the number of elements in <code>seq</code>. <strong>Explain the reason why.</strong> Correct answers without any explanation will receive zero marks.</p>\n<details class=\"hint-container details\"><summary>详情</summary>\n<p><code>first_or_last_is_even</code> 只访问 <code>seq[0]</code> 与 <code>seq[-1]</code>，常数次操作。</p>\n<ul>\n<li><strong>时间复杂度</strong>：<span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mn>1</mn><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(1)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord\">1</span><span class=\"mclose\">)</span></span></span></span>。</li>\n</ul>\n</details>\n<h3>Question 5</h3>\n<p>Given the following function definition statement:</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> power</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">x</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">n</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">  assert</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> n</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&gt;=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">  if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> n</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">==</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    return</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> </span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">  else</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> (n</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">%</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">==</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> power</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(x</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">*</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">x,n</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">//</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    else</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> x</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">*</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">power</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(x</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">*</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">x,n</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">//</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>Write down the time complexity in big-O notation as a function of <em>n</em>. <strong>Explain the reason why.</strong> Correct answers without any explanation will receive zero marks.</p>\n<details class=\"hint-container details\"><summary>详情</summary>\n<p>幂的二分递归（快速幂）：</p>\n<ul>\n<li>每次把指数 <code>n</code> 变为 <code>n//2</code>，递归深度 (\\lfloor \\log_2 n \\rfloor + 1)。</li>\n<li><strong>时间复杂度</strong>：<span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mi>log</mi><mo>⁡</mo><mi>n</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(\\log n)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mop\">lo<span style=\"margin-right:0.01389em;\">g</span></span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord mathnormal\">n</span><span class=\"mclose\">)</span></span></span></span>。</li>\n</ul>\n</details>\n<h3>Question 6</h3>\n<p>Given the following function definition statement:</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> f</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">n</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    assert</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> n</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&gt;=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> n</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">==</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        return</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 0</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    elif</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> n</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">==</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        return</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 1</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    else</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: </span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> f</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(n</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">f</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(n</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>Write down the time complexity in big-O notation as a function of <em>n</em>. <strong>Explain the reason why.</strong> Correct answers without any explanation will receive zero marks.</p>\n<details class=\"hint-container details\"><summary>详情</summary>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> f</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(n</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">f</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(n</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div></div></div><p>递推：<span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>T</mi><mo stretchy=\"false\">(</mo><mi>n</mi><mo stretchy=\"false\">)</mo><mo>=</mo><mn>2</mn><mi>T</mi><mo stretchy=\"false\">(</mo><mi>n</mi><mo>−</mo><mn>1</mn><mo stretchy=\"false\">)</mo><mo>+</mo><mi>O</mi><mo stretchy=\"false\">(</mo><mn>1</mn><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">T(n)=2T(n-1)+O(1)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">T</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">n</span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord\">2</span><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">T</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">n</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">−</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord\">1</span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord\">1</span><span class=\"mclose\">)</span></span></span></span> → <strong>指数级</strong> <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>T</mi><mo stretchy=\"false\">(</mo><mi>n</mi><mo stretchy=\"false\">)</mo><mo>=</mo><mi>O</mi><mo stretchy=\"false\">(</mo><msup><mn>2</mn><mi>n</mi></msup><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">T(n)=O(2^n)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">T</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">n</span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord\"><span class=\"mord\">2</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.6644em;\"><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\">n</span></span></span></span></span></span></span></span><span class=\"mclose\">)</span></span></span></span>。</p>\n</details>\n<h3>Question 7</h3>\n<p>Given the following function definition statement:</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> sum_scan</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">l</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">   result </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> i </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> range</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(l))]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">   for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> i </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> range</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(l)):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">      for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> j </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> range</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(i</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">         result[i]</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">result[i]</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">l[j]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">   return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> result</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p><strong>(a)</strong> Write down the time complexity in big-O notation as a function of n<em>n</em> being the length of the input list <code>l</code>.</p>\n<p><strong>(b)</strong> Is there a way to re-write this function such that it has a reduced order of complexity? If yes, explain with words what would you do to achieve such an objective.</p>\n<details class=\"hint-container details\"><summary>详情</summary>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> i </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> range</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(l)):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">  for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> j </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> range</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(i</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">     ...</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><ul>\n<li>(a) 双层三角循环，操作次数 <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><msubsup><mo>∑</mo><mrow><mi>i</mi><mo>=</mo><mn>0</mn></mrow><mrow><mi>n</mi><mo>−</mo><mn>1</mn></mrow></msubsup><mo stretchy=\"false\">(</mo><mi>i</mi><mo>+</mo><mn>1</mn><mo stretchy=\"false\">)</mo><mo>=</mo><mi>n</mi><mo stretchy=\"false\">(</mo><mi>n</mi><mo>+</mo><mn>1</mn><mo stretchy=\"false\">)</mo><mi mathvariant=\"normal\">/</mi><mn>2</mn></mrow><annotation encoding=\"application/x-tex\">\\sum_{i=0}^{n-1}(i+1)=n(n+1)/2</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1.2537em;vertical-align:-0.2997em;\"></span><span class=\"mop\"><span class=\"mop op-symbol small-op\" style=\"position:relative;top:0em;\">∑</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.954em;\"><span style=\"top:-2.4003em;margin-left:0em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">i</span><span class=\"mrel mtight\">=</span><span class=\"mord mtight\">0</span></span></span></span><span style=\"top:-3.2029em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">n</span><span class=\"mbin mtight\">−</span><span class=\"mord mtight\">1</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.2997em;\"><span></span></span></span></span></span></span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">i</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord\">1</span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">n</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">n</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord\">1</span><span class=\"mclose\">)</span><span class=\"mord\">/2</span></span></span></span> → <strong>(O(n^2))</strong>。</li>\n<li>(b) 可降到 <strong><span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mi>n</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(n)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">n</span><span class=\"mclose\">)</span></span></span></span></strong>：维护一个<strong>前缀和</strong>变量 <code>running</code>，一次遍历中依次 <code>running += l[i]</code> 并写入 <code>result[i] = running</code>。</li>\n</ul>\n</details>\n<h2>6. Programming problems</h2>\n<p>For each problem there is a problem description and a scaffold file for you to write your solution into. As usual, you can click the \"Test\" button to test your code. The scaffold file also has a testing function that runs several test cases on your functions if you want to test the function on your local IDE.</p>\n<p>Remember that the set of tests provided is never complete. Your task is to write a function that solves the problem that is described for all valid arguments (i.e., all arguments that meet the restrictions given in the problem description). Passing the tests does not prove that your implementation is correct, but <em>failing any test proves that your code is wrong</em>.</p>\n<h3>6.1 Problem 1: Super Increasing</h3>\n<p>A sequence of numbers is called <em>super-increasing</em> if and only if every number in the sequence is strictly greater than the sum of all numbers preceding it in the sequence. The first element in the sequence can be any number.</p>\n<p>For example, the sequences <code>1,3,5,11,21</code> and <code>-2,1,2</code> are both super-increasing; the sequence <code>1,3,5,7,19</code> is increasing, but not super-increasing.</p>\n<p>Write a function <code>super_increasing(seq)</code> that takes as argument a sequence of numbers and returns True if the sequence is super-increasing and False if it is not.</p>\n<ul>\n<li>You can assume that the argument is a non-empty sequence of numbers.</li>\n<li>You should not assume that values in the sequence are unique or increasing.</li>\n<li>You should not make any assumption about the type of the argument other than that it is a sequence type; likewise, you should not make any assumption about the type of the numbers in the sequence, other than that they are numbers.</li>\n<li>The function must not modify the argument sequence.</li>\n<li>The function must return a truth value (a value of type <code>bool</code>).</li>\n</ul>\n<p>You should write your solution into the file <code>super_increasing.py</code>. Remember that:</p>\n<ul>\n<li>The file must contain only syntactically correct python code (and comments).</li>\n<li>Do not import any module that you do not use.</li>\n<li>You must define a function named <code>super_increasing</code> that has one parameter. You may also define additional functions if it helps you break down or solve the problem.</li>\n</ul>\n<p><strong>Testing</strong></p>\n<p>You can click the \"Test\" button to test your code. The scaffold code file also includes a testing function, <code>test_super_increasing</code>, which will run the same tests on your function and raise an error if any test fails. Passing the tests does not prove that your solution is correct. <em>Failing any test proves that your function is wrong</em>.</p>\n\n<h3>6.2 Problem 2: Interval Intersection</h3>\n<p>A closed interval of the real number line is defined by its lower and upper end points. Write a function <code>interval_intersection(lower_a, upper_a, lower_b, upper_b)</code> that returns the length of the intersection of two intervals <em>A</em> and <em>B</em>. Arguments <code>lower_a</code> and <code>upper_a</code> are the lower and upper end points of interval <em>A</em>, and <code>lower_b</code> and <code>upper_b</code> are the lower and upper end points of interval <em>B</em>. If the intervals do not intersect, the function should return 0.</p>\n<p>For example, <code>interval_intersection(0, 3, 1, 5)</code> should return <code>2</code>, because the intersection of the two intervals [<em>0,3</em>] and [<em>1,5</em>] is [<em>1,3</em>], which has a length of <em>3 - 1 = 2</em>.</p>\n<ul>\n<li>You can assume that the function's arguments are numbers, but NOT that they are integers, or positive.</li>\n<li>Your function must return a number.</li>\n</ul>\n<p>You should write your solution into the scaffold file <code>interval_intersection.py</code>. Remember that:</p>\n<ul>\n<li>The file must contain only syntactically correct python code (and comments).</li>\n<li>Do not import any module that you do not use.</li>\n<li>You must define a function named <code>interval_intersection</code> that has four parameters. You may also define additional functions if it helps you break down or solve the problem.</li>\n</ul>\n<p><strong>Testing</strong></p>\n<p>You can click the \"Test\" button to test your code. The scaffold code file also includes a testing function, <code>test_interval_intersection</code>, which will run the same tests on your function and raise an error if any test fails. Passing the tests does not prove that your solution is correct. <em>Failing any test proves that your function is wrong</em>.</p>\n\n<h3>6.3 Problem 3: Counting Dictionary</h3>\n<p>Let's say that a <em>counting dictionary</em> is a dictionary in which all values (not keys) are positive integers. (In other words, it's the kind of dictionary you get when you use a dictionary to count repetitions of keys.) Given two counting dictionaries, <code>a</code> and <code>b</code>, the <em>difference between <code>a</code> and <code>b</code></em> is another counting dictionary that contains the key-value pairs <code>(k, n)</code> where <code>n = a[k] - b[k]</code> for exactly those keys <code>k</code> such that <code>n &gt; 0</code> or <code>k</code> appears only in <code>a</code>.</p>\n<p>Write a function <code>count_dict_difference(a, b)</code> that takes as arguments two counting dictionaries and returns a new dictionary that is the difference between them.</p>\n<ul>\n<li>You can assume that both arguments are dictionaries, and the values stored in them are integers.</li>\n<li>You should make <em>no</em> assumption about the types of keys that can appear in the dictionaries.</li>\n<li>Your function <em>must not</em> modify either of the argument dictionaries.</li>\n<li>Your function should value of type <code>dict</code>.</li>\n</ul>\n<p><strong>Example:</strong></p>\n<p>For example if <code>a = {'s': 4, 'm': 1, 'p': 2, 'i': 4}</code> (that's the letter counts for the word 'mississippi') and <code>b = {'e': 1, 's': 3, 'm': 1, 'p': 1, 'i': 2, 't': 1}</code> (that's the letter counts for the word 'pessimist'), the difference of <code>a</code> and <code>b</code> is the dictionary <code>{'s' : 1, 'p' : 1, 'i' : 2}</code> (note how <code>'m'</code> is not in the difference because <code>a['m'] - b['m'] == 0</code>).</p>\n<p>You should write your solution into the scaffold file <code>count_dict_difference.py</code>. Remember that:</p>\n<ul>\n<li>The file must contain only syntactically correct python code (and comments).</li>\n<li>Do not import any module that you do not use.</li>\n<li>You must define a function named <code>count_dict_difference</code> that has two parameters. You may also define additional functions if it helps you break down or solve the problem.</li>\n</ul>\n<p><strong>Testing</strong></p>\n<p>You can click the \"Test\" button to test your code. The scaffold code file also includes a testing function, <code>test_count_dict_difference</code>, which will run the same tests on your function and raise an error if any test fails. Passing the tests does not prove that your solution is correct. <em>Failing any test proves that your function is wrong</em>.</p>\n\n<h3>6.4 Problem 4: Remove All</h3>\n<p>Write a function <code>remove_all(a_list, element)</code>, which removes <em>all</em> occurrences of <code>element</code> from <code>a_list</code>. You can assume that the first argument to the function, <code>a_list</code>, is a list. The function should not return any value (i.e., return <code>None</code>) but should modify the argument list. For example,</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: my_list </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">remove_all</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(my_list, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: my_list</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">Out [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>You should write your solution into the scaffold file <code>remove_all.py</code>. Remember that:</p>\n<ul>\n<li>The file must contain only syntactically correct python code (and comments).</li>\n<li>Do not import any module that you do not use.</li>\n<li>You must define a function named <code>remove_all</code> that has two parameters. You may also define additional functions if it helps you break down or solve the problem.</li>\n</ul>\n<p><strong>Testing</strong></p>\n<p>You can click the \"Test\" button to test your code. The scaffold code file also includes a testing function, <code>test_remove_all</code>, which will run the same tests on your function and raise an error if any test fails. Passing the tests does not prove that your solution is correct. <em>Failing any test proves that your function is wrong</em>.</p>\n\n<h3>6.5 Problem 5: Moving Average</h3>\n<p>The <em>moving average</em> of a numeric sequence is a sequence of averages of subsequences of the original sequence; the subsequences are known as <em>windows</em> (or a <em>sliding window</em>), and the length of the subsequence used is called the <em>window size</em>. More precisely, given a sequence <code>S</code>, the moving average with window size <code>w</code> is sequence <code>A</code> such that the first element in <code>A</code> is the average of <code>w</code> consecutive elements in <code>S</code> starting with the first, the second element in <code>A</code> is the average of <code>w</code> consecutive elements in <code>S</code> starting with the second, and so on until the last element in <code>A</code>, which is the average of <code>w</code> consecutive elements in <code>S</code> ending with the last.</p>\n<p><strong>Example:</strong></p>\n<p>If <code>S = (2, 0, -2, 2)</code> and <code>w = 2</code>, the moving average is <code>[1, -1, 0]</code>. <code>1</code> is the average of <code>(2, 0)</code>, <code>-1</code> is the average of <code>(0, -2)</code>, and <code>0</code> is the average of <code>(-2, 2)</code>.</p>\n<p>Write a function <code>moving_average(seq, w_size)</code> that computes and returns the moving average of <code>seq</code> with window size <code>w_size</code>.</p>\n<ul>\n<li>You should assume that the argument is a sequence of numbers (integer or floating point, or a mix of them).</li>\n<li>You should NOT make any assumption about the type of the sequence (e.g., it could be list, tuple or NumPy array).</li>\n<li>You can assume that <code>w_size</code> is an integer, at least 1, and less than or equal to the length of <code>seq</code>.</li>\n<li>Your function must return a sequence of numbers (this can be, for example, a list, a tuple or NumPy array).</li>\n</ul>\n<p>You should write your solution into the scaffold file <code>moving_average.py</code>. Remember that:</p>\n<ul>\n<li>The file must contain only syntactically correct python code (and comments).</li>\n<li>Do not import any module that you do not use.</li>\n<li>You must define a function named <code>moving_average</code> that has two parameters. You may also define additional functions if it helps you break down or solve the problem.</li>\n</ul>\n<p><strong>Testing</strong></p>\n<p>You can click the \"Test\" button to test your code. The scaffold code file also includes a testing function, <code>test_moving_average</code>, which will run the same tests on your function and raise an error if any test fails. Passing the tests does not prove that your solution is correct. <em>Failing any test proves that your function is wrong</em>.</p>\n\n<h3>6.6 Problem 6: Unnest</h3>\n<p>We say that a list that contains lists is <em>nested</em>. The result of <em>unnesting</em> (also known as \"flattening\") a nested list is a list that contains the same non-list elements as the nested list, in the same order, but in a single list.</p>\n<p>For example, <code>[1, [2], [[3], [[4], 5]]]</code> is a nested list. The unnesting of this list is <code>[1, 2, 3, 4, 5]</code>.</p>\n<p>Write a function called <code>unnest</code> that takes as argument a list, which may be nested, and returns the unnesting of the argument list.</p>\n<ul>\n<li>You should assume that the argument is a list, and that all elements in the list are either lists or some non-sequence type.</li>\n<li>Your function <em>must not</em> modify the argument list. It must return a value of type <code>list</code>.</li>\n</ul>\n<p>You should write your solution into the scaffold file <code>unnest.py</code>. Remember that:</p>\n<ul>\n<li>The file must contain only syntactically correct python code (and comments).</li>\n<li>Do not import any module that you do not use.</li>\n<li>You must define a function named <code>unnest</code> that has one parameter. You may also define additional functions if it helps you break down or solve the problem.</li>\n</ul>\n<p><strong>Testing</strong></p>\n<p>You can click the \"Test\" button to test your code. The scaffold code file also includes a testing function, <code>test_unnest</code>, which will run the same tests on your function and raise an error if any test fails. Passing the tests does not prove that your solution is correct. <em>Failing any test proves that your function is wrong</em>.</p>\n\n<details class=\"hint-container details\"><summary>公众号：AI悦创【二维码】</summary>\n<figure><img src=\"/gzh.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n</details>\n<div class=\"hint-container info\">\n<p class=\"hint-container-title\">AI悦创·编程一对一</p>\n<p>AI悦创·推出辅导班啦，包括「Python 语言辅导班、C++ 辅导班、java 辅导班、算法/数据结构辅导班、少儿编程、pygame 游戏开发、Web、Linux」，招收学员面向国内外，国外占 80%。全部都是一对一教学：一对一辅导 + 一对一答疑 + 布置作业 + 项目实践等。当然，还有线下线上摄影课程、Photoshop、Premiere 一对一教学、QQ、微信在线，随时响应！微信：Jiabcdefh</p>\n<p>C++ 信息奥赛题解，长期更新！长期招收一对一中小学信息奥赛集训，莆田、厦门地区有机会线下上门，其他地区线上。微信：Jiabcdefh</p>\n<p>方法一：<a href=\"http://wpa.qq.com/msgrd?v=3&amp;uin=1432803776&amp;site=qq&amp;menu=yes\" target=\"_blank\" rel=\"noopener noreferrer\">QQ</a></p>\n<p>方法二：微信：Jiabcdefh</p>\n</div>\n<figure><img src=\"/zsxq.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n",
      "image": "https://bornforthis.cn/gzh.jpg",
      "date_published": "2025-10-16T17:06:57.000Z",
      "date_modified": "2025-10-18T12:01:10.000Z",
      "authors": [
        {
          "name": "bornforthis"
        }
      ],
      "tags": []
    },
    {
      "title": "16-白菜酿肉",
      "url": "https://bornforthis.cn/column/cookdinner/P07-%E7%89%B9%E8%89%B2%E7%94%9C%E9%A3%9F%E5%B0%8F%E5%90%83/16-%E7%99%BD%E8%8F%9C%E9%85%BF%E8%82%89.html",
      "id": "https://bornforthis.cn/column/cookdinner/P07-%E7%89%B9%E8%89%B2%E7%94%9C%E9%A3%9F%E5%B0%8F%E5%90%83/16-%E7%99%BD%E8%8F%9C%E9%85%BF%E8%82%89.html",
      "summary": "白菜一出，百财进屋！ 年夜饭抢手菜！白菜肉卷，寓意百财聚来！简单好做，清淡有滋味！ 1. 食材 2. 步骤 提前准备好：葱姜水； 香菇泡水，切碎； 小香葱切成末；（葱末） 白菜洗干净，掰开一片一片； 瘦肉搅碎——>加入：适量的盐、一小勺白胡椒粉、半瓶盖花雕酒、一小勺生抽、一小勺蚝油、十三香——>进行抓匀，下入适量的：葱姜水，边加边打（顺着一个方向）——...",
      "content_html": "<div style=\"text-align:center\">\n<h3>白菜一出，百财进屋！</h3>\n<p><strong>年夜饭抢手菜！白菜肉卷，寓意百财聚来！简单好做，清淡有滋味！</strong></p>\n</div>\n<h2>1. 食材</h2>\n<p>| 超大白菜！ | 八瘦两肥的肉 | 盐         | 白胡椒粉 | 花雕酒     |<br>\n|</p>\n",
      "image": "https://bornforthis.cn/gzh.jpg",
      "date_published": "2025-10-12T21:30:16.000Z",
      "date_modified": "2025-10-12T14:08:06.000Z",
      "authors": [
        {
          "name": "AI悦创"
        }
      ],
      "tags": []
    },
    {
      "title": "Lab 10：Practice exam-type questions (weeks 11 and 12)",
      "url": "https://bornforthis.cn/1v1/101-Sallymisty/Lab/10-lab10-practice-exam-type-questions-weeks-11-and-12.html",
      "id": "https://bornforthis.cn/1v1/101-Sallymisty/Lab/10-lab10-practice-exam-type-questions-weeks-11-and-12.html",
      "summary": "1. Objectives 相关信息 Recall that the final exam will be performed in the lab using the lab computers. If you have never logged into the lab computers before, you must try to do so...",
      "content_html": "<h2>1. Objectives</h2>\n<div class=\"hint-container info\">\n<p class=\"hint-container-title\">相关信息</p>\n<p>Recall that the final exam will be performed in the lab using the lab computers. If you have never logged into the lab computers before, you must try to do so successfully in advance, such as in your weekly labs. Otherwise, you may experience some important delays the day of the exam in order to be able to login into the lab computers. <strong>We will NOT consider this as a reason to extend your exam beyond the established 3 hours and 15 minutes.</strong></p>\n</div>\n<p>This lab contains some examples of the types of problems you may encounter on the final exam. The exam will in general cover all topics covered in lectures and labs, for example, to check your ability to (<em>but not limited to</em>):</p>\n<ul>\n<li>Improve the quality of certain code</li>\n<li>Propose \"good\" test cases for some function without needing to know the code</li>\n<li>Read, understand, and debug certain code</li>\n<li>Analyse time complexity</li>\n<li>Write Python code to solve certain programming problems</li>\n</ul>\n<p>Problems are presented in no particular order. Don't assume that the first is easier than the second, and so on.</p>\n<p>Tutors will be busy talking with students about the project assignment during week 11, but you can ask them during week 12 if you have any questions.</p>\n<h2>2. Improve Code Quality</h2>\n<details class=\"hint-container details\"><summary>公众号：AI悦创【二维码】</summary>\n<figure><img src=\"/gzh.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n</details>\n<div class=\"hint-container info\">\n<p class=\"hint-container-title\">AI悦创·编程一对一</p>\n<p>AI悦创·推出辅导班啦，包括「Python 语言辅导班、C++ 辅导班、java 辅导班、算法/数据结构辅导班、少儿编程、pygame 游戏开发、Web、Linux」，招收学员面向国内外，国外占 80%。全部都是一对一教学：一对一辅导 + 一对一答疑 + 布置作业 + 项目实践等。当然，还有线下线上摄影课程、Photoshop、Premiere 一对一教学、QQ、微信在线，随时响应！微信：Jiabcdefh</p>\n<p>C++ 信息奥赛题解，长期更新！长期招收一对一中小学信息奥赛集训，莆田、厦门地区有机会线下上门，其他地区线上。微信：Jiabcdefh</p>\n<p>方法一：<a href=\"http://wpa.qq.com/msgrd?v=3&amp;uin=1432803776&amp;site=qq&amp;menu=yes\" target=\"_blank\" rel=\"noopener noreferrer\">QQ</a></p>\n<p>方法二：微信：Jiabcdefh</p>\n</div>\n<figure><img src=\"/zsxq.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n",
      "image": "https://bornforthis.cn/gzh.jpg",
      "date_published": "2025-10-12T18:10:51.000Z",
      "date_modified": "2025-10-12T10:44:41.000Z",
      "authors": [
        {
          "name": "bornforthis"
        }
      ],
      "tags": []
    },
    {
      "title": "Assagment1",
      "url": "https://bornforthis.cn/1v1/100-Leo/Assagment1.html",
      "id": "https://bornforthis.cn/1v1/100-Leo/Assagment1.html",
      "summary": "Introduction In this assignment, you will make use of Python programming to implement a simple game called 1023 Game. The game is inspired by both the 2048 game and the Tetris g...",
      "content_html": "<h3>Introduction</h3>\n<p>In this assignment, you will make use of Python programming to implement a simple game called 1023 Game. The game is inspired by both the <a href=\"https://en.wikipedia.org/wiki/2048_(video_game)\" target=\"_blank\" rel=\"noopener noreferrer\">2048 game</a> and the <a href=\"https://en.wikipedia.org/wiki/Tetris\" target=\"_blank\" rel=\"noopener noreferrer\">Tetris game</a>.</p>\n<h4>Piece</h4>\n<figure><figcaption>Piece</figcaption></figure>\n<p>In the 1023 Game, a piece is a connected group of 4 blocks, just like the Tetris game. There are 7 types of pieces in our game. The player can control the movement of each piece. More information about the movement in the \"Gameplay\" section.</p>\n<h4>Block</h4>\n<figure><figcaption>Block</figcaption></figure>\n<p>A block is the smallest unit in the 1023 Game. Each block has a value of 1, 3, 7, 15, ..., 1023 (each number is two times the previous number plus one: <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mn>3</mn><mo>=</mo><mn>2</mn><mo>∗</mo><mn>1</mn><mo>+</mo><mn>1</mn></mrow><annotation encoding=\"application/x-tex\">3 = 2*1 + 1</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6444em;\"></span><span class=\"mord\">3</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6444em;\"></span><span class=\"mord\">2</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">∗</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.7278em;vertical-align:-0.0833em;\"></span><span class=\"mord\">1</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6444em;\"></span><span class=\"mord\">1</span></span></span></span>, <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mn>7</mn><mo>=</mo><mn>2</mn><mo>∗</mo><mn>3</mn><mo>+</mo><mn>1</mn></mrow><annotation encoding=\"application/x-tex\">7 = 2*3 +1</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6444em;\"></span><span class=\"mord\">7</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6444em;\"></span><span class=\"mord\">2</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">∗</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.7278em;vertical-align:-0.0833em;\"></span><span class=\"mord\">3</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6444em;\"></span><span class=\"mord\">1</span></span></span></span> ...). The values can be changed through merging when a block stacks on top of another block of equal value. More information about the merging rule is in the \"Gameplay\" section.</p>\n<h4>Movement</h4>\n<p>Before we start implementing the game, let's first understand the gameplay of the 1023 Game. As shown in the screenshot below, this game is played on a 20x6 grid. The player can move the pieces left, right, down, or rotate them. The player can also drop the piece to the bottom of the grid.</p>\n<p>A proposed move is considered valid if none of the blocks of the piece move into the position of another block already on the grid (no overlapping blocks) or is out of bounds. If the move is considered invalid, the move will be ignored, and nothing happens. Some important rules about the movement of the piece:</p>\n<ol>\n<li>\n<p>The blocks do not fall automatically. That is, unlike Tetris, if the player does nothing, the piece will stay at the original position.</p>\n</li>\n<li>\n<p>The pieces can be moved with the <code>'a'</code>, <code>'s'</code>, <code>'d'</code> keys on the keyboard. In the graphical user interface (GUI) mode of the game, controlling with the arrow keys is also possible. The <code>'w'</code> key and the up arrow key are used for rotating the piece. Pieces do not move upwards.</p>\n</li>\n<li>\n<p>Press the space bar on the keyboard to drop the piece to the bottom of the grid. When blocks of equal value stack vertically, they merge. Unlike Tetris, gravity (dropping down) is applied to each block individually, not to the entire piece as a whole.</p>\n<figure><figcaption>Drop</figcaption></figure>\n</li>\n<li>\n<p>Since pieces will not fall automatically, the player has to press the space bar to drop the piece and continue the game. Even if the piece is already at the bottom, the space bar still needs to be pressed to proceed to the next piece.</p>\n</li>\n</ol>\n<h4>Merging</h4>\n<p>In this game, we have a special rule for merging blocks. When two blocks of equal values are stacked vertically, they will merge into a new block. The value of the new block is the sum of the values of the two blocks plus 1. After merging, the two blocks are replaced with the new block (with a value equal to two times the original value plus one) at the position of the lower block. For example, when two blocks of 15 are stacked, they will merge into a block of <code>31 (= 15 + 15 + 1)</code> at the position of the lower block (higher row index number). <strong>The result is NOT directly adding the values of the two blocks.</strong></p>\n<p>One special case is that when there are multiple blocks of equal value stacked together, the pair of blocks closest to the bottom will be merged first. Refer to the example below for a better understanding.</p>\n<figure><figcaption>Merge</figcaption></figure>\n<h4>Gameplay</h4>\n<p>The game starts with an empty grid. The game will keep generating new pieces with 4 blocks, each with a value randomly chosen from <code>[1, 3, 7, 15, 31, 63, 127, 255]</code>. The player can move the piece or drop the piece, and the game proceeds with the mechanics specified above.</p>\n<p>The goal of the player is to create a block with a value of 1023 through merging, and if they do so before losing the game, they win.</p>\n<p>The game will end when the player reaches the goal (has a block with a value of 1023) or any block <strong>touches</strong> the red limit line of the grid (that is, if there is any block in the top five rows) after merging checking, and all blocks of the current piece have fallen. If any block touches the line after the block merging process, the game ends, and the player loses. The limit line is represented by the red line in the images above. You can also observe the red limit line when you run your game. An example of a game lost is shown below.</p>\n<figure><figcaption>Game lost</figcaption></figure>\n<p>An example game play video recording is shown below.</p>\n<p><video src=\"https://github.com/AndersonHJB/AndersonHJB.github.io/releases/download/V0.06/035a069701ab5d0875fb969ab3f05387_raw.mp4\" controls=\"\" autoplay=\"\" loop=\"\" muted=\"\" width=\"600\"></video></p>\n<h4>Technical Details</h4>\n<p>In this section, we will provide some technical details about the game implementation.</p>\n<ol>\n<li>\n<p><strong>Game board</strong>: The game board is a 20x6 grid, and will be stored as a 2D list of values. A cell is referenced in the list as <code>game_board[row_number][col_number]</code>. Each cell contains a block value that can be used for merging. In this game, possible beginning block values are either <code>1 or 3 or 7 or 15 or 31 or 63 or 127 or 255</code>. Also, in this assignment, we will be following Python's convention of 0-based indexing.</p>\n<p>For easier implementation, the game board will <strong>NOT</strong> store data of the floating piece.</p>\n<p>For example, in the example below, we have <code>game_board[18][1] = 127</code>, but <code>game_board[6][2] = 0</code>.</p>\n<figure><figcaption>gameboard.png</figcaption></figure>\n</li>\n<li>\n<p><strong>Piece shape and location</strong>: The shapes of the pieces are stored in the list <code>shapes</code> (initialization is contained in the top portion of the provided skeleton program), accessed using <code>shapes[piece_number][rotation_number][block_number][dimension]</code>. Each element in the 4D list is an <code>int</code>, the row or column offset of the block.</p>\n<p>For example, <code>shapes[6][3] = [[0, 2], [-1, 1], [0, 1], [1, 1]]</code>, 6 corresponds to the T-shaped piece (shape 6), and 3 means the piece is rotated 3 times. The offsets of the first block (block 0) are <code>[0, 2]</code>. This means that the first block is at the same row as the piece's location (each piece has an anchor location), and 2 columns to the right of the piece's location.</p>\n<p>The location of a piece is stored as a pair of integers, the row and column of the piece, in a list of two integers <code>[r, c]</code>. It is the reference point for the blocks of the piece. The location of the piece itself may overlap with other blocks, or even outside the grid. When a piece is moved, the location of the piece is updated, and the new location is used to calculate the new position of the blocks using the offsets. All pieces start at position <code>[0, 1]</code> (row index: 0 and column index: 1).</p>\n<p>An example is provided here for better understanding (shape 6 rotation 3).</p>\n<figure><figcaption>shapes_new.png</figcaption></figure>\n<p>Suppose we want to calculate the position of the third block (block number 2) of the piece (shape number 6, rotation number 3). We can get the row offset by <code>shapes[6][3][2][0]</code>, which should be 0, and the column offset by <code>shapes[6][3][2][1]</code>, which should be 1. These offsets are then added to the piece's position at [row 9, column 1] to get the position of the block [row 9 + 0, column 1 + 1] = [row 9, column 2] or position [9, 2].</p>\n<p>Consider the piece <code>shapes[6][3][2][1]</code>.</p>\n<ul>\n<li>The first index (piece_number) <code>6</code> indicates the piece shape. Shape number 6 corresponds to the T-shaped piece.</li>\n<li>The second index (rotation_number) <code>3</code> indicates that the piece is rotated 3 times.</li>\n<li>The third index (block_number) <code>2</code> indicates block number 2 of the piece.</li>\n<li>The fourth index (dimension) <code>1</code> indicates the column offset of the block. Index of <code>0</code> contains the row offset instead. The dimension index is always either <code>0</code> (for row) or <code>1</code> (for column).</li>\n</ul>\n</li>\n<li>\n<p><strong>Rotation</strong>: The player can rotate the piece using the 'w' key or the up arrow key. The rotation is stored with an integer indicating the number of 90-degree rotations performed. However, in order to keep the numbers small and stop them from growing indefinitely, the rotation number is kept as <code>0 or 1 or 2 or 3</code>. After 3 rotations, if the player rotates the piece again, the rotation number will be reset to 0, since the piece returns to its original orientation.</p>\n</li>\n<li>\n<p><strong>CLI and GUI</strong>: We provide two versions of the game, one is the command-line interface (CLI), which is a text-based version of the game, using input statements and print statements to control the pieces' movement and show the current status. You can launch the CLI version by running the <code>cli.py</code> file.</p>\n<p>Another version is the graphical user interface (GUI) version, which is a more user-friendly version with graphics displayed on the screen. You can launch the GUI version by running the <code>gui.py</code> file. All examples above are based on the GUI version.</p>\n<p>In this assignment, you <strong>only</strong> have to implement the game logic in <code>game.py</code>.</p>\n<p><code>cli.py</code> and <code>gui.py</code> are provided to you. Feel free to modify <code>cli.py</code> and <code>gui.py</code> if you want to improve the user experience. <strong>However, you should make sure your game can be played normally when it is run with the unmodified code provided in the skeleton code.</strong></p>\n<p>Some of you may find it easier to debug using the CLI version since you are more familiar with the code structure and language features like <code>input()</code> and <code>print()</code>, and some of you may find it easier to use the GUI since you can better visualize the effect of the code. It does not matter whether you use the CLI or GUI version to debug or run your code. After you have implemented the game logic, the game should be able to run normally in both versions.</p>\n</li>\n</ol>\n<h4>How to Start</h4>\n<p>To begin your implementation:</p>\n<ol>\n<li>Make sure VS Code and Python 3.13.5 are both installed and set up (see <a href=\"https://course.cse.ust.hk/comp1023/labs/lab1\" target=\"_blank\" rel=\"noopener noreferrer\">lab 1</a> for the details) on your computer.</li>\n<li>Download the whole zipped package for this assignment <a href=\"https://course.cse.ust.hk/comp1023/assignments/pa1/skeleton.zip\" target=\"_blank\" rel=\"noopener noreferrer\">here</a>.</li>\n<li>Unzip the zip file into a directory. You should be able to see the directory \"pa1\" after unzipping. Open the directory \"pa1\" using VS Code (i.e., \"File\"-&gt;\"Open Folder...\").</li>\n<li>You should be able to see in the \"EXPLORER\" window of VS Code the files in the folder. There is the <code>game.py</code> file with Tasks that you need to work on. Modify only the <code>game.py</code> file - do not change any part of the <code>cli.py</code> and <code>gui.py</code> files!</li>\n<li>Implement the tasks in the <code>game.py</code> file according to the comments in the file and the description in the <a href=\"https://course.cse.ust.hk/comp1023/assignments/pa1/#description\" target=\"_blank\" rel=\"noopener noreferrer\">\"Description\"</a> part below. If you want to see whether you have implemented the tasks correctly, you can choose the <strong><code>cli.py</code></strong> file or <strong><code>gui.py</code></strong> under VS Code and then click the \"run\" button. If you run <a href=\"http://cli.py\" target=\"_blank\" rel=\"noopener noreferrer\">cli.py</a>, the plain text mode is run. If you run <a href=\"http://gui.py\" target=\"_blank\" rel=\"noopener noreferrer\">gui.py</a>, the GUI mode is run. The only difference between these two modes is in the way the 1023 game is displayed (text mode vs GUI mode). Before you have finished with the correct implementation of the tasks in the <code>game.py</code> file, it is normal to see error messages.</li>\n<li>After implementing each Task, you could <strong>run <code>cli.py</code> or <code>gui.py</code></strong> and see if that task has been implemented correctly. Repeat this for all the Tasks until you have implemented them all correctly.</li>\n<li><strong>Do not run <code>game.py</code>, it will show you nothing!</strong></li>\n</ol>\n<p>If you have any questions regarding the programming assignment, such as needing clarification on the requirements, please post your inquiries on the course Piazza (<a href=\"https://piazza.com/ust.hk/fall2025/comp1023l01l10/home\" target=\"_blank\" rel=\"noopener noreferrer\">https://piazza.com/ust.hk/fall2025/comp1023l01l10/home</a>). However, please refrain from posting your code to prevent other students from copying it, which could lead to issues of plagiarism.</p>\n<h3>Description</h3>\n<p>The following are tasks of the assignment. Please go through the tasks in the order listed. There are <strong>more specific requirements in the comments of the relevant functions in the skeleton code</strong>. This description is provided to give you a general overview of each function.</p>\n<p>All tasks below should be implemented in the <code>game.py</code> file. All numbers used should be of type <code>int</code>.</p>\n<h4>Task 1: Initialize Game Board</h4>\n<div class=\"language-py line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"py\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-py\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> init_gameboard</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">():</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div></div></div><p><strong>Description -</strong> In this task, you have to implement the <code>init_gameboard</code> function to create a 20x6 empty gameboard. In other words, complete Python code in the function init_gameboard() such that the function returns a 2D list (a list of lists) of 20 rows and 6 columns in each row, with each item in the 2D list having a value of 0 of type <code>int</code>. Edit the code inside the function <code>init_gameboard()</code> specified between <code>### TASK 1 STARTS HERE ###</code> and <code>### TASK 1 ENDS HERE ###</code> to return the game board list of lists.</p>\n<p>The lists inside the game board should be independent. That is, changing an element in a row should not affect the values of the other lists.</p>\n<p>To generate a list of lists <strong>independently</strong>, use simple <code>for</code> loops or <code>list comprehension</code> compactly. A simple <code>for</code> loop to generate a 2x2 2D array with zeros:</p>\n<div class=\"language-py line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"py\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-py\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">a </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> []</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> i </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> range</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    a.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">append</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">([</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">])</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(a)        </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># prints [[0, 0], [0, 0]]</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>Please note, however, that the <code>list</code> inside the <code>append</code> function <strong>must be a list of values and not variables defined elsewhere</strong>. For example, <code>[0, 0]</code> in <code>a.append([0, 0])</code> can be replaced with <code>[0 for i in range (2)]</code> but not <code>b = [0, 0]; a.append(b)</code>.</p>\n<h4>Task 2: Biased Random Value Selection</h4>\n<div class=\"language-py line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"py\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-py\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> default_random_number_generator</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">():</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div></div></div><p><strong>Description -</strong> To make the game more interesting, we would like our game to generate blocks with random values. However, if the probability of generating a piece with a large value (like 255) is high, the game would be too easy. Therefore, we would like to favor generating blocks with smaller values. <strong>Edit</strong> the code inside the function <code>default_random_number_generator()</code>, including changing the example <code>return</code> statement, if necessary, and return an appropriate integer.</p>\n<p>In this task, you have to modify the code between <code>### TASK 2 STARTS HERE ###</code> and <code>### TASK 2 ENDS HERE ###</code> in the <code>default_random_number_generator</code> function to generate a randomly selected number from the specified list that is more likely to be smaller (more likely to be within the smaller half subset than the larger half). To achieve this, you can generate 2 random numbers and take the minimum of the two numbers as the result. Return only an integer from this list: <code>1, 3, 7, 15, 31, 63, 127, 255</code>.</p>\n<p>The <code>randint</code> function of the <code>random</code> library can be used to generate random integers between two numbers (inclusively). For example, if you want to randomly pick a number from among <code>0, 1, 2, 3, 4</code>:</p>\n<div class=\"language-py line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"py\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-py\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">import</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> random</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">x </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> random.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">randint</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">4</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(x)          </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># generates a random integer between 0 and 4 inclusively</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>To pick the smaller of two given integers, the <code>min(a, b)</code> function can be used.</p>\n<div class=\"language-py line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"py\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-py\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">a, b </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">min</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(a, b)) </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># prints 0</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><h4>Task 3: Valid Position Checking</h4>\n<div class=\"language-py line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"py\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-py\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> is_valid_move</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">game_board</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> current_shape</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> current_location</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> current_rotation</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div></div></div><p><strong>Description -</strong> In this task, you have to implement the <code>is_valid_move</code> function to check if the piece can be placed in the given location. You are given the gameboard and the new position of the piece. Return True if the move is valid (no block is out of bounds in any side and no piece of the block is in a position where there is already another block) or return False otherwise. Edit the code inside the function <code>is_valid_move()</code> between <code>### TASK 3 STARTS HERE ###</code> and <code>### TASK 3 ENDS HERE ###</code> including changing the example <code>return</code> statement, if necessary. The function should return a <code>Boolean</code> type, <code>True</code> or <code>False</code>.</p>\n<p>A method to check validity is to iteratively go through each block (4 blocks in each shape) in a loop and calculate if that specific block's location on the grid is valid. Valid if not out of bounds and there is not already a block at that position. The <code>current_location</code> input parameter to the function represents the anchor coordinate of the position to check. Each block's location equals to the anchor position coordinate plus the offset from the specific rotation of the shape.</p>\n<p>For example, for shape 0 (<code>current_shape</code> == 0) and rotation 0 (<code>current_rotation</code> == 0), the coordinate offsets of the relevant four blocks are: <code>[[0, 0], [0, 1], [0, 2], [0, 3]]</code> (14th line of the skeleton program about the <code>shapes</code> variable initialization). If <code>current_location = [5, 5] </code>, then the coordinates of the four blocks to check are : <code>[5+0,5+0], [5+0,5+1], [5+0,5+2], [5+0,5+3]</code>, or the coordinates to check are: <code>[5,5], [5,6], [5,7], [5,8]</code>. Validity checks would include whether any of these coordinates are out of bounds (rows between 0 and 19 inclusive, columns between 0 and 5 inclusive) and if there is already a block in that coordinate. To check if there is already a block in that coordinate, check if the specific <code>game_board[row][column]</code> value of that block is not zero.</p>\n<p>Do NOT modify the input parameters inside the function.</p>\n<h4>Task 4-6: Move Piece</h4>\n<div class=\"language-py line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"py\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-py\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> move_left</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">game_board</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> current_shape</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> current_location</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> current_rotation</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> move_right</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">game_board</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> current_shape</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> current_location</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> current_rotation</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> move_down</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">game_board</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> current_shape</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> current_location</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> current_rotation</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p><strong>Description -</strong> Implement the <code>move_left</code>, <code>move_right</code>, and <code>move_down</code> functions to move the piece to the left, right, and down, respectively. Keep the piece in the original position if the move is invalid. You may use the <code>is_valid_move</code> function to help with your implementation. Edit the code inside the functions <code>move_left()</code>, <code>move_right()</code>, and <code>move_down()</code> between <code>### TASK x STARTS HERE ###</code> and <code>### TASK x ENDS HERE ###</code> (x is the task number), including changing the example <code>return</code> statements, if necessary, and return two values: location and rotation. The syntax to <code>return</code> two variables, <code>x1</code> and <code>x2</code>, would be <code>return x1, x2</code>. Please note that location is a list of two integers and rotation is an integer.</p>\n<p>In each of the functions <code>move_left</code>, <code>move_right</code>, and <code>move_down</code>, check if the piece with the proposed new location and unchanged rotation is valid. If valid, return the new location and rotation values. If invalid, return the original location and rotation values. The original location and rotation values are the input parameters to the functions.</p>\n<p>Do NOT modify the game_board parameter inside these functions.</p>\n<h4>Task 7: Rotate Piece</h4>\n<div class=\"language-py line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"py\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-py\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> rotate</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">game_board</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> current_shape</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> current_location</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> current_rotation</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div></div></div><p><strong>Description -</strong> In this task, you have to implement the <code>rotate</code> function to rotate the piece (rotate means to increase rotation by 1 modulo 4). Keep the piece in the original orientation if the new position is invalid. You may use the <code>is_valid_move</code> function to help with your implementation. Edit the code inside the function <code>rotate()</code> between <code>### TASK 7 STARTS HERE ###</code> and <code>### TASK 7 ENDS HERE ###</code>, including changing the example <code>return</code> statement, if necessary, and return two values: location and rotation in similar syntax to <code>return x1, x2</code>.</p>\n<p>Check if the <strong>proposed</strong> rotation with unchanged location is valid. Return new values if valid, return original values otherwise.</p>\n<p>Do NOT modify the game_board parameter inside this function.</p>\n<h4>Task 8: Gravity and Merge</h4>\n<div class=\"language-py line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"py\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-py\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> gravity_and_merge</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">game_board</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div></div></div><p><strong>Description -</strong> In this task, you have to implement the <code>gravity_and_merge</code> function according to the mechanisms described above in the \"Introduction\" section. The parameter of the function is the gameboard only, with the new piece already inserted to the gameboard. The function should directly update the gameboard. Edit the code inside the function <code>gravity_and_merge()</code> between <code>### TASK 8 STARTS HERE ###</code> and <code>### TASK 8 ENDS HERE ###</code>.</p>\n<p>There are two sets of actions in this task: gravity and merging:</p>\n<ul>\n<li>\n<p><strong>Gravity</strong></p>\n<p>Gravity refers to moving blocks of the \"floating\" piece (with empty cells below) to the empty cell (largest row number) closest to the game board's bottom.</p>\n</li>\n<li>\n<p><strong>Merging</strong></p>\n<p>Merging is described in the section headed \"Introduction\" above. Merging is performed from bottom up, not top down.</p>\n</li>\n</ul>\n<p>A possible algorithm can be:</p>\n<div class=\"language- line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-\"><span class=\"line\"><span>Loop through each column:</span></span>\n<span class=\"line\"><span>  Repeat this 20 times (or number of rows): </span></span>\n<span class=\"line\"><span>    Loop through each row, but from bottom to top, and check each cell to:</span></span>\n<span class=\"line\"><span>      Take the cell value above if the current cell is empty and reset the above cell (gravity); or</span></span>\n<span class=\"line\"><span>      Merge if the current cell value equals the cell value above and reset the above cell value (merge); or</span></span>\n<span class=\"line\"><span>      Do nothing</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><h4>Task 9: Get Game Status</h4>\n<div class=\"language-py line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"py\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-py\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> get_game_status</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">game_board</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div></div></div><p><strong>Description -</strong> In this task, you have to implement the <code>get_game_status</code> function to check the game status. You should <code>return \"Lose\"</code> or <code>return \"Win\"</code> or <code>return \"Playing\"</code>. The game is considered to be \"Win\" if there is a block with a value of 1023 on the gameboard. The game is considered to be \"Lose\" if the blocks touch the line after the block merging process. To be specific, that is to check if any of the top five rows of the game board contain non zero values. Otherwise, the game is considered to be \"Playing\". If there is a block with a value of 1023 and a block in the top five rows at the same time, the game is considered to be \"Lose\".</p>\n<p>Do NOT modify the game_board parameter inside this function.</p>\n<h4>Optional Task: Custom Random Value Selection</h4>\n<div class=\"language-py line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"py\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-py\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> custom_random_number_generator</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">():</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div></div></div><p><strong>Description -</strong> In this optional task, you can implement the <code>custom_random_number_generator</code> function to create your own random number generator to make the game more interesting. You can use any method to generate a random number. You can also use this function for debugging purposes. <strong>This task will NOT be graded.</strong></p>\n\n",
      "date_published": "2025-10-08T21:12:21.000Z",
      "date_modified": "2025-10-22T03:37:58.000Z",
      "authors": [
        {
          "name": "bornforthis"
        }
      ],
      "tags": []
    },
    {
      "title": "09-Lab 9：Time complexity. More practice on debugging and programming",
      "url": "https://bornforthis.cn/1v1/101-Sallymisty/Lab/09-Lab9-Time-complexity-More-practice-on-debugging-and-programming.html",
      "id": "https://bornforthis.cn/1v1/101-Sallymisty/Lab/09-Lab9-Time-complexity-More-practice-on-debugging-and-programming.html",
      "summary": "1. Objectives The purpose of this week's lab is to: Analyse time complexity of certain programs. Practice debugging code again. Practice more programming problems. If you have a...",
      "content_html": "<h2>1. Objectives</h2>\n<p>The purpose of this week's lab is to:</p>\n<ul>\n<li>Analyse time complexity of certain programs.</li>\n<li>Practice debugging code again.</li>\n<li>Practice more programming problems.</li>\n</ul>\n<p><strong>If you have any questions about any of the material in the previous labs, now is a good time to ask your tutor for help during the lab.</strong></p>\n<div class=\"hint-container info\">\n<p class=\"hint-container-title\">相关信息</p>\n<p>If you do not have time to finish all exercises (in particular, the programming problems) during the lab time, you should continue working on them later.</p>\n</div>\n<h2>2. Time complexity</h2>\n<p>As we have seen in the lecture last week, the big-O notation is used to denote the <em>worst-case</em> time complexity of an algorithm to solve a certain problem. If the problem size is n<em>n</em> and the algorithm needs <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>x</mi><mo>×</mo><mi>n</mi></mrow><annotation encoding=\"application/x-tex\">x \\times n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6667em;vertical-align:-0.0833em;\"></span><span class=\"mord mathnormal\">x</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">×</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.4306em;\"></span><span class=\"mord mathnormal\">n</span></span></span></span> numerical <em>operations</em> to solve it, where c<em>c</em> is a constant number (thus independent of <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>n</mi></mrow><annotation encoding=\"application/x-tex\">n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.4306em;\"></span><span class=\"mord mathnormal\">n</span></span></span></span>), we say that the algorithm has a <em>linear</em> time complexity <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mi>n</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(n)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">n</span><span class=\"mclose\">)</span></span></span></span>. Here, we assume that each operation has a constant time complexity <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mn>1</mn><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(1)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord\">1</span><span class=\"mclose\">)</span></span></span></span>. (Otherwise, the algorithm won't have a linear complexity anymore.)</p>\n<p>For example, the following function finds the index of an element in a sequence, (returning <code>-1</code> if the element is not found):</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> find_element</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">sequence</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> element</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> i </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> range</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(sequence)):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> sequence[i] </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">==</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> element:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">            return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> i</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> -</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>It has time complexity of <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mi>n</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(n)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">n</span><span class=\"mclose\">)</span></span></span></span>, where n<em>n</em> is the length of the sequence. This is because the main <code>for</code> loop needs n<em>n</em> comparisons in the worst-case, namely when the element we are looking for does not appear in the sequence.</p>\n<p>As a rule of thumb, a <code>for</code> or <code>while</code> loop with n<em>n</em> iterations indicates that the code may have a complexity of <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mi>n</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(n)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">n</span><span class=\"mclose\">)</span></span></span></span>. If there are two loops nested within each other, the code might have a <em>quadratic</em> time complexity of <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mi>n</mi><mn>2</mn><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(n2)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">n</span><span class=\"mord\">2</span><span class=\"mclose\">)</span></span></span></span>.</p>\n<p>Let's look at an example: the following code computes the minimum absolute difference between any pairs of elements in a numerical sequence:</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> smallest_difference</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">sequence</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    min_diff </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> abs</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(sequence[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">sequence[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">])</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> i </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> range</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(sequence)</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> j </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> range</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(i</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(sequence)):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">            diff </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> abs</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(sequence[i] </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> sequence[j])</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">            if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> diff </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&lt;</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> min_diff:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">                min_diff </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> diff</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> min_diff</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>Let's analyse the time complexity of this code. Let n<em>n</em> be the length of the input sequence. The outer <code>for</code> loop has <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>n</mi><mo>−</mo><mn>1</mn></mrow><annotation encoding=\"application/x-tex\">n−1</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6667em;vertical-align:-0.0833em;\"></span><span class=\"mord mathnormal\">n</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">−</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6444em;\"></span><span class=\"mord\">1</span></span></span></span> iterations using index <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>i</mi></mrow><annotation encoding=\"application/x-tex\">i</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6595em;\"></span><span class=\"mord mathnormal\">i</span></span></span></span>. In the first iteration of the outer loop, i.e., when <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>i</mi><mo>=</mo><mn>0</mn></mrow><annotation encoding=\"application/x-tex\">i=0</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6595em;\"></span><span class=\"mord mathnormal\">i</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6444em;\"></span><span class=\"mord\">0</span></span></span></span>, the inner loop iterates in <code>range(1,n)</code>, each doing four operations (subtraction, <code>abs</code>, comparison, and assignment), totalling <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mn>4</mn><mo stretchy=\"false\">(</mo><mi>n</mi><mo>−</mo><mn>1</mn><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">4(n−1)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord\">4</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">n</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">−</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord\">1</span><span class=\"mclose\">)</span></span></span></span> operations. In the 2nd iteration of the outer loop (<span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>i</mi><mo>=</mo><mn>1</mn></mrow><annotation encoding=\"application/x-tex\">i=1</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6595em;\"></span><span class=\"mord mathnormal\">i</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6444em;\"></span><span class=\"mord\">1</span></span></span></span>), the inner loop iterates over <code>range(2,n)</code>, which means <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>n</mi><mo>−</mo><mn>2</mn></mrow><annotation encoding=\"application/x-tex\">n−2</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6667em;vertical-align:-0.0833em;\"></span><span class=\"mord mathnormal\">n</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">−</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6444em;\"></span><span class=\"mord\">2</span></span></span></span> iterations. And so on. Summing all together, the total number of operations is:</p>\n<p v-pre=\"\" class=\"katex-block\"><span class=\"katex-display\"><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\" display=\"block\"><semantics><mrow><mn>4</mn><mo stretchy=\"false\">(</mo><mi>n</mi><mo>−</mo><mn>1</mn><mo stretchy=\"false\">)</mo><mo>+</mo><mn>4</mn><mo stretchy=\"false\">(</mo><mi>n</mi><mo>−</mo><mn>2</mn><mo stretchy=\"false\">)</mo><mo>+</mo><mo>⋯</mo><mo>+</mo><mn>4</mn><mo>=</mo><mn>4</mn><mi>n</mi><mfrac><mrow><mi>n</mi><mo>−</mo><mn>1</mn></mrow><mn>2</mn></mfrac><mo>=</mo><mn>2</mn><msup><mi>n</mi><mn>2</mn></msup><mo>−</mo><mn>2</mn><mi>n</mi></mrow><annotation encoding=\"application/x-tex\">4(n - 1) + 4(n - 2) + \\cdots + 4 = 4n \\frac{n - 1}{2} = 2n^2 - 2n\n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord\">4</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">n</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">−</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord\">1</span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord\">4</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">n</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">−</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord\">2</span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6667em;vertical-align:-0.0833em;\"></span><span class=\"minner\">⋯</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6444em;\"></span><span class=\"mord\">4</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:2.0074em;vertical-align:-0.686em;\"></span><span class=\"mord\">4</span><span class=\"mord mathnormal\">n</span><span class=\"mord\"><span class=\"mopen nulldelimiter\"></span><span class=\"mfrac\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:1.3214em;\"><span style=\"top:-2.314em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"mord\"><span class=\"mord\">2</span></span></span><span style=\"top:-3.23em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"frac-line\" style=\"border-bottom-width:0.04em;\"></span></span><span style=\"top:-3.677em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">n</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">−</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mord\">1</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.686em;\"><span></span></span></span></span></span><span class=\"mclose nulldelimiter\"></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.9474em;vertical-align:-0.0833em;\"></span><span class=\"mord\">2</span><span class=\"mord\"><span class=\"mord mathnormal\">n</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8641em;\"><span style=\"top:-3.113em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">−</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6444em;\"></span><span class=\"mord\">2</span><span class=\"mord mathnormal\">n</span></span></span></span></span></p>\n<p>Now, when <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>n</mi></mrow><annotation encoding=\"application/x-tex\">n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.4306em;\"></span><span class=\"mord mathnormal\">n</span></span></span></span> is large enough, the <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><msup><mi>n</mi><mn>2</mn></msup></mrow><annotation encoding=\"application/x-tex\">n^2</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8141em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">n</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8141em;\"><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span></span></span></span></span></span></span></span> term will dominate over the n<em>n</em> term. We can also ignore the constant <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mn>2</mn></mrow><annotation encoding=\"application/x-tex\">2</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6444em;\"></span><span class=\"mord\">2</span></span></span></span> multiplying this leading term. That means that the function <code>smallest_difference</code> has time complexity <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mi>n</mi><mn>2</mn><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(n2)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">n</span><span class=\"mord\">2</span><span class=\"mclose\">)</span></span></span></span>.</p>\n<h2>3. Exercise 1.0</h2>\n<p>Each of the following three functions takes as input an integer n. For each function, give its computational complexity in big-O notation in terms of n.</p>\n<p>It is important you to format your answer exactly. If the algorithm has linear time complexity, you should answer:</p>\n<p><span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mi>n</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(n)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">n</span><span class=\"mclose\">)</span></span></span></span></p>\n<p>If the algorithm has cubic time complexity, then either of the following are acceptable:</p>\n<p><span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><msup><mi>n</mi><mn>3</mn></msup><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(n^3)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1.0641em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord\"><span class=\"mord mathnormal\">n</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8141em;\"><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">3</span></span></span></span></span></span></span></span><span class=\"mclose\">)</span></span></span></span></p>\n<p><span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mi>n</mi><mo>∗</mo><mo>∗</mo><mn>3</mn><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(n**3)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">n</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">∗</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord\">∗</span><span class=\"mord\">3</span><span class=\"mclose\">)</span></span></span></span></p>\n<p>Other possible time complexities should be formatted similarly.</p>\n<h3>3.1 Question 1</h3>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> func_a</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">n</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    total </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 0</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> i </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> range</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(n):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> j </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> range</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(n):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">            total </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> total </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> i </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">*</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> j</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> total</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><blockquote>\n<p><span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><msup><mi>n</mi><mn>2</mn></msup><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(n^2)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1.0641em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord\"><span class=\"mord mathnormal\">n</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8141em;\"><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span></span></span></span></span><span class=\"mclose\">)</span></span></span></span></p>\n</blockquote>\n<h3>3.2 Question 2</h3>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> fun_b</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">n</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    total </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 0</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> i </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> range</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">100</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> *</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> n):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> j </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> range</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">10</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">            total </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> total </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> i </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">*</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> j</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> total</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><blockquote>\n<p>外层 <code>100*n</code>、内层常数 <code>10</code>，常数忽略：</p>\n<p><span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mi>n</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(n)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">n</span><span class=\"mclose\">)</span></span></span></span></p>\n</blockquote>\n<h3>3.3 Question 3</h3>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> fun_c</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">n</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    total </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 0</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> i </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> range</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">100</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> j </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> range</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(n):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">            total </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> total </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> i </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">*</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> j</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> k </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> range</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(n):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">            total </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> total </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> i </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">*</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> k</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> l </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> range</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">100</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">            total </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> total </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> i </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">*</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> l</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> l</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><blockquote>\n<p>外层常数 <code>100</code>；内有两个 <code>range(n)</code> 和一个常数 <code>range(100)</code>，总体仍线性于 <code>n</code>：</p>\n<p><span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mi>n</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(n)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">n</span><span class=\"mclose\">)</span></span></span></span></p>\n</blockquote>\n<h2>4. Exercise 1.1: Efficient Implementation of smallest_difference</h2>\n<p>It turns out that there is another algorithm for <code>smallest_difference</code> with a time complexity of only <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mi>n</mi><mi>log</mi><mo>⁡</mo><mo stretchy=\"false\">(</mo><mi>n</mi><mo stretchy=\"false\">)</mo><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(n \\log(n))</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">n</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mop\">lo<span style=\"margin-right:0.01389em;\">g</span></span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">n</span><span class=\"mclose\">))</span></span></span></span>. Can you figure it out? Write your solution in the scaffold file <code>smallest_difference.py</code> with that time complexity.</p>\n<div class=\"hint-container info\">\n<p class=\"hint-container-title\">相关信息</p>\n<p>After thinking about it and you still can't find it out, click the spoiler below for a hint!</p>\n</div>\n<p><strong>Expand：</strong> What if the sequence is sorted? What is the time for sorting?</p>\n<p><strong>smallest_difference.py</strong></p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> smallest_difference</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">sequence</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">    # </span><span style=\"--shiki-light:#A626A4;--shiki-light-font-style:italic;--shiki-dark:#C678DD;--shiki-dark-font-style:italic\">TODO</span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">: Find the smallest difference </span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">    # between numbers in the sequence</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">    # in worst-case O(n log(n)) time.</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    pass</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><div class=\"language-python line-numbers-mode has-collapsed-lines collapsed\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--vp-collapsed-lines:15;--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> smallest_difference</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">sequence</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    \"\"\"</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    Return the smallest absolute difference between any two numbers in sequence.</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    Worst-case time: O(n log n) due to sorting; the scan is O(n).</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    Assumes len(sequence) &gt;= 2. Raises ValueError otherwise.</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    \"\"\"</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    if</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(sequence) </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&lt;</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        raise</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#ABB2BF\"> ValueError</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"sequence must contain at least two elements\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    seq </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> sorted</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(sequence)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    min_diff </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> abs</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(seq[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">] </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> seq[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">])</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> i </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> range</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(seq)):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">        d </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> abs</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(seq[i] </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> seq[i </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">])</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> d </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&lt;</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> min_diff:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">            min_diff </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> d</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">            if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> min_diff </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">==</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:  </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># early exit: duplicate values</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">                return</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 0</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> min_diff</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div><div class=\"collapsed-lines\"></div></div><h2>5. Exercise 1.2: Largest Difference</h2>\n<p>Here is an implementation to compute the maximum absolute difference in a similar style to <code>smallest_difference</code>:</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> largest_difference</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">sequence</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    max_diff </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> abs</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(sequence[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">sequence[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">])</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> i </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> range</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(sequence)):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> j </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> range</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(i):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">            diff </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> abs</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(sequence[i] </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> sequence[j])</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">            if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> max_diff </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&lt;</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> diff:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">                max_diff </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> diff</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> max_diff</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>It has a time complexity of <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><msup><mi>n</mi><mn>2</mn></msup><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(n^2)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1.0641em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord\"><span class=\"mord mathnormal\">n</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8141em;\"><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span></span></span></span></span><span class=\"mclose\">)</span></span></span></span>. You can of course use the same idea from exercise 1.1 to reduce the complexity to <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mi>n</mi><mi>log</mi><mo>⁡</mo><mo stretchy=\"false\">(</mo><mi>n</mi><mo stretchy=\"false\">)</mo><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(n \\log(n))</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">n</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mop\">lo<span style=\"margin-right:0.01389em;\">g</span></span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">n</span><span class=\"mclose\">))</span></span></span></span>.</p>\n<p>However, it turns out there is another algorithm with linear time complexity: <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mi>n</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(n)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">n</span><span class=\"mclose\">)</span></span></span></span>. Can you work it out? Provide a solution to the <code>largest_difference</code> function with that time complexity.</p>\n<p><strong>largest_difference.py</strong></p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> largest_difference</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">sequence</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">    # </span><span style=\"--shiki-light:#A626A4;--shiki-light-font-style:italic;--shiki-dark:#C678DD;--shiki-dark-font-style:italic\">TODO</span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">: Find the largest difference </span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">    # between numbers in the sequence</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">    # in worst-case O(n log(n)) time</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    pass</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div>",
      "image": "https://bornforthis.cn/gzh.jpg",
      "date_published": "2025-10-08T14:17:57.000Z",
      "date_modified": "2025-10-09T12:01:20.000Z",
      "authors": [
        {
          "name": "bornforthis"
        }
      ],
      "tags": []
    },
    {
      "title": "Lab4 香港科技大学",
      "url": "https://bornforthis.cn/1v1/100-Leo/Lab4.html",
      "id": "https://bornforthis.cn/1v1/100-Leo/Lab4.html",
      "summary": "Background The three lifts transport people between the ground floor (G/F) and the 10th floor (10/F). They do not stop at other floors. Let's suppose each lift has a screen show...",
      "content_html": "<h4>Background</h4>\n<p>The three lifts transport people between the ground floor (G/F) and the 10th floor (10/F). They do not stop at other floors.</p>\n<p>Let's suppose each lift has a screen showing its current floor and status. Floor, which is a string, can be either <code>G</code> or <code>10</code>. Status, which is also a string, can be one of <code>moving up</code>, <code>moving down</code> or <code>stopped</code>. These are similar to the information that the screens for those real lifts show.</p>\n<p>Here are some examples of what the floor and status of a lift mean:</p>\n<p>| Floor | Status      | Meaning                                                 |<br>\n|</p>\n",
      "date_published": "2025-10-04T21:29:53.000Z",
      "date_modified": "2025-10-08T13:24:35.000Z",
      "authors": [
        {
          "name": "AI悦创"
        }
      ],
      "tags": []
    },
    {
      "title": "03-分组与引用：如何用正则实现更复杂的查找和替换操作？",
      "url": "https://bornforthis.cn/column/Python-Programming-Course/P11-regex-intro-course/03-regex-grouping-backreferences-replace.html",
      "id": "https://bornforthis.cn/column/Python-Programming-Course/P11-regex-intro-course/03-regex-grouping-backreferences-replace.html",
      "summary": "你好，我是悦创。 今天我打算和你聊聊分组与引用。那什么场合下会用到分组呢？ 假设我们现在要去查找 15 位或 18 位数字。根据前面学习的知识，使用量词可以表示出现次数，使用管道符号可以表示多个选择，你应该很快就能写出 \\d{15}|\\d{18} 。但经过测试，你会发现，这个正则并不能很好地完成任务，因为 18 位数字也会匹配上前 15 位，具体如下图...",
      "content_html": "<figure><figcaption></figcaption></figure>\n<p>你好，我是悦创。</p>\n<p>今天我打算和你聊聊分组与引用。那什么场合下会用到分组呢？</p>\n<p>假设我们现在要去查找 15 位或 18 位数字。根据前面学习的知识，使用量词可以表示出现次数，使用管道符号可以表示多个选择，你应该很快就能写出 <code>\\d{15}|\\d{18}</code> 。但经过测试，你会发现，这个正则并不能很好地完成任务，因为 18 位数字也会匹配上前 15 位，具体如下图所示。</p>\n<figure><figcaption></figcaption></figure>\n<p>为了解决这个问题，你灵机一动，很快就想到了办法，就是把 15 和 18 调换顺序，即写成 <code>\\d{18}|\\d{15}</code>。你发现，这回符合要求了。</p>\n<figure><figcaption></figcaption></figure>\n<p>为什么会出现这种情况呢？因为在大多数正则实现中，多分支选择都是左边的优先。类似地，你可以使用 “<code>北京市|北京</code>” 来查找 “<code>北京</code>” 和 “<code>北京市</code>”。另外我们前面学习过，问号可以表示出现 0 次或 1 次，你发现可以使用“<code>北京市?</code>” 来实现来查找 “<code>北京</code>” 和 “<code>北京市</code>”。</p>\n<figure><figcaption></figcaption></figure>\n<p>同样，针对 15 或 18 位数字这个问题，可以看成是 15 位数字，后面 3 位数据有或者没有，你应该很快写出了 <code>\\d{15}\\d{3}?</code> 。但这样写对不对呢？我们来看一下。</p>\n<p>在上一节我们学习了量词后面加问号表示非贪婪，而我们现在想要的是 <code>\\d{3}</code> 出现 0 次或 1 次。</p>\n<ul>\n<li><strong>示例一</strong>：<code>\\d{15}\\d{3}?</code> 由于 <code>\\d{3}</code> 表示三次，加问号非贪婪还是 3 次；</li>\n<li><strong>示例二</strong>：<code>\\d{15}(\\d{3})?</code> 在 <code>\\d{3}</code> 整体后加问号，表示后面三位有或无；</li>\n</ul>\n<p>这时候，必须使用括号将来把表示“三个数字”的 <code>\\d{3}</code> 这一部分括起来，也就是表示成 <code>\\d{15}(\\d{3})?</code> 这样。现在就比较清楚了：括号在正则中的功能就是用于分组。简单来理解就是，由多个元字符组成某个部分，应该被看成一个整体的时候，可以用括号括起来表示一个整体，这是括号的一个重要功能。其实用括号括起来还有另外一个作用，那就是“复用”，我接下来会给你讲讲这个作用。</p>\n<h2>1. 分组与编号</h2>\n<p>括号在正则中可以用于分组，被括号括起来的部分“子表达式”会被保存成一个子组。</p>\n<p>那分组和编号的规则是怎样的呢？其实很简单，用一句话来说就是，第几个括号就是第几个分组。这么说可能不好理解，我们来举一个例子看一下。</p>\n<p>这里有个时间格式 2020-05-10 20:23:05。假设我们想要使用正则提取出里面的日期和时间。</p>\n<figure><figcaption></figcaption></figure>\n<p>我们可以写出如图所示的正则，将日期和时间都括号括起来。这个正则中一共有两个分组，日期是第 1 个，时间是第 2 个。</p>\n<h3>1.1 不保存子组</h3>\n<p>在括号里面的会保存成子组，但有些情况下，你可能只想用括号将某些部分看成一个整体，后续不用再用它，类似这种情况，在实际使用时，是没必要保存子组的。这时我们可以在括号里面使用 <code>?:</code> 不保存子组。</p>\n<p>如果正则中出现了括号，那么我们就认为，这个子表达式在后续可能会再次被引用，所以不保存子组可以提高正则的性能。除此之外呢，这么做还有一些好处，由于子组变少了，正则性能会更好，在子组计数时也更不容易出错。</p>\n<p>那到底啥是不保存子组呢？我们可以理解成，括号只用于归组，把某个部分当成“单个元素”，不分配编号，后面不会再进行这部分的引用。</p>\n<figure><figcaption></figcaption></figure>\n<figure><figcaption></figcaption></figure>\n<h3>1.2 括号嵌套</h3>\n<p>前面讲完了子组和编号，但有些情况会比较复杂，比如在括号嵌套的情况里，我们要看某个括号里面的内容是第几个分组怎么办？不要担心，其实方法很简单，我们只需要数左括号（开括号）是第几个，就可以确定是第几个子组。</p>\n<p>在阿里云简单日志系统中，我们可以使用正则来匹配一行日志的行首。假设时间格式是 2020-05-10 20:23:05 。</p>\n<figure><figcaption></figcaption></figure>\n<p>日期分组编号是 1，时间分组编号是 5，年月日对应的分组编号分别是 2，3，4，时分秒的分组编号分别是 6，7，8。</p>\n<h3>1.3 命名分组</h3>\n<p>前面我们讲了分组编号，但由于编号得数在第几个位置，后续如果发现正则有问题，改动了括号的个数，还可能导致编号发生变化，因此一些编程语言提供了命名分组（named grouping），这样和数字相比更容易辨识，不容易出错。命名分组的格式为 <code>(?P&lt;分组名&gt;正则)</code>。</p>\n<p>比如在 Django 的路由中，命名分组示例如下：</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">url</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">r</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#E06C75\">'^profile/</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#D19A66\">(</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">?P&lt;username&gt;</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#E06C75\">\\w</span><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">+</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#D19A66\">)</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#E06C75\">/$'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, view_func)</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div></div></div><p>需要注意的是，刚刚提到的方式命名分组和前面一样，给这个分组分配一个编号，不过你可以使用名称，不用编号，实际上命名分组的编号已经分配好了。不过命名分组并不是所有语言都支持的，在使用时，你需要查阅所用语言正则说明文档，如果支持，那你才可以使用。</p>\n<h2>2. 分组引用</h2>\n<p>在知道了分组引用的编号 （number）后，大部分情况下，我们就可以使用 “反斜扛 + 编号”，即 <code>\\number</code> 的方式来进行引用，而 JavaScript 中是通过 <code>$</code> 编号来引用，如 <code>$1</code>。</p>\n<p>我给到了你一些在常见的编程语言中，分组查找和替换的引用方式：</p>\n<figure><figcaption></figcaption></figure>\n<p>这些内容不要求你完全记住，只要有个印象就好，最关键的是要知道正则可以实现这样的功能，需要用到的时候查一下相应的文档，就知道怎么用了。</p>\n<h2>3. 分组引用在查找中使用</h2>\n<p>前面介绍了子组和引用的基本知识，现在我们来看下在正则查找时如何使用分组引用。比如我们要找重复出现的单词，我们使用正则可以很方便地使“前面出现的单词再次出现”，具体要怎么操作呢？我们可以使用 <code>\\w+</code> 来表示一个单词，针对刚刚的问题，我们就可以很容易写出 <code>(\\w+) \\1</code> 这个正则表达式了。</p>\n<figure><figcaption></figcaption></figure>\n<h2>4. 分组引用在替换中使用</h2>\n<p>和查找类似，我们可以使用反向引用，在得到的结果中，去拼出来我们想要的结果。还是使用刚刚日期时间的例子，我们可以很方便地将它替换成， 2020 年 05 月 10 日这样的格式。</p>\n<figure><figcaption></figcaption></figure>\n<p>由于这个例子稍微复杂一些，这里我给出一个<a href=\"https://regex101.com/r/2RVPTJ/2\" target=\"_blank\" rel=\"noopener noreferrer\">示例链接</a>方便你学习，不知道学到这里，你有没有觉得子组和引用非常强大呢？</p>\n<details class=\"hint-container details\"><summary>详情</summary>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">((\\</span><span style=\"--shiki-light:white;--shiki-dark:#FFFFFF\">d{4})-(\\d{2})-(\\d{2})) ((\\d{2}):(\\d{2}):(\\d{2}))</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2020</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0</span><span style=\"--shiki-light:white;--shiki-dark:#FFFFFF\">5</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">10</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 20</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">23</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0</span><span style=\"--shiki-light:white;--shiki-dark:#FFFFFF\">5</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><figure><figcaption></figcaption></figure>\n</details>\n<p>你可能很好奇，那在编程语言中如何实现这个功能呢？我下面以 Python3 为例，给出一个示例。</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&gt;&gt;&gt;</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> import</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> re</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&gt;&gt;&gt;</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> test_str </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> \"2020-05-10 20:23:05\"</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&gt;&gt;&gt;</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> regex </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> r</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#E06C75\">\"</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#D19A66\">((</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#E06C75\">\\d</span><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">{4}</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#D19A66\">)</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#E06C75\">-</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#D19A66\">(</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#E06C75\">\\d</span><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">{2}</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#D19A66\">)</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#E06C75\">-</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#D19A66\">(</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#E06C75\">\\d</span><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">{2}</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#D19A66\">))</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#D19A66\"> ((</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#E06C75\">\\d</span><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">{2}</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#D19A66\">)</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#E06C75\">:</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#D19A66\">(</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#E06C75\">\\d</span><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">{2}</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#D19A66\">)</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#E06C75\">:</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#D19A66\">(</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#E06C75\">\\d</span><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">{2}</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#D19A66\">))</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#E06C75\">\"</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&gt;&gt;&gt;</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> subst </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> r</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#E06C75\">\"日期</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">\\1</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#E06C75\"> 时间</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">\\5</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">   \\2</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#E06C75\">年</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">\\3</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#E06C75\">月</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">\\4</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#E06C75\">日 </span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">\\6</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#E06C75\">时</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">\\7</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#E06C75\">分</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">\\8</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#E06C75\">秒\"</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&gt;&gt;&gt;</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> re.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">sub</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(regex, subst, test_str)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'日期2020-05-10 时间20:23:05   2020年05月10日 20时23分05秒'</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>在 Python 中 sub 函数用于正则的替换，使用起来也非常简单，和在网页上操作测试的几乎一样。</p>\n<h2>5. 在文本编辑器中使用</h2>\n<h3>5.1 Sublime Text 3 简介</h3>\n<p>接下来我用 Sublime Text 3 来当例子，给你讲解一下正则查找和替换的使用方式。Sublime Text 3 是一个跨平台编辑器，非常小巧、强悍，虽然是一个收费软件，但可以永久试用，你自行可以下载安装。</p>\n<p>当熟练使用编辑器之后，你会发现在很多工作里都可以使用它，不需要编写代码就可以完成。</p>\n<p>下面我以文本编辑器 Sublime Text 3 为例，来讲解正则查找和替换的使用方式。首先，我们要使用的“查找”或“替换”功能，在菜单 Find 中可以找到。</p>\n<figure><figcaption></figcaption></figure>\n<p>下面是对编辑器查找 - 替换界面的图标简介，Find 输入栏第一个 <code>.*</code> 图标，表示开启或关闭正则支持。</p>\n<figure><figcaption></figcaption></figure>\n<h3>5.2 编辑器中进行正则查找</h3>\n<p>接下来，我们来演示用编辑器查找引号引起来的内容，课程中使用到的文本，建议你用 chrome 等浏览器等，打开极客时间网页版本 <a href=\"https://bornforthis.cn/\" target=\"_blank\" rel=\"noopener noreferrer\">https://bornforthis.cn/</a>，点击右键查看源代码，把看到的代码复制到 Sublime Text 3 中。</p>\n<figure><figcaption></figcaption></figure>\n<p>输入相应的正则，我们就可以看到查找的效果了。这里给一个小提示，如果你点击 Find All，然后进行剪切，具体操作可以在菜单中找到 Edit -&gt; Cut，也可以使用快捷键操作。剪切之后，找一个空白的地方，粘贴就可以看到提取出的所有内容了。</p>\n<p>我们可以使用正则进行资源链接提取，比如从一个图片网站的源代码中查找到图片链接，然后再使用下载工具批量下载这些图片。</p>\n<h3>5.3 在编辑器中进行正则替换</h3>\n<p>接着，我们再来看一下在编辑器中进行文本替换工作。你可以在编辑器中输入这些文本：</p>\n<p>the little cat cat is in the hat hat, we like it.</p>\n<p>如果我们要尝试从中查找连续重复出现两次的单词，我们可以用 \\w+ 代表单词，利用我们刚刚学习的知识，相信你可以很快写出正则 <code>(\\w+) \\1</code>。</p>\n<figure><figcaption></figcaption></figure>\n<p>接着点击菜单中的 Find -&gt; Replace，在替换栏中输入子组的引用 <code>\\1</code> ，然后点击 Replace All 就可以完成替换工作了。</p>\n<figure><figcaption></figcaption></figure>\n<p>这样，通过少量的正则，我们就完成了文本的处理工作了。</p>\n<p>几乎所有主流编辑器都是支持正则的，你可以在你喜欢的编辑器中尝试一下这个例子，在后面的工作中，也可以尝试使用它来完成一些复杂的文本查找和替换工作。</p>\n<h2>6. 总结</h2>\n<p>好了，今天的内容讲完了，我来带你总结回顾一下。</p>\n<p>今天我们学习到了正则中的分组和子组编号相关内容。括号可以将某部分括起来，看成一个整体，也可以保存成一个子组，在后续查找替换的时候使用。分组编号是指，在正则中第几个括号内就是第几个分组，而嵌套括号我们只要看左括号是第几个就可以了。如果不想将括号里面的内容保存成子组，可以在括号里面加上<code>?:</code> 来解决。</p>\n<p>搞懂了分组的内容，我们就可以利用分组引用，来实现将“原文本部分内容”，在查找或替换时进行再次利用，达到实现复杂文本的查找和替换工作。甚至在使用一些文本编辑器的时候，不写代码，我们就可以完成文本的查找替换处理工作，这往往可以节约很多开发时间。</p>\n<figure><figcaption></figcaption></figure>\n<h2>7. 课后思考</h2>\n<p>最后，我们来做一个小练习吧。有一篇英文文章，里面有一些单词连续出现了多次，我们认为连续出现多次的单词应该是一次，比如：</p>\n<blockquote>\n<p>the little cat cat is in the hat hat hat, we like it.</p>\n</blockquote>\n<blockquote>\n<p>其中 cat 和 hat 连接出现多次，要求处理后结果是</p>\n</blockquote>\n<blockquote>\n<p>the little cat is in the hat, we like it.</p>\n</blockquote>\n<figure><figcaption></figcaption></figure>\n<p>这个题目我给出了相应的地址 <a href=\"https://regex101.com/r/2RVPTJ/3\" target=\"_blank\" rel=\"noopener noreferrer\">https://regex101.com/r/2RVPTJ/3</a>，你可以直接在网页上进行测试，写入相应的 “正则查找部分” 和 “正则替换部分”，让结果符合预期。多动手练习，你才能更好地掌握学习的内容。</p>\n<figure><figcaption></figcaption></figure>\n<p>好，今天的课程就结束了，希望可以帮助到你，也希望你在下方的留言区和我参与讨论。也欢迎把这篇文章分享给你的朋友或者同事，一起交流一下。</p>\n\n<details class=\"hint-container details\"><summary>公众号：AI悦创【二维码】</summary>\n<figure><img src=\"/gzh.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n</details>\n<div class=\"hint-container info\">\n<p class=\"hint-container-title\">AI悦创·编程一对一</p>\n<p>AI悦创·推出辅导班啦，包括「Python 语言辅导班、C++ 辅导班、java 辅导班、算法/数据结构辅导班、少儿编程、pygame 游戏开发、Web、Linux」，招收学员面向国内外，国外占 80%。全部都是一对一教学：一对一辅导 + 一对一答疑 + 布置作业 + 项目实践等。当然，还有线下线上摄影课程、Photoshop、Premiere 一对一教学、QQ、微信在线，随时响应！微信：Jiabcdefh</p>\n<p>C++ 信息奥赛题解，长期更新！长期招收一对一中小学信息奥赛集训，莆田、厦门地区有机会线下上门，其他地区线上。微信：Jiabcdefh</p>\n<p>方法一：<a href=\"http://wpa.qq.com/msgrd?v=3&amp;uin=1432803776&amp;site=qq&amp;menu=yes\" target=\"_blank\" rel=\"noopener noreferrer\">QQ</a></p>\n<p>方法二：微信：Jiabcdefh</p>\n</div>\n<figure><img src=\"/zsxq.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n",
      "date_published": "2025-09-29T11:00:50.000Z",
      "date_modified": "2025-10-16T00:46:46.000Z",
      "authors": [
        {
          "name": "bornforthis"
        }
      ],
      "tags": []
    },
    {
      "title": "Lab 8：Files & I/O and Dictionaries and sets",
      "url": "https://bornforthis.cn/1v1/101-Sallymisty/Lab/08-python-lab8-files-io-dictionaries-sets.html",
      "id": "https://bornforthis.cn/1v1/101-Sallymisty/Lab/08-python-lab8-files-io-dictionaries-sets.html",
      "summary": "1. Introduction The purpose of this week's lab is to: Practice working with dictionaries and sets. Examine the directory structure and file system on your computer, and understa...",
      "content_html": "<h2>1. Introduction</h2>\n<p>The purpose of this week's lab is to:</p>\n<ul>\n<li>Practice working with dictionaries and sets.</li>\n<li>Examine the directory structure and file system on your computer, and understand the concept of absolute and relative paths.</li>\n<li>Read text files in python.</li>\n</ul>\n<div class=\"hint-container info\">\n<p class=\"hint-container-title\">相关信息</p>\n<p>If you do not have time to finish all exercises (in particular, the programming problems) during the lab time, you can continue working on them later.</p>\n</div>\n<div class=\"hint-container info\">\n<p class=\"hint-container-title\">相关信息</p>\n<p>If you have any questions about or difficulties with any of the material in this lab, or any of the material covered in the course so far, ask your tutor for help during the lab.</p>\n</div>\n<h2>2. The File System</h2>\n<p>Files and directories are an abstraction provided by the operating system (OS) to make it easier for programmers and users to interact with the underlying storage device (hard drive, USB key, network file server, etc).</p>\n<p>In a unix system (like the one in the CSIT labs), or a system running MacOS, the file system is organised into a single directory tree. That means directories can contain several (sub-)directories (or none), but each directory has only one directory directly above it, the one that it is contained in. (This is often called the \"parent directory\".) The top-most directory in the tree, which is called <code>/</code>, has no parent directory. Every file is located in some directory.</p>\n<p>If you are working on a computer running Microsoft Windows, each \"drive\" will be the root of it's own directory tree. The topmost directory within a drive is the drive letter - followed by a ':', for example \"C:\". Within each drive, the parent/sub-directory structure is similar to a MacOS or Unix system, where each directory has a single parent directory, but can contain many sub-directories.</p>\n<h3>2.1 Exercise 0: Navigating the Directory Structure</h3>\n<div class=\"hint-container info\">\n<p class=\"hint-container-title\">相关信息</p>\n<p>Work through this exercise on your personal computer, or the lab computer.</p>\n</div>\n<p>For this exercise, you will need some directories and files to work with. On the lab computer or your personal device, create a directory called <code>comp1730</code> in your home directory (if you haven't already), and within that directory create one called <code>lab8</code>. You can do this using whichever tool you're familiar with (the command-line terminal or the graphical folders tool).</p>\n<p><strong>Next, create a file with a few lines of text (including some empty lines). You can use the editor in the IDE, or any other text editor, to write the file. (If you don't know what to write, just copy some text from this page.) Save your file with the name <code>sample.txt</code> in the <code>lab8</code> directory.</strong></p>\n<p>When you are done, you should have something like the following:</p>\n<figure><figcaption></figcaption></figure>\n<p>In the python3 shell, import the <code>os</code> module:</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">import</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> os</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div></div></div><p>This module provides several useful functions for interacting with the file system; in particular, it can let you know what the current working directory is, and change that. Try the following:</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: os.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">getcwd</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">Out [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'NNNNN'</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>The value returned will depend on your operating system and where you are running Python from. From here onwards, where we ask you to type \"NNNNN\" you should use whatever was returned in Out [2].</p>\n<p>If you are running Linux or MacOs try:</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: os.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">chdir</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'NNNNN/comp1730'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">4</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: os.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">getcwd</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">Out [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">4</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">...</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>Where \"NNNNN\" was the value returned in Out [2]</p>\n<p>If you are running Windows try:</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: os.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">chdir</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'NNNNN</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">\\\\</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">comp1730'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">4</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: os.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">getcwd</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">Out [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">4</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">...</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>Where again \"NNNNN\" was the value returned in Out [2]</p>\n<p>You should find that the current working directory is now <code>'NNNNN/comp1730'</code>. The <code>os.chdir</code> (\"change directory\") function changes it.</p>\n<p>The location given in the example above is <em>absolute</em>: it specifies the full path, from the top-level (\"root\") directory or drive. A <em>relative</em> path specifies a location in the directory structure relative to the current working directory. Try</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">5</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: os.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">chdir</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'lab8'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">6</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: os.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">getcwd</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">Out [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">6</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">...</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">7</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: os.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">chdir</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'..'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">8</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: os.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">getcwd</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">Out [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">8</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">...</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>The path <code>..</code> means \"the parent directory\". So, for example, if your current working directory is <code>NNNNN/comp1730/lab8</code> and you also have a <code>lab1</code> directory in <code>comp1730</code>, you can change to it with</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">os.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">chdir</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'../lab1'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div></div></div><p>Finally, the <code>os.listdir</code> function returns a list of the files and subdirectories in a given directory. If you have created the text file <code>sample.txt</code> (and nothing else) in <code>comp1730/lab8</code>, then</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">os.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">listdir</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'NNNNN/comp1730/lab8'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)  </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># Linux or MacOS</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">os.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">listdir</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'NNNNN</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">\\\\</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">comp1730</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">\\\\</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">lab8'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)  </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># Windows</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>should return <code>['sample.txt']</code>, while</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">os.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">listdir</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'..'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div></div></div><p>will return a list of the subdirectories and files in the parent of the current working directory.</p>\n<h3>2.2 Exercise 1: Reading Text Files</h3>\n<div class=\"hint-container info\">\n<p class=\"hint-container-title\">相关信息</p>\n<p>Work through this exercise on your personal computer, or the lab computer.</p>\n</div>\n<p><strong>Reading a text file.</strong></p>\n<p>To read the sample text file that you created in python, you can do the following:</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: fileobj </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> open</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"sample.txt\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"r\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: fileobj.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">readline</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">Out [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">...</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: fileobj.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">readline</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">Out [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">...</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>(This assumes the current working directory is where the file is located, i.e., <code>'NNNNN/comp1730/lab7'</code>. If not, you need to give the (absolute or relative) path to the file as the first argument to <code>open</code>.) You can keep repeating <code>fileobj.readline()</code> as many times as you wish. Notice that each call returns the next line in the file: the file object keeps track of the next point in the file to read from. When you get to the end of the file, <code>readline()</code> returns an empty string. Also notice that each line has a newline character (<code>'\\n'</code>) at the end, including empty lines in the file.</p>\n<p>When you are done reading the file (whether you have reached the end of it or not), you must always close it:</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">4</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: fileobj.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">close</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div></div></div><p><strong>Walking through the contents of the file with a <code>for</code> loop.</strong></p>\n<p>A more convenient way to iterate through the lines of a text file is using a <code>for</code> loop. The file object that is returned by the built-in function <code>open</code> is <em>iterable</em>, which means that you can use a for loop, like this:</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> line </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> my_file_obj:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">    # do something with the line</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>However, the file object is not a sequence, so you can't index it, or even ask for its length.</p>\n<p>Write a function that takes as argument the path to a file, reads the file and returns the number of non-empty lines in it. You should use a <code>for</code> loop to iterate through the file.</p>\n<p>Remember to <em>close the file</em> before the end of the function!</p>\n<h2>3. Dictionaries and sets</h2>\n<p>The <code>dict</code> type in python implements a <em>mapping</em>, which is also, in computer science, known as a <em>dictionary</em>, or sometimes an <em>associative container type</em> or <em>associative array</em>.</p>\n<ul>\n<li>A dictionary stores <em>key-value pairs</em>. Each key that is stored in the dictionary has exactly one associated value. The same value can be associated with several keys, but a key cannot have more (or less) than one value.</li>\n<li>Dictionaries are mutable objects; they can be modified by adding and removing keys, and replacing the value associated with a key.</li>\n<li>Keys must be immutable values (such as integers, strings or tuples).</li>\n<li>Keys in a dictionary do not all have to be of the same type. However, mixing key types in a dictionary will give rise to some limitations; for example, you will not be able to sort the keys.</li>\n<li>The values stored in a dictionary can be of any type, including mutable objects (or even other dictionaries).</li>\n<li>Given a key, it is easy to find out if the key is stored in the dictionary, and if so what is its value. The opposite - finding the key given a value - is not so easy (in computational terms).</li>\n<li>A dictionary is a collection, but it is NOT a sequence. Contrast this with lists and tuples, which are sequences. An implication of this is that saying \"the third element\" of a dictionary has no meaning. We  can \"index\" the elements of the dictionary, but we do this using the key.</li>\n<li>The operators <code>[]</code>, <code>len(.)</code> and <code>in</code> can be applied to dictionaries. Note that <code>x in adict</code> is <code>True</code> if <code>x</code> appears as a key in the dictionary; the <code>in</code> operator does not check if <code>x</code> appears as a value.</li>\n<li>Dictionaries have some additional methods. The most important are <code>items()</code>, <code>keys()</code> and <code>values()</code>, which allow iteration over the dictionary content.</li>\n</ul>\n<p>The <code>set</code> type in python implements the mathematical notion of a set.</p>\n<ul>\n<li>\n<p>A set is an unordered collection of values (called the elements or</p>\n<p>members of the set), without duplicates.</p>\n</li>\n<li>\n<p>A python <code>set</code> can contain objects of any immutable type, including a mixture of different types. Thus, lists cannot be elements of a set, but tuples can be.</p>\n</li>\n<li>\n<p>There is only one copy of any element in a set. If you add an element that appears already, it is not added again, but it will not result in a run-time error.</p>\n</li>\n<li>\n<p>There is no order to the elements of the set. The <code>set</code> type is iterable, but it is not a sequence (so it is not indexable).</p>\n</li>\n<li>\n<p>The <code>len()</code> and <code>in</code> operators can be applied to sets. The \"length\" of a set is the number of elements in it.</p>\n</li>\n<li>\n<p>Sets are mutable: methods <code>set.add(element)</code> and <code>set.remove(element)</code> can be used to modify a set.</p>\n</li>\n<li>\n<p>The binary operators <code>&amp;</code> (intersection), <code>|</code> (union), <code>-</code> (difference) and <code>^</code> (symmetric difference) can be applied to set; these return their result as a new set, without modifying the operands.</p>\n</li>\n</ul>\n<h3>3.1 Exercise 2: Dictionaries and Sets</h3>\n<p>You can create a dictionary by writing a comma-separated sequence of <code>key : value</code> pairs within curly brackets, <code>{</code> and <code>}</code>. You can similarly create a set by writing a comma-separated sequence of elements (without the <code>:</code> and associated value) in curly brackets. However, an empty pair of curly brackets creates an empty dictionary, not an empty set. Try the following:</p>\n<div class=\"language-python line-numbers-mode has-collapsed-lines collapsed\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--vp-collapsed-lines:15;--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: a </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> { </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> : </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'none'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> : </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'one'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> : </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'two'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> : </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'many'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> }</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">type</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(a)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">Out [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">...</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: b </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> { </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'one'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'two'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'many'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> }</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">4</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">type</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(b)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">Out [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">4</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">...</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">5</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: c </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {}</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">6</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">type</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(c)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">Out [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">6</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">...</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div><div class=\"collapsed-lines\"></div></div><p>Values stored in a dictionary are accessed by writing the key in square brackets. What is the output of the following?</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">7</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: a[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">] </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> \" hundred \"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> +</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> a[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">] </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> \" ten \"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> +</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> a[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">Out [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">7</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">...</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">8</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: a[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">7</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">] </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> \" ten \"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> +</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> a[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">Out [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">8</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">...</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>Trying to access the value of a key that is not in the dictionary causes an error.</p>\n<p>Dictionaries are mutable: you can add keys, change the value associated with a key already in the dictionary, and remove keys. Changing the value associated with a dictionary is done by assigning to the dictionary indexed with the key using the same syntax. Adding keys to a dictionary is done by simply assigning a value to the new key:</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">9</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: a</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">Out [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">9</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">...</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">10</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: a[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">] </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> 'three'</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">11</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: a[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">7</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">] </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> 'a lot of'</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">12</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: a</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">Out [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">12</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">...</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>Retry the two string expressions (inputs 7 and 8) above with the dictionary after reassigning the keys <code>3</code> and <code>7</code>.</p>\n<p>Keys themselves cannot be mutable however. The following examples work because tuples and strings are immutable.</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">13</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: a[(</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)] </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> 'one and two'</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">14</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: a[</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'lab'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">] </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 7</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>The following example with a list as key however will not, as lists are mutable.</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">15</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: a[[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]] </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> 'does not work'</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#ABB2BF\">TypeError</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: unhashable </span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">type</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'list'</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>Think about why mutable objects cannot be used as dictionary keys. Discuss with your tutor after you have had a think about it.</p>\n<h3>3.2 Exercise 3: Creating Dictionaries and Sets</h3>\n<p>Writing every key-value pair in a dictionary explicitly will quickly get tedious, so let's look at ways to create dictionaries programmatically (which is how you will use them most of the time anyway).</p>\n<p>You can create a dictionary from a list (or any sequence) of keys and a value expression, much like you can create a list using list comprehension. For example, copy the following statement into the python shell:</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">wordlist </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> [</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'test'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'your'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'function'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'with'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'a'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'diverse'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> 'range'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'of'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'examples'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'your'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'tests'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'should'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'cover'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> 'all'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'cases'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'for'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'example'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'test'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'words'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'beginning'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> 'with'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'a'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'vowel'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'and'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'word'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'beginning'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'with'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'a'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> 'consonant'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'pay'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'particular'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'attention'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'to'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'edge'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> 'cases'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'for'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'example'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'what'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'happens'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'if'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'the'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> 'word'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'consists'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'of'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'just'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'one'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'vowel'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'like'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> 'a'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'what'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'happens'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'if'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'the'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'string'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'is'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'empty'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>This sets <code>wordlist</code> to a list of strings. Now, the expression</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: wordlen </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> { word : </span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(word) </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> word </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> wordlist }</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div></div></div><p>creates a dictionary, called <code>wordlen</code> in which every word in the list is mapped to its length. To check that it has worked, print the dictionary, and look up some sample words.</p>\n<p>But wait! The list contains some words multiple times (for example, both \"for\" and \"example\" appear twice). Haven't we said that in a dictionary a key can only appear once? When you create a dictionary from an iterable (such as a sequence), key-value pairs are assigned in order. For example,</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: { </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'a'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> : </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'b'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> : </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'a'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> : </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> }</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">Out [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: {</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'a'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'b'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">}</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>That is, the second occurrence of the <code>'a'</code> in a pair in the list overwrites the first.</p>\n<p>In a similar way, you can create a set from any iterable collection of values (as long as all values are immutable). For example,</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: wordset </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> set</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(wordlist)</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div></div></div><p>creates a set of strings. Here also, duplicates in the list are ignored.</p>\n<h3>3.3 Exercise 4: Counting with Dictionaries</h3>\n<div class=\"hint-container info\">\n<p class=\"hint-container-title\">相关信息</p>\n<p>There are purposefully no tests for this exercise.</p>\n</div>\n<p>A very common use of a dictionary is to count things. The following function (from section \"Dictionary as a Collection of Counters\", Chapter 11, in Downey's book), creates a dictionary that maps values in a sequence (string, list, etc) to the number of times they appear.</p>\n<p>Run the python file and run the file so that you can test the function. You can test it on strings,</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">histogram</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"neverending\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">Out [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">...</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">histogram</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"mississippi\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">Out [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">...</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>on lists of numbers,</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">histogram</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">([</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">4</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">6</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">5</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">5</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">4</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">4</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">6</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">])</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">Out [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">...</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>on lists of strings,</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">4</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">histogram</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(wordlist)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">Out [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">4</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">...</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>and other sequences. What happens if you try</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">5</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">histogram</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">([[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">], [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">], [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">], [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">], [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]])</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div></div></div><p>Can you explain why this happens?</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> histogram</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">seq</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    \"\"\"</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    Given a sequence of values, return a dictionary counting</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    the number of times each value appears in the sequence.</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    Parameters</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div>",
      "date_published": "2025-09-28T19:44:09.000Z",
      "date_modified": "2025-09-30T09:02:13.000Z",
      "authors": [
        {
          "name": "bornforthis"
        }
      ],
      "tags": []
    },
    {
      "title": "Lab 7：NumPy arrays. (More) Data analysis.",
      "url": "https://bornforthis.cn/1v1/101-Sallymisty/Lab/07-lab7-numpy-arrays-data-analysis.html",
      "id": "https://bornforthis.cn/1v1/101-Sallymisty/Lab/07-lab7-numpy-arrays-data-analysis.html",
      "summary": "1. Introduction The purpose of this week's lab is to: Familiarise yourself with rank-1 (one-dimensional) and rank-2 (two-dimensional) NumPy arrays, and with the concept of vecto...",
      "content_html": "<h2>1. Introduction</h2>\n<p>The purpose of this week's lab is to:</p>\n<ul>\n<li>Familiarise yourself with rank-1 (one-dimensional) and rank-2 (two-dimensional) NumPy arrays, and with the concept of <strong>vectorisation</strong>.</li>\n<li>Practice more data analysis exercises. You will have to use the approach in Lecture 7 to solve these exercises, namely, to leverage the tools provided by the pandas library.</li>\n</ul>\n<div class=\"hint-container info\">\n<p class=\"hint-container-title\">相关信息</p>\n<p>If you do not have time to finish all exercises (in particular, the programming problems) during the lab time, you can continue working on them later.</p>\n</div>\n<div class=\"hint-container info\">\n<p class=\"hint-container-title\">相关信息</p>\n<p>If you have any questions about or difficulties with any of the material in this lab, or any of the material covered in the course so far, ask your tutor for help during the lab.</p>\n</div>\n<h2>2. NumPy arrays</h2>\n<p>As we saw in last week's lecture, <strong>arrays</strong> are provided by the external library NumPy, which stands for \"Numerical Python''. <a href=\"https://numpy.org/\" target=\"_blank\" rel=\"noopener noreferrer\">NumPy</a> is a vast library with many features that are very useful for writing scientific programs. In this course (and this lab), we restrict ourselves to a small subset of this functionality. In any case, probably the next most natural (and less steep) step to explore more about this functionality is <a href=\"https://numpy.org/doc/stable/user/absolute_beginners.html\" target=\"_blank\" rel=\"noopener noreferrer\">this tutorial</a> from the NumPy documentation.</p>\n<h2>3. Rank-1 (one-dimensional) arrays</h2>\n<p>Arrays are sequence types. In contrast to lists, all of its elements are <strong>ALWAYS</strong> of the same type (e.g., <code>int</code>s or <code>float</code>s).</p>\n<p>Let us start working with rank-1 arrays, also known as 1-dimensional arrays or simply vectors.</p>\n<p>Recall that the defining property of rank-1 array is that you only have to use one index to access to its entries (as with lists or strings).</p>\n<h3>3.1 Warm-up exercise on rank-1 arrays</h3>\n<p>The first thing to do when working with NumPy arrays is to import the <code>numpy</code> module. The de-facto practice (i.e., you will observe many programs doing this) is to rename it as <code>np</code> when importing:</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">import</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> numpy </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">as</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> np</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div></div></div><p>Before working with a rank-1 array, one has to generate (create) it. NumPy offers many different ways to generate rank-1 arrays. The function calls below show some examples of these. Run the following in a Python shell and try to understand what each function call does:</p>\n<div class=\"language-python line-numbers-mode has-collapsed-lines collapsed\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--vp-collapsed-lines:15;--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">import</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> numpy </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">as</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> np</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: x </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> np.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">array</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">([</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0.0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0.25</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0.5</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0.75</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1.0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">])</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: x</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">Out[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">array</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">([</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.  , </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0.25</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0.5</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> , </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0.75</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.  ])</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">4</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">type</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(x) </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># what type of sequence is this?</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">Out[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">4</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">...</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">4</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: y </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> np.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">zeros</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">5</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">5</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: y</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">Out[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">5</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">...</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">6</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: z </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> np.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">linspace</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0.0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">10.0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">5</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">7</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: z</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">Out[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">7</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">...</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">8</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: t </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> np.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">arange</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0.0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">5.0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0.5</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">8</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: t</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">Out[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">8</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">...</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div><div class=\"collapsed-lines\"></div></div><p>As always, you can check the docstrings of these functions (e.g., <code>help(np.zeros)</code> in the Python shell) to find more about these.</p>\n<p>Recall that arrays are sequence types. Thus, once the rank-1 array is established, we can set and retrieve individual values, and extract slices, as with lists or strings. We can also iterate over the entries using loops. Run the following in the Python shell to convince yourself that this is indeed true:</p>\n<div class=\"language-python line-numbers-mode has-collapsed-lines collapsed\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--vp-collapsed-lines:15;--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">import</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> numpy </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">as</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> np</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: y </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> np.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">zeros</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">4</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: y[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">] </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 0.0</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">4</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: y[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">] </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 0.01</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">5</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: y[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">] </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 0.02</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">6</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: y[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">] </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 0.03</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">7</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: y</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">Out[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">7</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">...</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">8</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: y[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">Out[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">8</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">...</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">9</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: y[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">Out[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">9</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">...</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">10</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: y[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">Out[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">10</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">...</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">11</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> elem </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> y:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">             print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(elem)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">Out[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">11</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">...</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">12</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> i </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> range</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(y)):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">             print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(y[i])</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">Out[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">12</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">...</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div><div class=\"collapsed-lines\"></div></div><p>An important feature of NumPy is that code written in terms of arrays might be <strong>vectorised</strong>. That is, rewritten/transformed in terms of <strong>operations on entire arrays at once</strong> (without Python loops). Vectorised code can run much faster than non-vectorised code, especially with large arrays, as we saw in the lecture.</p>\n<p>Execute the <strong>vectorised</strong> operations below in a Python shell and figure out what they are returning:</p>\n<div class=\"language-python line-numbers-mode has-collapsed-lines collapsed\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--vp-collapsed-lines:15;--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">import</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> numpy </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">as</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> np</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">import</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> math</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> double</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">x</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">             return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> x</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">*</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">4</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: x </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> np.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">linspace</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0.0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">*</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">math.pi, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">10</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">5</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: x </span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">Out[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">5</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">...</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">6</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: x</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">10</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> </span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">Out[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">6</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">...</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">7</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: x</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">**</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> </span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">Out[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">7</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">...</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">8</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: np.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">sin</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(x) </span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">Out[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">8</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">...</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">9</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: math.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">sin</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(x) </span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">Out[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">9</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">...</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">10</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">double</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(x) </span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">Out[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">10</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">...</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div><div class=\"collapsed-lines\"></div></div><h3>3.2 Exercise 1: Plotting a function</h3>\n<p>Given the mathematical function:</p>\n<p v-pre=\"\" class=\"katex-block\"><span class=\"katex-display\"><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\" display=\"block\"><semantics><mrow><mi>h</mi><mo stretchy=\"false\">(</mo><mi>x</mi><mo stretchy=\"false\">)</mo><mo>=</mo><mfrac><mn>1</mn><msqrt><mrow><mn>2</mn><mi>π</mi></mrow></msqrt></mfrac><msup><mi>e</mi><mrow><mo>−</mo><mstyle displaystyle=\"false\" scriptlevel=\"0\"><mfrac><mn>1</mn><mn>2</mn></mfrac></mstyle><msup><mi>x</mi><mn>2</mn></msup></mrow></msup></mrow><annotation encoding=\"application/x-tex\">h(x) = \\frac{1}{\\sqrt{2\\pi}} e^{-\\tfrac{1}{2}x^2}\n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">h</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">x</span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:2.2514em;vertical-align:-0.93em;\"></span><span class=\"mord\"><span class=\"mopen nulldelimiter\"></span><span class=\"mfrac\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:1.3214em;\"><span style=\"top:-2.2028em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"mord\"><span class=\"mord sqrt\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.9072em;\"><span class=\"svg-align\" style=\"top:-3em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"mord\" style=\"padding-left:0.833em;\"><span class=\"mord\">2</span><span class=\"mord mathnormal\" style=\"margin-right:0.03588em;\">π</span></span></span><span style=\"top:-2.8672em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"hide-tail\" style=\"min-width:0.853em;height:1.08em;\"><svg xmlns=\"http://www.w3.org/2000/svg\" width=\"400em\" height=\"1.08em\" viewBox=\"0 0 400000 1080\" preserveAspectRatio=\"xMinYMin slice\"><path d=\"M95,702\nc-2.7,0,-7.17,-2.7,-13.5,-8c-5.8,-5.3,-9.5,-10,-9.5,-14\nc0,-2,0.3,-3.3,1,-4c1.3,-2.7,23.83,-20.7,67.5,-54\nc44.2,-33.3,65.8,-50.3,66.5,-51c1.3,-1.3,3,-2,5,-2c4.7,0,8.7,3.3,12,10\ns173,378,173,378c0.7,0,35.3,-71,104,-213c68.7,-142,137.5,-285,206.5,-429\nc69,-144,104.5,-217.7,106.5,-221\nl0 -0\nc5.3,-9.3,12,-14,20,-14\nH400000v40H845.2724\ns-225.272,467,-225.272,467s-235,486,-235,486c-2.7,4.7,-9,7,-19,7\nc-6,0,-10,-1,-12,-3s-194,-422,-194,-422s-65,47,-65,47z\nM834 80h400000v40h-400000z\"></path></svg></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.1328em;\"><span></span></span></span></span></span></span></span><span style=\"top:-3.23em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"frac-line\" style=\"border-bottom-width:0.04em;\"></span></span><span style=\"top:-3.677em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"mord\"><span class=\"mord\">1</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.93em;\"><span></span></span></span></span></span><span class=\"mclose nulldelimiter\"></span></span><span class=\"mord\"><span class=\"mord mathnormal\">e</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:1.0369em;\"><span style=\"top:-3.413em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mtight\">−</span><span class=\"mord mtight\"><span class=\"mopen nulldelimiter sizing reset-size3 size6\"></span><span class=\"mfrac\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8443em;\"><span style=\"top:-2.656em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"sizing reset-size3 size1 mtight\"><span class=\"mord mtight\"><span class=\"mord mtight\">2</span></span></span></span><span style=\"top:-3.2255em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"frac-line mtight\" style=\"border-bottom-width:0.049em;\"></span></span><span style=\"top:-3.384em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"sizing reset-size3 size1 mtight\"><span class=\"mord mtight\"><span class=\"mord mtight\">1</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.344em;\"><span></span></span></span></span></span><span class=\"mclose nulldelimiter sizing reset-size3 size6\"></span></span><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">x</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8913em;\"><span style=\"top:-2.931em;margin-right:0.0714em;\"><span class=\"pstrut\" style=\"height:2.5em;\"></span><span class=\"sizing reset-size3 size1 mtight\"><span class=\"mord mtight\">2</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></p>\n<p>You are asked to solve the following tasks.</p>\n<p><strong>Task 1: Scalar function evaluations.</strong> Write a function <code>evaluate_h(a,b,N)</code> that returns two rank-1 arrays of <code>float</code>s named, say, <code>x</code> and <code>y</code>. The array <code>x</code> holds x<em>x</em> values obtained from splitting the interval <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mo stretchy=\"false\">[</mo><mi>a</mi><mo separator=\"true\">,</mo><mi>b</mi><mo stretchy=\"false\">]</mo></mrow><annotation encoding=\"application/x-tex\">[a,b]</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mopen\">[</span><span class=\"mord mathnormal\">a</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord mathnormal\">b</span><span class=\"mclose\">]</span></span></span></span> into <code>N&gt;1</code> equispaced points. For example, if <code>a=0</code>, <code>b=10</code>, and <code>N=5</code>, then <code>x</code> must have the values <code>0.0</code>, <code>2.5</code>, <code>5.0</code>, <code>7.5</code>, and <code>10.0</code>, in this order. On the other hand, the array <code>y</code> holds <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>h</mi><mo stretchy=\"false\">(</mo><mi>x</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">h(x)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">h</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">x</span><span class=\"mclose\">)</span></span></span></span> evaluations at the corresponding values of the array <code>x</code>. The function MUST first create two rank-1 arrays of the appropriate size, and then fill them by computing each element, element by element, with a <code>for</code> loop.</p>\n<div class=\"hint-container info\">\n<p class=\"hint-container-title\">相关信息</p>\n<p><strong>Hint</strong>: the distance among two consecutive <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>x</mi></mrow><annotation encoding=\"application/x-tex\">x</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.4306em;\"></span><span class=\"mord mathnormal\">x</span></span></span></span> values in the <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mo stretchy=\"false\">[</mo><mi>a</mi><mo separator=\"true\">,</mo><mi>b</mi><mo stretchy=\"false\">]</mo></mrow><annotation encoding=\"application/x-tex\">[a, b]</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mopen\">[</span><span class=\"mord mathnormal\">a</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord mathnormal\">b</span><span class=\"mclose\">]</span></span></span></span> interval is given by</p>\n<p v-pre=\"\" class=\"katex-block\"><span class=\"katex-display\"><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\" display=\"block\"><semantics><mrow><mfrac><mrow><mi>b</mi><mo>−</mo><mi>a</mi></mrow><mrow><mi>N</mi><mo>−</mo><mn>1</mn></mrow></mfrac></mrow><annotation encoding=\"application/x-tex\">\\frac{b - a}{N - 1}\n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:2.1408em;vertical-align:-0.7693em;\"></span><span class=\"mord\"><span class=\"mopen nulldelimiter\"></span><span class=\"mfrac\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:1.3714em;\"><span style=\"top:-2.314em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.10903em;\">N</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">−</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mord\">1</span></span></span><span style=\"top:-3.23em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"frac-line\" style=\"border-bottom-width:0.04em;\"></span></span><span style=\"top:-3.677em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">b</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">−</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mord mathnormal\">a</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.7693em;\"><span></span></span></span></span></span><span class=\"mclose nulldelimiter\"></span></span></span></span></span></span></p>\n<p>(Think why!)</p>\n</div>\n<p><strong>Task 2: Vectorised function evaluations.</strong> Write a version of the previous function, <code>evaluate_h_vectorized(a,b,N)</code>, that vectorises <code>evaluate_h(a,b,N)</code>. This function must <strong>not</strong> use Python loops. To this end, you can use the <code>linspace</code> or <code>arange</code> functions from <code>numpy</code> to create the entries of the <code>x</code> array, and evaluate <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>h</mi><mo stretchy=\"false\">(</mo><mi>x</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">h(x)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">h</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">x</span><span class=\"mclose\">)</span></span></span></span> for an array argument to create the corresponding ones of <code>y</code> (as we showed in the lecture).</p>\n<p><strong>Task 3:</strong> <strong>Compare performance (i.e., time to solve the problem).</strong> Using the <code>%timeit</code> IPython shell magic command (as shown in the lecture code examples), compare the performance of the functions written in Task 1 versus Task 2 with increasing powers of 10 for <code>N</code>, e.g., 1010, 102102, ……, 106106. Accordingly to your measurements, which one is faster?</p>\n<div class=\"hint-container warning\">\n<p class=\"hint-container-title\">注意</p>\n<p><em>Please note that Task 3 will NOT be auto-tested, so please contact your tutor if you struggle while trying to solve this.</em></p>\n</div>\n<p><strong>Task 4:</strong> <strong>Write a function to generate a plot.</strong> Write a function, <code>plot_h(filename, a, b, N)</code>, with <code>filename</code> being a string, that generates an image called <code>filename</code> with a plot of <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>h</mi><mo stretchy=\"false\">(</mo><mi>x</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">h(x)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">h</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">x</span><span class=\"mclose\">)</span></span></span></span> within the interval [a,b][<em>a</em>,<em>b</em>]. It can use any of the two functions written in Task 1 and Task 2.  In order to generate the image with the plot, you can use the <code>matplotlib</code> library. If <code>x</code> and <code>y</code> are two rank-1 arrays produced by the functions written in 1(a) and 1(b), then you can use the following code to plot the function:</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">import</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> matplotlib.pyplot </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">as</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> plt</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">...</span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"> # generate x and y rank-1 arrays</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">plt.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">figure</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">plt.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">plot</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(x,y)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">plt.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">grid</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">plt.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">savefig</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(filename)</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>Note that the <code>plt.grid()</code> function call shows a grid of vertical and horizontal lines on the plot on certain x- and y-values, respectively. In general, grids are used to help you to interpret the quantitative values in a graph.</p>\n<p>Using the <code>plot_h</code> function, visualize the function <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>h</mi><mo stretchy=\"false\">(</mo><mi>x</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">h(x)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">h</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">x</span><span class=\"mclose\">)</span></span></span></span> using increasing values of  <code>N</code> in the interval <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mo stretchy=\"false\">[</mo><mo>−</mo><mn>4</mn><mo separator=\"true\">,</mo><mn>4</mn><mo stretchy=\"false\">]</mo></mrow><annotation encoding=\"application/x-tex\">[−4,4]</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mopen\">[</span><span class=\"mord\">−</span><span class=\"mord\">4</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord\">4</span><span class=\"mclose\">]</span></span></span></span>. For example, you can use <code>plot_h(\"h_5_points.png\",-4,4,5)</code>, <code>plot_h(\"h_10_points.png\",-4,4,10)</code>, <code>plot_h(\"h_20_points.png\",-4,4,20)</code>, <code>plot_h(\"h_40_points.png\",-4,4,40)</code>, etc. Can you find a value of <code>N</code> beyond which the plot does not apparently change to your eye when you increase <code>N</code>?</p>\n\n<figure><figcaption></figcaption></figure>\n<h2>4. Rank-2 arrays</h2>\n<p>Rank-2 arrays can be thought of as tables of numbers (also known as \"matrices\" by mathematicians). They are indexed using two indices, one for the rows, and another one for the columns.</p>\n<h3>4.1 Warm-up exercise on rank-2 arrays</h3>\n<p>As with rank-1 arrays, there are many ways one can create a rank-2 array. Two possible ways are:</p>\n<ul>\n<li>\n<p>By converting a list of lists (a.k.a. nested list) into a rank-2 array:</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">    &gt;&gt;&gt;</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> import</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> numpy </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">as</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> np</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">    &gt;&gt;&gt;</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> A </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> np.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">array</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">([[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1.0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2.0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3.0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">], [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">4.0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">5.0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">6.0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]])</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">    &gt;&gt;&gt;</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> A </span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">    &gt;&gt;&gt;</span><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\"> ...</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div></li>\n<li>\n<p>By providing the <strong>shape</strong> of the rank-2 array to the <code>zeros</code> function:</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">    &gt;&gt;&gt;</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> A </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> np.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">zeros</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">((</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">))</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">    &gt;&gt;&gt;</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> A</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">    &gt;&gt;&gt;</span><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\"> ...</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div></li>\n</ul>\n<p>Recall from the lecture that the shape of a rank-2 array is a tuple with the number of elements in each dimension. Here we have 2 rows and 3 columns.</p>\n<p>Once created, the shape of an array can be queried like this:</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&gt;&gt;&gt;</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> A.shape</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&gt;&gt;&gt;</span><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\"> ...</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>A word of caution in regards to shapes. The shape of a rank-1 array with <code>n</code> elements is the tuple <code>(n,)</code>. On the other hand, rank-2 arrays might have only one element in some (or all) the dimensions. Even in this case, <strong>they are still rank-2 arrays.</strong> Execute the following instructions to double check this:</p>\n<div class=\"language-python line-numbers-mode has-collapsed-lines collapsed\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--vp-collapsed-lines:15;--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&gt;&gt;&gt;</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> import</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> numpy </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">as</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> np</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&gt;&gt;&gt;</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> x</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">np.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">zeros</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">((</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,))</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&gt;&gt;&gt;</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> x.shape</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">...</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&gt;&gt;&gt;</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> y</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">np.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">zeros</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">((</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">))</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&gt;&gt;&gt;</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> y.shape </span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&gt;&gt;&gt;</span><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\"> ...</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&gt;&gt;&gt;</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> z</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">np.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">zeros</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">((</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">))</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&gt;&gt;&gt;</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> z.shape </span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&gt;&gt;&gt;</span><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\"> ...</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&gt;&gt;&gt;</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> t</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">np.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">zeros</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">((</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">))</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&gt;&gt;&gt;</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> t.shape </span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&gt;&gt;&gt;</span><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\"> ...</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div><div class=\"collapsed-lines\"></div></div><p>Once created, the individual entries of a rank-2 array can be accessed using <code>A[i][j]</code> or <code>A[i,j]</code>, where <code>i</code> and <code>j</code> denote the row and column identifiers of the corresponding entry of <code>A</code>. One can also use slicing in the column dimension (e.g., <code>A[i,:]</code> returns the row <code>i</code> of <code>A</code> as a rank-1 array), in the row dimension (e.g., <code>A[:,j]</code> returns the column <code>j</code> of <code>A</code> as a rank-1 array), or both dimensions (e.g., <code>A[0:2,1:3]</code> returns a rank-2 array with the entries in [rows 0 or 1] <strong>and</strong> [columns 1 or 2]).</p>\n<p><strong>An important difference among lists and arrays</strong> is that array slices create a \"view\" of the original array, instead of a shallow copy (as we showed in the lectures). This means that if you modify an array view, you will be actually modifying the original array the view was created from. Execute the following Python statements and expressions, and convince yourself that this is the case:</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&gt;&gt;&gt;</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> import</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> numpy </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">as</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> np</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&gt;&gt;&gt;</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> A </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> np.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">array</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">([[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1.0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2.0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3.0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">], [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">4.0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">5.0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">6.0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]])</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&gt;&gt;&gt;</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> A </span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&gt;&gt;&gt;</span><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\"> ...</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&gt;&gt;&gt;</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> A[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,:]</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">np.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">array</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">([</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">12.3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">44.5</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">22.3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">])</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&gt;&gt;&gt;</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> A </span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&gt;&gt;&gt;</span><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\"> ...</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&gt;&gt;&gt;</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> A[:,</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">A[:,</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&gt;&gt;&gt;</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> A </span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&gt;&gt;&gt;</span><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\"> ...</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&gt;&gt;&gt;</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> A[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,:]</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">A[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,:]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&gt;&gt;&gt;</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> A </span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&gt;&gt;&gt;</span><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\"> ...</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><h3>4.2 Exercise 2: Apply a function to a rank-2 array</h3>\n<p><strong>Task 1.</strong> Write a function, <code>evaluate_function(function, A)</code> that given a function <code>function</code>, and a rank-2 array <code>A</code>, applies the function to each entry of <code>A</code>, element by element, and stores the result in another array <code>B</code> of the same shape as <code>A</code>.  The function returns the array <code>B</code>. The function MUST use a nested loop to access the individual entries of <code>A</code> and <code>B</code>.</p>\n<p><strong>Task 2.</strong> Write a vectorised version of the previous function, <code>evaluate_function_vectorized(function, A)</code> that applies <code>function</code> to <code>A</code> to generate the array <code>B</code> without using any loop.</p>\n<p><strong>Task 3.</strong> Write code to check that the result of the two functions (e.g., non-vectorised versus vectorised) is the same as the following two-dimensional array:</p>\n<p v-pre=\"\" class=\"katex-block\"><span class=\"katex-display\"><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\" display=\"block\"><semantics><mrow><mo fence=\"true\">[</mo><mtable rowspacing=\"0.16em\" columnalign=\"center center center center\" columnspacing=\"1em\"><mtr><mtd><mstyle scriptlevel=\"0\" displaystyle=\"false\"><mn>0.2</mn></mstyle></mtd><mtd><mstyle scriptlevel=\"0\" displaystyle=\"false\"><mn>12.4</mn></mstyle></mtd><mtd><mstyle scriptlevel=\"0\" displaystyle=\"false\"><mrow><mo>−</mo><mn>1.0</mn></mrow></mstyle></mtd><mtd><mstyle scriptlevel=\"0\" displaystyle=\"false\"><mn>5.78</mn></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel=\"0\" displaystyle=\"false\"><mrow><mo>−</mo><mn>1.34</mn></mrow></mstyle></mtd><mtd><mstyle scriptlevel=\"0\" displaystyle=\"false\"><mrow><mo>−</mo><mn>1.5</mn></mrow></mstyle></mtd><mtd><mstyle scriptlevel=\"0\" displaystyle=\"false\"><mrow><mo>−</mo><mn>1.5</mn></mrow></mstyle></mtd><mtd><mstyle scriptlevel=\"0\" displaystyle=\"false\"><mn>0.1</mn></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel=\"0\" displaystyle=\"false\"><mn>1.43</mn></mstyle></mtd><mtd><mstyle scriptlevel=\"0\" displaystyle=\"false\"><mn>5.23</mn></mstyle></mtd><mtd><mstyle scriptlevel=\"0\" displaystyle=\"false\"><mn>5.45</mn></mstyle></mtd><mtd><mstyle scriptlevel=\"0\" displaystyle=\"false\"><mrow><mo>−</mo><mn>2.23</mn></mrow></mstyle></mtd></mtr></mtable><mo fence=\"true\">]</mo></mrow><annotation encoding=\"application/x-tex\">\\begin{bmatrix}\n0.2 &amp; 12.4 &amp; -1.0 &amp; 5.78 \\\\\n-1.34 &amp; -1.5 &amp; -1.5 &amp; 0.1 \\\\\n1.43 &amp; 5.23 &amp; 5.45 &amp; -2.23\n\\end{bmatrix}\n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:3.6em;vertical-align:-1.55em;\"></span><span class=\"minner\"><span class=\"mopen\"><span class=\"delimsizing mult\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:2.05em;\"><span style=\"top:-4.05em;\"><span class=\"pstrut\" style=\"height:5.6em;\"></span><span style=\"width:0.667em;height:3.600em;\"><svg xmlns=\"http://www.w3.org/2000/svg\" width=\"0.667em\" height=\"3.600em\" viewBox=\"0 0 667 3600\"><path d=\"M403 1759 V84 H666 V0 H319 V1759 v0 v1759 h347 v-84\nH403z M403 1759 V0 H319 V1759 v0 v1759 h84z\"></path></svg></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:1.55em;\"><span></span></span></span></span></span></span><span class=\"mord\"><span class=\"mtable\"><span class=\"col-align-c\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:2.05em;\"><span style=\"top:-4.21em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"mord\"><span class=\"mord\">0.2</span></span></span><span style=\"top:-3.01em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"mord\"><span class=\"mord\">−</span><span class=\"mord\">1.34</span></span></span><span style=\"top:-1.81em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"mord\"><span class=\"mord\">1.43</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:1.55em;\"><span></span></span></span></span></span><span class=\"arraycolsep\" style=\"width:0.5em;\"></span><span class=\"arraycolsep\" style=\"width:0.5em;\"></span><span class=\"col-align-c\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:2.05em;\"><span style=\"top:-4.21em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"mord\"><span class=\"mord\">12.4</span></span></span><span style=\"top:-3.01em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"mord\"><span class=\"mord\">−</span><span class=\"mord\">1.5</span></span></span><span style=\"top:-1.81em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"mord\"><span class=\"mord\">5.23</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:1.55em;\"><span></span></span></span></span></span><span class=\"arraycolsep\" style=\"width:0.5em;\"></span><span class=\"arraycolsep\" style=\"width:0.5em;\"></span><span class=\"col-align-c\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:2.05em;\"><span style=\"top:-4.21em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"mord\"><span class=\"mord\">−</span><span class=\"mord\">1.0</span></span></span><span style=\"top:-3.01em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"mord\"><span class=\"mord\">−</span><span class=\"mord\">1.5</span></span></span><span style=\"top:-1.81em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"mord\"><span class=\"mord\">5.45</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:1.55em;\"><span></span></span></span></span></span><span class=\"arraycolsep\" style=\"width:0.5em;\"></span><span class=\"arraycolsep\" style=\"width:0.5em;\"></span><span class=\"col-align-c\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:2.05em;\"><span style=\"top:-4.21em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"mord\"><span class=\"mord\">5.78</span></span></span><span style=\"top:-3.01em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"mord\"><span class=\"mord\">0.1</span></span></span><span style=\"top:-1.81em;\"><span class=\"pstrut\" style=\"height:3em;\"></span><span class=\"mord\"><span class=\"mord\">−</span><span class=\"mord\">2.23</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:1.55em;\"><span></span></span></span></span></span></span></span><span class=\"mclose\"><span class=\"delimsizing mult\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:2.05em;\"><span style=\"top:-4.05em;\"><span class=\"pstrut\" style=\"height:5.6em;\"></span><span style=\"width:0.667em;height:3.600em;\"><svg xmlns=\"http://www.w3.org/2000/svg\" width=\"0.667em\" height=\"3.600em\" viewBox=\"0 0 667 3600\"><path d=\"M347 1759 V0 H0 V84 H263 V1759 v0 v1759 H0 v84 H347z\nM347 1759 V0 H263 V1759 v0 v1759 h84z\"></path></svg></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:1.55em;\"><span></span></span></span></span></span></span></span></span></span></span></span></p>\n<div class=\"hint-container warning\">\n<p class=\"hint-container-title\">注意</p>\n<p><em>Please note that Task 3 will NOT be auto-tested, so please contact your tutor if you struggle while trying to solve this task.</em></p>\n</div>\n\n<figure><figcaption></figcaption></figure>\n<h2>5. Data analysis with CSV files and pandas</h2>\n<p>As we saw in week 6 lecture, data analysis problems will typically require you to:</p>\n<ul>\n<li>read data from one or more files;</li>\n<li>organise the data into a table; and</li>\n<li>process the elements in the table while dealing with entries in the table where some data might be missing.</li>\n</ul>\n<p>As we covered in Lecture 7, the pandas library provides a set of convenient tools to implement these tasks.</p>\n<p>For example, reading a CSV file into a so-called pandas <code>DataFrame</code> is as simple as:</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">import</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> pandas </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">as</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> pd</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">covid_data </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> pd.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">read_csv</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"03-25-2022.csv\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>Once you have imported the CSV file into a <code>DataFrame</code>, you can do many different operations with it.</p>\n<p>See Lecture 7 slides and accompanying code examples for more details.</p>\n<h2>6. Programming problems</h2>\n<p>In the rest of the lab, you will have to solve three more advanced programming problems. We don't expect everyone to finish all these problems during the lab time. If you do not have time to finish them in the lab, you should continue working on them later.</p>\n<h3>6.1 Programming problem 1: Computing the diagonality of a matrix</h3>\n<p>A <strong>diagonal matrix</strong> is a <strong>square</strong> table of numbers such that only elements on the diagonal are non-zero. <strong>Square</strong> means that it has the same number of rows as columns. If we call this matrix <code>M</code>, then the elements on the <strong>diagonal</strong> are those where row index equals column index, that is, <code>M[i,i]</code>.</p>\n<p>This property can be generalised to the concept of <strong>diagonality</strong>.A matrix <strong>M</strong> has diagonality <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>d</mi></mrow><annotation encoding=\"application/x-tex\">d</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6944em;\"></span><span class=\"mord mathnormal\">d</span></span></span></span> if <code>M[i,j] != 0</code> only in positions such that the absolute difference between <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>i</mi></mrow><annotation encoding=\"application/x-tex\">i</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6595em;\"></span><span class=\"mord mathnormal\">i</span></span></span></span> and <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>j</mi></mrow><annotation encoding=\"application/x-tex\">j</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.854em;vertical-align:-0.1944em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05724em;\">j</span></span></span></span> is strictly less than <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>d</mi></mrow><annotation encoding=\"application/x-tex\">d</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6944em;\"></span><span class=\"mord mathnormal\">d</span></span></span></span>, i.e.,</p>\n<p v-pre=\"\" class=\"katex-block\"><span class=\"katex-display\"><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\" display=\"block\"><semantics><mrow><mi mathvariant=\"normal\">∣</mi><mi>i</mi><mo>−</mo><mi>j</mi><mi mathvariant=\"normal\">∣</mi><mo>&lt;</mo><mi>d</mi></mrow><annotation encoding=\"application/x-tex\">|i - j| &lt; d\n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord\">∣</span><span class=\"mord mathnormal\">i</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">−</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05724em;\">j</span><span class=\"mord\">∣</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">&lt;</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6944em;\"></span><span class=\"mord mathnormal\">d</span></span></span></span></span></p>\n<p>In other words, <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>d</mi></mrow><annotation encoding=\"application/x-tex\">d</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6944em;\"></span><span class=\"mord mathnormal\">d</span></span></span></span> is equivalent to the maximum <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi mathvariant=\"normal\">∣</mi><mi>i</mi><mo>−</mo><mi>j</mi><mi mathvariant=\"normal\">∣</mi></mrow><annotation encoding=\"application/x-tex\">|i - j|</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord\">∣</span><span class=\"mord mathnormal\">i</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">−</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05724em;\">j</span><span class=\"mord\">∣</span></span></span></span> among all nonzero elements plus one.</p>\n<p>To-think: According to this general definition of diagonality, what would be the diagonality of a diagonal matrix?</p>\n<p>For example, this matrix has diagonality <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>d</mi><mo>=</mo><mn>3</mn></mrow><annotation encoding=\"application/x-tex\">d=3</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6944em;\"></span><span class=\"mord mathnormal\">d</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6444em;\"></span><span class=\"mord\">3</span></span></span></span> (Think why!):<br>\n[<br>\n\\begin{bmatrix}<br>\n1 &amp; 2 &amp; 3 &amp; 0 &amp; 0 &amp; 0 &amp; 0 &amp; 0 &amp; 0 &amp; 0 \\<br>\n4 &amp; 5 &amp; 6 &amp; 0 &amp; 0 &amp; 0 &amp; 0 &amp; 0 &amp; 0 &amp; 0 \\<br>\n7 &amp; 8 &amp; 9 &amp; 0 &amp; 0 &amp; 0 &amp; 0 &amp; 0 &amp; 0 &amp; 0 \\<br>\n0 &amp; 0 &amp; 0 &amp; 1 &amp; 2 &amp; 0 &amp; 0 &amp; 0 &amp; 0 &amp; 0 \\<br>\n0 &amp; 0 &amp; 0 &amp; 3 &amp; 4 &amp; 0 &amp; 0 &amp; 0 &amp; 0 &amp; 0 \\<br>\n0 &amp; 0 &amp; 0 &amp; 0 &amp; 0 &amp; 1 &amp; 2 &amp; 3 &amp; 0 &amp; 0 \\<br>\n0 &amp; 0 &amp; 0 &amp; 0 &amp; 0 &amp; 4 &amp; 5 &amp; 6 &amp; 0 &amp; 0 \\<br>\n0 &amp; 0 &amp; 0 &amp; 0 &amp; 0 &amp; 0 &amp; 0 &amp; 0 &amp; 1 &amp; 2 \\<br>\n0 &amp; 0 &amp; 0 &amp; 0 &amp; 0 &amp; 0 &amp; 0 &amp; 0 &amp; 3 &amp; 4 \\<br>\n0 &amp; 0 &amp; 0 &amp; 0 &amp; 0 &amp; 0 &amp; 0 &amp; 0 &amp; 5 &amp; 6 \\<br>\n\\end{bmatrix}<br>\n]<br>\nWrite a function <code>diagonality(matrix)</code> which takes as argument a matrix (represented as a rank-2 NumPy array) and returns the smallest d<em>d</em> such that <code>matrix</code> has diagonality <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>d</mi></mrow><annotation encoding=\"application/x-tex\">d</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6944em;\"></span><span class=\"mord mathnormal\">d</span></span></span></span>.</p>\n<div class=\"hint-container info\">\n<p class=\"hint-container-title\">相关信息</p>\n<p>Hint: the <code>diag</code> numpy function may help you out our solving this problem. In any case, it can be solved without that function.</p>\n</div>\n\n<figure><figcaption></figcaption></figure>\n<h3>6.2 Programming problem 2: Shifting a rank-1 array</h3>\n<p>Write a function which takes as an argument a 1D NumPy array (vector) of length <code>n</code> and returns a square 2D NumPy array (matrix) with <code>n</code> rows and <code>n</code> columns defined as follows. Row 0 of the matrix is identical to the input vector. Row 1 is formed by shifting all elements of the vector one position to the right and move the last element into the first element. Row 2 is formed by applying this shift to Row 1. And so on until the last row.</p>\n<p>For example, if the input vector is <code>np.array([1,2,3])</code>, then the output 2D array should be <code>np.array([[1,2,3],[3,1,2],[2,3,1]])</code>.</p>\n<p>Requirements:</p>\n<ul>\n<li>You can assume that the input argument is a 1D NumPy array.</li>\n<li>You can assume that the elements of the array are numbers.</li>\n<li>Your function must return a 2D NumPy array.</li>\n</ul>\n\n<figure><figcaption></figcaption></figure>\n<h3>6.3 Programming problem 3: Analysis of COVID-19 data</h3>\n<p>This programming problem ask you to write code to analyze COVID-19 CSV data files. The basics on the format of these files and how to process them were covered during week 6 lecture. See also the section above on data analysis with CSV files for a quick recap. For completeness, below, after the task statements, you will see a detailed explanation on the format of the COVID-19 CSV data files. We provide three different CSV example files in order to help you test your code, although we might test the code with different data files.</p>\n<p><em>You can solve the following tasks using list of lists (like in week 6 lecture) or using the Pandas library (week 7 lecture).</em></p>\n<div class=\"hint-container info\">\n<p class=\"hint-container-title\">相关信息</p>\n<p>You may download the csv files to get a better look at the format. Alternatively, you may type <code>less 09-11-2020.csv</code> into the terminal to explore the contents of the files there.</p>\n</div>\n<p><strong>Task 1.</strong> Write a function, <code>get_num_deaths_per_state_and_territory(csv_filename)</code>, that given the name of a COVID-19 CSV data file, returns two lists. The first list should be a list of integers containing the number of COVID-19 deaths per Australian state and territory in descending order, and the second list, a list of strings with the corresponding state and territory names.</p>\n<div class=\"hint-container info\">\n<p class=\"hint-container-title\">相关信息</p>\n<p>Hint: you can use the <code>sorted</code> Python built-in function to sort a list of tuples in descending order. To see why this might be helpful, try to understand how comparison operators (e.g., <code>&lt;</code> or <code>&gt;</code>) work with tuples composed of the number of deaths and the name of the state or territory corresponding to that number.</p>\n</div>\n<p><strong>Task 2.</strong> Write a function, <code>get_country_new_cases(countryname,csv_filename1,csv_filename2)</code>, that given the name of a country, and the name of two COVID-19 CSV data files, returns the number of new COVID-19 cases among the two dates corresponding to the files. You can safely assume (1) the first file to be associated to a previous date than the second; (2) there exist records for the country specified in both data files. On the other hand, the country's name may be specified by the user with arbitrary case, e.g., <code>aUSTRAlia</code> has to return the same number as <code>Australia</code> or <code>AUSTRALIA</code>.</p>\n<h3>6.3.1 COVID-19 CSV data files format</h3>\n<p>Each CSV file is named <code>MM-DD-YYYY.csv</code>, and contains the statistics up to that day for every country or region in the world with at least one recorded case. For many countries/regions, the statistics are broken down into states/provinces. For example, within Australia we have data for each state and territory (such as “Australian Capital Territory”, “Victoria”, etc). For the US, the data is even further broken down into Counties.</p>\n<p>Each <code>MM-DD-YYYY.csv</code> file has a header line with names of the columns (see below). The following lines contain actual data. The meanings of the columns are:</p>\n<ul>\n<li><code>FIPS</code>: US only. Federal Information Processing Standards code that uniquely identifies counties within the USA. For other countries/regions, this column will be empty.</li>\n<li><code>Admin2</code>: County name. US only. For other countries/regions, this column will be empty.</li>\n<li><code>Province_State</code>: Province, state or dependency name for those countries/regions that we have breakdowns per state/province (e.g. Australia, China, Germany, etc.). For other countries without such a breakdown, this column will be empty.</li>\n<li><code>Country_Region</code>: Country, region or sovereignty name. The names of locations correspond with the official designations used by the U.S. Department of State.</li>\n<li><code>Last_Update</code>: Last time that the entry was updated, in the format <code>YYYY-MM-DD HH:mm:ss</code> (24 hour format, in UTC).</li>\n<li><code>Lat</code> and <code>Long_</code>: Dot locations on the dashboard. All points (except for Australia) shown on the map are based on geographic centroids, and are not representative of a specific address, building or any location at a spatial scale finer than a province/state. Australian dots are located at the centroid of the largest city in each state.</li>\n<li><code>Confirmed</code>: Total number of confirmed (positive) cases up to the corresponding day shown in the CSV file name.</li>\n<li><code>Deaths</code>: Total number of deaths up to the corresponding day shown in the CSV file name.</li>\n<li><code>Recovered</code>: Total recovered cases. However, this field is no longer updated due to the unreliability of the data source. Therefore, you can assume that this column will be empty for all lines in the CSV file. It is just still there for compatibility of older versions of the data.</li>\n<li><code>Active</code>: Active cases = total cases - total recovered - total deaths. However, this field is no longer updated due to the unreliability of the data source. Therefore, you can assume that this column will be empty for all lines in the CSV file. It is just still there for compatibility of older versions of the data.</li>\n<li><code>Combined_key</code>: combined name in the format <code>\"Province_State, Country_Region\"</code> (for US this will be <code>\"Admin2, Province_State, Country_Region\"</code>). For those countries without breakdowns, <code>Combined_Key</code> is equal to <code>Country_Region</code>. <code>Combined_key</code> will be distinct for different lines of the file. That’s why it’s called a “key”.</li>\n<li><code>Incident_Rate</code>: Total number of all cases to date per 100,000 people.</li>\n<li><code>Case_Fatality_Ratio</code>: Number of deaths divided by number of cases in percentage. That means, this value is equal to <code>Deaths</code> / <code>Confirmed</code> * 100%.</li>\n</ul>\n<p>As an example, let’s look at this one line in a file named <code>09-14-2021.csv</code>:</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,,Australian Capital Territory,Australia,</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2021</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0</span><span style=\"--shiki-light:white;--shiki-dark:#FFFFFF\">9</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">15</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 0</span><span style=\"--shiki-light:white;--shiki-dark:#FFFFFF\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">22</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">37</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">35.4735</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">149.0124</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">665</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,,,</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"Australian Capital Territory, Australia\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">155.33753795842094</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0.45112781954887216</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div></div></div><p>This means that until Sept 14th 2021, in the state <code>Australian Capital Territory</code> of the country <code>Australia</code>, there are a total of 665 COVID-19 cases from the beginning of the pandemic (column <code>Confirmed</code>), 3 among them are dead (column <code>Deaths</code>); on average there are 155.33 confirmed cases out of 100,000 people (column <code>Incident_Rate</code>); 0.45% of infected people are dead (column <code>Case_Fatality_Ratio</code>, which should be equal to <code>Deaths</code> divided by <code>Confirmed</code> * 100%). This record was updated on <code>2021-09-15 03:22:37</code>, UTC time.</p>\n<p>If you’re interested, you can find more data files to test your code on the <a href=\"https://github.com/CSSEGISandData/COVID-19/tree/master/csse_covid_19_data/csse_covid_19_daily_reports\" target=\"_blank\" rel=\"noopener noreferrer\">GitHub repository of Johns Hopkins University</a>.</p>\n\n<figure><figcaption></figcaption></figure>\n<div class=\"language-python line-numbers-mode has-collapsed-lines collapsed\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--vp-collapsed-lines:15;--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">import</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> numpy </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">as</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> np</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">import</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> pandas </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">as</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> pd</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">import</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> math</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">import</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> matplotlib.pyplot </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">as</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> plt</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># ===== 3. Rank-1 arrays =====</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> evaluate_h</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">a</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> b</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> N</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> N </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&lt;=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        raise</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#ABB2BF\"> ValueError</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"N must be &gt; 1\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    x </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> np.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">zeros</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(N, </span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">dtype</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">float</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    y </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> np.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">zeros</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(N, </span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">dtype</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">float</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    step </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> (b </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> a) </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">/</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> (N </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> i </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> range</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(N):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">        xi </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> a </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> i </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">*</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> step</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">        x[i] </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> xi</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">        y[i] </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> (</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1.0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> /</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> math.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">sqrt</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">*</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">math.pi)) </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">*</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> math.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">exp</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0.5</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> *</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> (xi</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">**</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">))</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> x, y</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> evaluate_h_vectorized</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">a</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> b</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> N</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> N </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&lt;=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        raise</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#ABB2BF\"> ValueError</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"N must be &gt; 1\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    x </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> np.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">linspace</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(a, b, N, </span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">dtype</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">float</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    y </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> (</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1.0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> /</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> math.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">sqrt</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">*</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">math.pi)) </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">*</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> np.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">exp</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0.5</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> *</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> (x</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">**</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">))</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> x, y</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> plot_h</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">filename</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> a</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> b</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> N</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> use_vectorized</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">True</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> use_vectorized:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">        x, y </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> evaluate_h_vectorized</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(a, b, N)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    else</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">        x, y </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> evaluate_h</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(a, b, N)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    import</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> matplotlib.pyplot </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">as</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> plt</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    plt.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">figure</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    plt.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">plot</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(x, y)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    plt.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">grid</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    plt.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">savefig</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(filename)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    plt.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">close</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># ===== 4. Rank-2 arrays =====</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> evaluate_function</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">function</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> A</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    A </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> np.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">asarray</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(A)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    m, n </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> A.shape</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    B </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> np.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">zeros_like</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(A, </span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">dtype</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">float</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> i </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> range</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(m):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> j </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> range</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(n):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">            B[i, j] </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> function</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(A[i, j])</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> B</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> evaluate_function_vectorized</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">function</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> A</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    A </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> np.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">asarray</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(A)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> function</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(A)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># ===== 6.1 Diagonality =====</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> diagonality</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">matrix</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    M </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> np.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">asarray</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(matrix)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    nz </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> np.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">argwhere</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(M </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">!=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> nz.size </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">==</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        return</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 0</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    max_band </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 0</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> i, j </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> nz:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">        band </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> abs</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">int</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(i) </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> int</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(j))</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> band </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&gt;</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> max_band:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">            max_band </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> band</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> max_band </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 1</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># ===== 6.2 Cyclic shifts =====</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># </span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> cyclic_shifts_rightwards</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">vec</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    v </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> np.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">asarray</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(vec)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> v.ndim </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">!=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        raise</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#ABB2BF\"> ValueError</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"Input must be a 1D NumPy array\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    n </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> v.shape[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> np.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">vstack</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">([np.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">roll</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(v, k) </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> k </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> range</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(n)])</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">import</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> numpy </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">as</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> np</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> cyclic_shifts_rightwards</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">vec</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    v </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> np.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">asarray</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(vec)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> v.ndim </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">!=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        raise</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#ABB2BF\"> ValueError</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"Input must be a 1D NumPy array\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    n </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> v.shape[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> n </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">==</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">        # 返回 2D 空矩阵，形状 (0, 0)，满足测试要求</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> np.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">empty</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">((</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">), </span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">dtype</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">v.dtype)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> np.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">vstack</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">([np.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">roll</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(v, k) </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> k </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> range</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(n)])</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># ===== 6.3 COVID-19 =====</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> _read_covid_csv</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">csv_filename</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    df </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> pd.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">read_csv</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(csv_filename, </span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">dtype</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">{</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"FIPS\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: </span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">str</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">}, </span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">keep_default_na</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">False</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> col </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> [</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"Confirmed\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"Deaths\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> col </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> df.columns:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">            df[col] </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> pd.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">to_numeric</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(df[col], </span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">errors</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"coerce\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">).</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">fillna</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">).</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">astype</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">int</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> df</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> get_num_deaths_per_state_and_territory</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">csv_filename</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    df </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> _read_covid_csv</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(csv_filename)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    m_country </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> df[</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"Country_Region\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">].str.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">lower</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">() </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">==</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> \"Australia\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">lower</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    sub </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> df[m_country].</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">copy</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    grouped </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> (</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">        sub.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">groupby</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"Province_State\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">dropna</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">False</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)[</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"Deaths\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">        .</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">sum</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">        .</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">reset_index</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    )</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    grouped </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> grouped.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">sort_values</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">([</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"Deaths\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"Province_State\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">], </span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">ascending</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">False</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">True</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">])</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    deaths </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> grouped[</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"Deaths\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">].</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">astype</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">int</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">).</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">tolist</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    state_names </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> grouped[</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"Province_State\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">].</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">astype</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">str</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">).</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">tolist</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> deaths, state_names</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> get_country_new_cases</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">country_name</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> csv_filename1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> csv_filename2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> _country_confirmed_total</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">name</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> path</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">        df </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> _read_covid_csv</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(path)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">        mask </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> df[</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"Country_Region\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">].str.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">lower</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">() </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">==</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> name.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">lower</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        return</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> int</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(df.loc[mask, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"Confirmed\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">].</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">sum</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">())</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    c1 </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> _country_confirmed_total</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(country_name, csv_filename1)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    c2 </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> _country_confirmed_total</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(country_name, csv_filename2)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    return</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> int</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(c2 </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> c1)</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div><div class=\"collapsed-lines\"></div></div><p><strong>怎么复现实验（最短路径）：</strong></p>\n<p>复制上面的代码到你的 <code>.py</code> 或 Notebook。</p>\n<p>运行以下测试片段：</p>\n<div class=\"language-python line-numbers-mode has-collapsed-lines collapsed\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--vp-collapsed-lines:15;--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 3.2 绘图</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">plot_h</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"h_80_points.png\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">4</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">4</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">80</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 4.2 校验</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">A </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> np.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">array</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">([[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0.2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">12.4</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1.0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">5.78</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">],[</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1.34</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1.5</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1.5</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0.1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">],[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1.43</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">5.23</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">5.45</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2.23</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]])</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">assert</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> np.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">allclose</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">evaluate_function</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">lambda</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> u</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:u, A),</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">                   evaluate_function_vectorized</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">lambda</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> u</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:u, A))</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 6.1 对角性</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">assert</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> diagonality</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(np.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">diag</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">([</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">4</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">])) </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">==</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 1</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 6.2 环移</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">assert</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> np.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">array_equal</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">cyclic_shifts_rightwards</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(np.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">array</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">([</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">])),</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">                      np.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">array</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">([[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">],[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">],[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]]))</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 6.3 COVID（用你的 CSV 路径）</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">deaths, states </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> get_num_deaths_per_state_and_territory</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"/mnt/data/09-11-2020.csv\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">new_cases </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> get_country_new_cases</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"Australia\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"/mnt/data/09-11-2020.csv\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"/mnt/data/09-11-2021.csv\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div><div class=\"collapsed-lines\"></div></div><details class=\"hint-container details\"><summary>公众号：AI悦创【二维码】</summary>\n<figure><img src=\"/gzh.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n</details>\n<div class=\"hint-container info\">\n<p class=\"hint-container-title\">AI悦创·编程一对一</p>\n<p>AI悦创·推出辅导班啦，包括「Python 语言辅导班、C++ 辅导班、java 辅导班、算法/数据结构辅导班、少儿编程、pygame 游戏开发、Web、Linux」，招收学员面向国内外，国外占 80%。全部都是一对一教学：一对一辅导 + 一对一答疑 + 布置作业 + 项目实践等。当然，还有线下线上摄影课程、Photoshop、Premiere 一对一教学、QQ、微信在线，随时响应！微信：Jiabcdefh</p>\n<p>C++ 信息奥赛题解，长期更新！长期招收一对一中小学信息奥赛集训，莆田、厦门地区有机会线下上门，其他地区线上。微信：Jiabcdefh</p>\n<p>方法一：<a href=\"http://wpa.qq.com/msgrd?v=3&amp;uin=1432803776&amp;site=qq&amp;menu=yes\" target=\"_blank\" rel=\"noopener noreferrer\">QQ</a></p>\n<p>方法二：微信：Jiabcdefh</p>\n</div>\n<figure><img src=\"/zsxq.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n",
      "date_published": "2025-09-28T18:04:08.000Z",
      "date_modified": "2025-09-28T12:02:09.000Z",
      "authors": [
        {
          "name": "AI悦创"
        }
      ],
      "tags": []
    },
    {
      "title": "02-量词与贪婪：小小的正则，也可能把 CPU 拖垮！",
      "url": "https://bornforthis.cn/column/Python-Programming-Course/P11-regex-intro-course/02-regex-liangci-tanlan-cpu-performance.html",
      "id": "https://bornforthis.cn/column/Python-Programming-Course/P11-regex-intro-course/02-regex-liangci-tanlan-cpu-performance.html",
      "summary": "你好，我是悦创。 在上一讲中，我们已经学习了正则中和一些元字符相关的内容。这一节我们讲一下正则中的三种模式，贪婪匹配、非贪婪匹配和独占模式。 这些模式会改变正则中量词的匹配行为，比如： 匹配一到多次； 在匹配的时候，匹配长度是尽可能长还是要尽可能短呢？ 如果不知道贪婪和非贪婪匹配模式，我们写的正则很可能是错误的，这样匹配就达不到期望的效果了。 1. 为...",
      "content_html": "<figure><figcaption></figcaption></figure>\n<p>你好，我是悦创。</p>\n<p>在上一讲中，我们已经学习了正则中和一些元字符相关的内容。这一节我们讲一下正则中的三种模式，贪婪匹配、非贪婪匹配和独占模式。</p>\n<p>这些模式会改变正则中量词的匹配行为，比如：</p>\n<ul>\n<li>匹配一到多次；</li>\n<li>在匹配的时候，匹配长度是尽可能长还是要尽可能短呢？</li>\n</ul>\n<p>如果不知道贪婪和非贪婪匹配模式，我们写的正则很可能是错误的，这样匹配就达不到期望的效果了。</p>\n<h2>1. 为什么会有贪婪与非贪婪模式？</h2>\n<p>由于本节内容和量词相关的元字符密切相关，所以我们先来回顾一下正则中表示量词的元字符。</p>\n<figure><figcaption></figcaption></figure>\n<p>在这 6 种元字符中，我们可以用 <code>{m,n}</code> 来表示 （<code>*</code>）（<code>+</code>）（<code>?</code>） 这 3 种元字符：</p>\n<figure><figcaption></figcaption></figure>\n<p>表示量词的星号（<code>*</code>）和 加号（<code>+</code>）可能没你想象的那么简单，我用一个例子给你讲解一下。我们先看一下加号（<code>+</code>），使用 <code>a+</code> 在 <code>aaabb</code> 中查找，可以看到只有一个输出结果：</p>\n<figure><figcaption></figcaption></figure>\n<p>对应的 Python 代码如下：</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&gt;&gt;&gt;</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> import</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> re</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&gt;&gt;&gt;</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> re.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">findall</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">r</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#E06C75\">'a</span><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">+</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#E06C75\">'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'aaabb'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">[</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'aaa'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>加号应该很容易理解，我们再使用 <code>a*</code> 在 <code>aaabb</code> 这个字符串中进行查找，这次我们看到可以找到 4 个匹配结果。</p>\n<figure><figcaption></figcaption></figure>\n<p>使用 Python 示例如下，我们可以看到输出结果，也是得到了 4 个匹配结果：</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&gt;&gt;&gt;</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> import</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> re</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&gt;&gt;&gt;</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> re.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">findall</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">r</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#E06C75\">'a</span><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">*</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#E06C75\">'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'aaabb'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">[</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'aaa'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">''</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">''</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">''</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>但这一次的结果匹配到了三次空字符串。为什么会匹配到空字符串呢？因为星号（<code>*</code>）代表 0 到多次，匹配 0 次就是空字符串。到这里，你可能会有疑问，如果这样，<code>aaa</code> 部分应该也有空字符串，为什么没匹配上呢？</p>\n<p>这就引入了我们今天要讲的话题，贪婪与非贪婪模式。这两种模式都必须满足匹配次数的要求才能匹配上。贪婪模式，简单说就是尽可能进行最长匹配。非贪婪模式呢，则会尽可能进行最短匹配。正是这两种模式产生了不同的匹配结果。</p>\n<h2>2. 贪婪、非贪婪与独占模式</h2>\n<h3>2.1 贪婪匹配（Greedy）</h3>\n<p>首先，我们来看一下贪婪匹配。在正则中，表示次数的量词默认是贪婪的，在贪婪模式下，会尝试尽可能最大长度去匹配。</p>\n<p>首先，我们来看一下在字符串 <code>aaabb</code> 中使用正则 <code>a*</code> 的匹配过程。</p>\n<figure><figcaption></figcaption></figure>\n<p><code>a*</code> 在匹配开头的 a 时，会尝试尽量匹配更多的 a，直到第一个字母 b 不满足要求为止，匹配上三个 a，后面每次匹配时都得到了空字符串。</p>\n<p>相信看到这里你也发现了，贪婪模式的特点就是尽可能进行最大长度匹配。所以要不要使用贪婪模式是根据需求场景来定的。如果我们想尽可能最短匹配呢？那就要用到非贪婪匹配模式了。</p>\n<h3>2.2 非贪婪匹配（Lazy）</h3>\n<p>那么如何将贪婪模式变成非贪婪模式呢？我们可以在量词后面加上英文的问号 (<code>?</code>)，正则就变成了 <code>a*?</code>。此时的匹配结果如下：</p>\n<figure><figcaption></figcaption></figure>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&gt;&gt;&gt;</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> import</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> re</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&gt;&gt;&gt;</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> re.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">findall</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">r</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#E06C75\">'a</span><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">*</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#E06C75\">'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'aaabb'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)  </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 贪婪模式</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">[</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'aaa'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">''</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">''</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">''</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&gt;&gt;&gt;</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> re.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">findall</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">r</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#E06C75\">'a</span><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">*?</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#E06C75\">'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'aaabb'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">) </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 非贪婪模式</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">[</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">''</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'a'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">''</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'a'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">''</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'a'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">''</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">''</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">''</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>这一次我们可以看到，这次匹配到的结果都是单个的 a，就连每个 a 左边的空字符串也匹配上了。</p>\n<p>到这里你可能就明白了，非贪婪模式会尽可能短地去匹配，我把这两者之间的区别写到了下面这张图中。</p>\n<figure><figcaption></figcaption></figure>\n<p>为了让你加深理解，我们再来看一个示例，这一次让我们查找一下引号中的单词。</p>\n<p>从下面这个示例中，我们可以很容易看出两者对比上的差异。左右的文本是一样的，其中有两对双引号。不同之处在于，左边的示例中，不加问号时正则是贪婪匹配，匹配上了从第一个引号到最后一个引号之间的所有内容；而右边的图是非贪婪匹配，找到了符合要求的结果。</p>\n<figure><figcaption></figcaption></figure>\n<h3>2.3 独占模式（Possessive）</h3>\n<p>不管是贪婪模式，还是非贪婪模式，都需要发生回溯才能完成相应的功能。但是在一些场景下，我们不需要回溯，匹配不上返回失败就好了，因此正则中还有另外一种模式，独占模式，它类似贪婪匹配，但匹配过程不会发生回溯，因此在一些场合下性能会更好。</p>\n<p>你可能会问，那什么是回溯呢？我们来看一些例子，例如下面的正则：</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">regex </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> \"xy{1,3}z\"</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">text </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> \"xyyz\"</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>在匹配时，<code>y{1,3}</code>会尽可能长地去匹配，当匹配完 <code>xyy</code> 后，由于 y 要尽可能匹配最长，即三个，但字符串中后面是个 z 就会导致匹配不上，这时候正则就会向前回溯，吐出当前字符 z，接着用正则中的 z 去匹配。</p>\n<figure><figcaption></figcaption></figure>\n<p>如果我们把这个正则改成非贪婪模式，如下：</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">regex </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> \"xy{1,3}?z\"</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">text </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> \"xyyz\"</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>由于 <code>y{1,3}?</code> 代表匹配 1 到 3 个 y，尽可能少地匹配。匹配上一个 y 之后，也就是在匹配上 text 中的 xy 后，正则会使用 z 和 text 中的 xy 后面的 y 比较，发现正则 z 和 y 不匹配，这时正则就会<strong>向前回溯</strong>，重新查看 y 匹配两个的情况，匹配上正则中的 xyy，然后再用 z 去匹配 text 中的 z，匹配成功。</p>\n<figure><figcaption></figcaption></figure>\n<p>了解了回溯，我们再看下独占模式。</p>\n<p>独占模式和贪婪模式很像，独占模式会尽可能多地去匹配，如果匹配失败就结束，不会进行回溯，这样的话就比较节省时间。具体的方法就是在量词后面加上加号（<code>+</code>）。</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">regex </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> \"xy{1,3}+yz\"</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">text </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> \"xyyz\"</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><figure><figcaption></figcaption></figure>\n<p>需要注意的是 Python 和 Go 的标准库目前都不支持独占模式，会报错，如下所示：</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&gt;&gt;&gt;</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> import</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> re</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&gt;&gt;&gt;</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> re.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">findall</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">r</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#E06C75\">'xy</span><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">{1,3}+</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#E06C75\">yz'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'xyyz'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">error: multiple repeat at position </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">7</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>报错显示，加号（<code>+</code>）被认为是重复次数的元字符了。如果要测试这个功能，我们可以安装 PyPI 上的 regex 模块。</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">注意：需要先安装 regex 模块，pip install regex</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&gt;&gt;&gt;</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> import</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> regex</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&gt;&gt;&gt;</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> regex.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">findall</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">r</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#E06C75\">'xy</span><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">{1,3}</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#E06C75\">z'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'xyyz'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)  </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 贪婪模式</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">[</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'xyyz'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&gt;&gt;&gt;</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> regex.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">findall</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">r</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#E06C75\">'xy</span><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">{1,3}+</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#E06C75\">z'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'xyyz'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">) </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 独占模式</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">[</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'xyyz'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&gt;&gt;&gt;</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> regex.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">findall</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">r</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#E06C75\">'xy</span><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">{1,2}+</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#E06C75\">yz'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'xyyz'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">) </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 独占模式</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">[]</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>你也可以使用 Java 或 Perl 等其它语言来测试独占模式，查阅相关文档，看一下你所用的语言对独占模式的支持程度。</p>\n<p>如果你用 <code>a{1,3}+ab</code> 去匹配 <code>aaab</code> 字符串，<code>a{1,3}+</code> 会把前面三个 a 都用掉，并且不会回溯，这样字符串中内容只剩下 b 了，导致正则中加号后面的 a 匹配不到符合要求的内容，匹配失败。如果是贪婪模式 <code>a{1,3}</code> 或非贪婪模式 <code>a{1,3}?</code> 都可以匹配上。</p>\n<figure><figcaption></figcaption></figure>\n<p>这里我简单总结一下，独占模式性能比较好，可以节约匹配的时间和 CPU 资源，但有些情况下并不能满足需求，要想使用这个模式还要看具体需求（比如我们接下来要讲的案例），另外还得看你当前使用的语言或库的支持程度。</p>\n<h2>3. 正则回溯引发的血案</h2>\n<p>学习到了这里，你是不是觉得自己对贪婪模式、非贪婪模式，以及独占模式比较了解了呢？其实在使用过程中稍不留神，就容易出问题，在网上可以看到不少因为回溯引起的线上问题。</p>\n<p>这里我们挑选一个比较出名的，是阿里技术微信公众号上的发文。Lazada 卖家中心店铺名检验规则比较复杂，名称中可以出现下面这些组合：</p>\n<ol>\n<li>英文字母大小写；</li>\n<li>数字；</li>\n<li>越南文；</li>\n<li>一些特殊字符，如“<code>&amp;</code>”，“<code>-</code>”，“<code>_</code>”等。</li>\n</ol>\n<p>负责开发的小伙伴在开发过程中使用了正则来实现店铺名称校验，如下所示：</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">^</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">([A</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">Za</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">z0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">9.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">_</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&amp;</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'\\- ]|[aAàÀảẢãÃáÁạẠăĂằẰẳẲẵẴắẮặẶâÂầẦẩẨẫẪấẤậẬbBcCdDđĐeEèÈẻẺẽẼéÉẹẸêÊềỀểỂễỄếẾệỆfFgGhHiIìÌỉỈĩĨíÍịỊjJkKlLmMnNoOòÒỏỎõÕóÓọỌôÔồỒổỔỗỖốỐộỘơƠờỜởỞỡỠớỚợỢpPqQrRsStTuUùÙủỦũŨúÚụỤưƯừỪửỬữỮứỨựỰvVwWxXyYỳỲỷỶỹỸýÝỵỴzZ])+$</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div></div></div><p>这个正则比较长，但很好理解，中括号里面代表多选一，我们简化一下，就成下面这样：</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">^</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">([符合要求的组成1]</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">|</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">[符合要求的组成2])</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:white;--shiki-dark:#FFFFFF\">$</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div></div></div><p>脱字符（<code>^</code>）代表以这个正则开头，美元符号（<code>$</code>）代表以正则结尾，我们后面会专门进行讲解。这里可以先理解成整个店铺名称要能匹配上正则，即起到验证的作用。</p>\n<p>你需要留意的是，正则中有个加号（<code>+</code>），表示前面的内容出现一到多次，进行贪婪匹配，这样会导致大量回溯，占用大量 CPU 资源，引发线上问题，我们只需要将贪婪模式改成独占模式就可以解决这个问题。</p>\n<p>我之前说过，要根据具体情况来选择合适的模式，在这个例子中，匹配不上时证明店铺名不合法，不需要进行回溯，因此我们可以使用独占模式，但要注意并不是说所有的场合都可以用独占模式解决，我们要首先保证正则能满足功能需求。</p>\n<p>仔细再看一下 这个正则，你会发现 “组成 1” 和 “组成 2” 部分中，A-Za-z 英文字母在两个集合里面重复出现了，这会导致回溯后的重复判断。这里要强调一下，并不是说有回溯就会导致问题，你应该尽量减少回溯后的计算量，这些在后面的原理讲解中我们会进一步学习。</p>\n<p>另外，腾讯云技术社区也有类似的技术文章，你如果感兴趣，可以点击这里<a href=\"https://zhuanlan.zhihu.com/p/38229530\" target=\"_blank\" rel=\"noopener noreferrer\">进行</a>查看。</p>\n<p>说到这里，你是不是想起了课程开篇里面提到的一句话：<strong>如果你有一个问题，你想到可以用正则来解决，那么你有两个问题了。</strong></p>\n<blockquote>\n<p>Some people, when confronted with a problem, think “I know, I’ll use regular expressions.” Now they have two problems.</p>\n</blockquote>\n<p>所以一个小小的正则，有些时候也可能会把 CPU 拖垮，这也提醒我们在写正则的时候，一定要思考下回溯问题，避免使用低效的正则，引发线上问题。</p>\n<h2>4. 最后总结</h2>\n<p>最后我来给你总结一下：正则中量词默认是贪婪匹配，如果想要进行非贪婪匹配需要在量词后面加上问号。贪婪和非贪婪匹配都可能会进行回溯，独占模式也是进行贪婪匹配，但不进行回溯，因此在一些场景下，可以提高匹配的效率，具体能不能用独占模式需要看使用的编程语言的类库的支持情况，以及独占模式能不能满足需求。</p>\n<figure><figcaption></figcaption></figure>\n<h2>5. 课后思考</h2>\n<p>最后，我们来做一个小练习吧。</p>\n<p>有一篇英文文章，里面有很多单词，单词和单词之间是用空格隔开的，在引号里面的一到多个单词表示特殊含义，即引号里面的多个单词要看成一个单词。现在你需要提取出文章中所有的单词。我们可以假设文章中除了引号没有其它的标点符号，有什么方法可以解决这个问题呢？如果用正则来解决，你能不能写出一个正则，提取出文章中所有的单词呢（不要求结果去重）？</p>\n<blockquote>\n<p>we found “the little cat” is in the hat, we like “the little cat”</p>\n<p>其中 the little cat 需要看成一个单词</p>\n</blockquote>\n<p>好了，今天的课程就结束了，希望可以帮助到你，也希望你在下方的留言区和我参与讨论，并把文章分享给你的朋友或者同事，一起交流一下。</p>\n<details class=\"hint-container details\"><summary>公众号：AI悦创【二维码】</summary>\n<figure><img src=\"/gzh.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n</details>\n<div class=\"hint-container info\">\n<p class=\"hint-container-title\">AI悦创·编程一对一</p>\n<p>AI悦创·推出辅导班啦，包括「Python 语言辅导班、C++ 辅导班、java 辅导班、算法/数据结构辅导班、少儿编程、pygame 游戏开发、Web、Linux」，招收学员面向国内外，国外占 80%。全部都是一对一教学：一对一辅导 + 一对一答疑 + 布置作业 + 项目实践等。当然，还有线下线上摄影课程、Photoshop、Premiere 一对一教学、QQ、微信在线，随时响应！微信：Jiabcdefh</p>\n<p>C++ 信息奥赛题解，长期更新！长期招收一对一中小学信息奥赛集训，莆田、厦门地区有机会线下上门，其他地区线上。微信：Jiabcdefh</p>\n<p>方法一：<a href=\"http://wpa.qq.com/msgrd?v=3&amp;uin=1432803776&amp;site=qq&amp;menu=yes\" target=\"_blank\" rel=\"noopener noreferrer\">QQ</a></p>\n<p>方法二：微信：Jiabcdefh</p>\n</div>\n<figure><img src=\"/zsxq.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n",
      "date_published": "2025-09-28T12:23:14.000Z",
      "date_modified": "2025-10-16T00:46:46.000Z",
      "authors": [
        {
          "name": "bornforthis"
        }
      ],
      "tags": []
    },
    {
      "title": "00-导读：我是怎么学习和使用正则的？",
      "url": "https://bornforthis.cn/column/Python-Programming-Course/P11-regex-intro-course/00-01-regex-learning-and-practice.html",
      "id": "https://bornforthis.cn/column/Python-Programming-Course/P11-regex-intro-course/00-01-regex-learning-and-practice.html",
      "summary": "你好，我是 Cleland。受悦创的邀请，今天我来和你聊聊我是怎么学习和使用正则的。 刚工作那会儿，因为密集用到正则表达式，所以我花了不少时间去钻研正则相关的问题。到如今，许多年过去了，这些东西还历历在目，我也很乐意拿出来和你分享一下，希望在学习正则的道路上，能给你一些启发。 我经常在网上看到，许多⼈抱怨正则表达式“难学”，我知道，它确实不好学。但同时...",
      "content_html": "<figure><figcaption></figcaption></figure>\n<p>你好，我是 Cleland。受悦创的邀请，今天我来和你聊聊我是怎么学习和使用正则的。</p>\n<p>刚工作那会儿，因为密集用到正则表达式，所以我花了不少时间去钻研正则相关的问题。到如今，许多年过去了，这些东西还历历在目，我也很乐意拿出来和你分享一下，希望在学习正则的道路上，能给你一些启发。</p>\n<p>我经常在网上看到，许多⼈抱怨正则表达式“难学”，我知道，它确实不好学。但同时，我也去看过大家的抱怨，发现和我之前的做法⼀样：用到什么功能，就去网上搜⼀个例⼦来改改，能跑通就满意。至于这例子到底如何构成的，自己是不是都懂了，其实心里没底，能大概看懂五六分，就已经很满足了。</p>\n<p>这样浮光掠影的使用方法或许能解决眼前的问题，但⼀定不算“学会”。它有点像打井，每次挖到⼀点水就满足了，根本不管有没有持续性，也不关心挖没挖到含水层。结果就是，每次要喝水的时候，你都得重新打⼀眼井。</p>\n<p>那么对于正则表达式，我们有没有可能打出一口“永不干涸”的深井呢？当然有，那就是**⼀次性多投入点时间，由表及里，由术及道。一旦掌握了方法，之后就会简单很多了**。</p>\n<p>按照我的经验，如果每天花一刻钟或者半小时，坚持个把礼拜，通常都能登堂入室，达到“不会忘”的境界。不要以为这时间很多，我知道有些人很喜欢找“正则表达式五分钟入门”，其实每次都没有入门，日积月累，反而浪费了几十甚至上百个五分钟。</p>\n<p>那多投入时间很好理解，但是什么叫掌握方法呢？用我的话说，就是摆脱了字符的限制，深入到概念思维的层面。不要盯着那些鬼画桃符⼀般的字符和表示法皱眉，要摆脱桃符，把真正的“鬼”给认出来——虽然它们不那么容易看见。 也正因为这样，我们才需要⼀次性多投入点时间。</p>\n<p>那最终怎样才算“入门”了呢？按照我的经验，就是通过学习掌握方法，后来无论用正则表达式解决什么问题，都能自发遵循下面的流程去走，甚至能达到不需要这个流程，也能做到解决问题，那基本上就算入门了。</p>\n<ul>\n<li>\n<p><strong>第⼀步，做分解</strong>：拿到一个问题后，我们要先思考：这个问题可以分为几个子问题？每个子问题是否独立？我们拿最常见的电子邮件地址匹配来说。从文本结构来看，它可以分为“<code>username + @ + domain name</code>”这三个独立的部分。怎么画呢？我们可以先画出逻辑结构图。通过这个过程来厘清思路。当然，这是软件⼯程最基本的思路，相信你做起来应该问题不大。</p>\n</li>\n<li>\n<p><strong>第⼆步，分析各个子问题</strong>：某个位置上可能有多个字符？那就用字符组。某个位置上可能有多个字符串？那就用多选结构。出现的次数不确定？那就用量词。对出现的位置有要求？那就用锚点锁定位置…… 某种程度上，这就像武术里的见招拆招，每个问题都有对应的解法，只要熟练掌握了，知道什么时候用字符组，什么时候用多选结构，什么时候用量词，什么时候用锚点，就很容易搭建起完整的概念模型。</p>\n</li>\n<li>\n<p><strong>第三步，套皮</strong>：你大概注意到了，到现在，我们还没有谈论正则表达式的典型标志，比如方括号、星号、花括号。要知道，这些典型标志无非只是一些符号而已，真正重要的是字符组、多选结构、量词等等这些概念。一旦你的概念模型清楚了，写出正则表达式就非常简单了，无非是查阅语法手册，把之前得到的概念模型按照对应语言或工具的约定写下来而已。</p>\n<p>许多人觉得正则表达式难懂，总是纠缠于“这里为什么要多一个星号？那里为什么是方括号而不是花括号？”，原因恰恰在于对概念模型不清楚。虽然各种语言或工具对正则表达式的支持大同小异，但细微差别仍然不可忽视。不过只要你心怀正念，洞若观火，这些差异其实并不是大问题。</p>\n</li>\n<li>\n<p><strong>第四步，调试</strong>：很多人都说，正则表达式的麻烦之处在于它像个黑箱子，很难调试，迄今为止仍然没有特别好用的⼯具，所以我们没法⼀步步跟进去看匹配的具体过程，只能笼统地知道“匹配了”或者“没匹配”。</p>\n</li>\n</ul>\n<p>那到底怎么调试呢？我的经验是，复杂⼀点的正则表达式不能⼀次写对，这是很正常的。与其纠结“这个正则表达式看起来这么复杂，此处到底要用星号 <code>*</code> 还是加号 <code>+</code>，不如先搞清楚，星号（ <code>*</code> ）或加号（ <code>+</code> ）限定的到底是正则表达式中的哪一部分，对应要匹配文本中的哪一部分。这两个问题搞清楚了，整个问题就迎刃而解了。</p>\n<p>另外，还有⼀点统摄全局的经验想和你说一下， <strong>那就是学会了正则表达式之后，务必要保持克制</strong> 。写正则表达式很容易上瘾，毕竟它的功能那么强⼤，处理速度那么快，⼜像天书符咒那样充满了“神秘”色彩。于是，“写⼀条其他⼈看不懂的正则表达式，⼀次性解决所有问题”，就成了某些程序员的执念。但是，从软件工程的角度来看，这种办法绝对是噩梦，不但其他人无法理解，自己过⼀段时间也会挠头。</p>\n<p>那到底该怎么“克制”呢？我的经验有以下三点。</p>\n<p><strong>第⼀，能用普通字符串处理的，坚决⽤普通字符串处理</strong>。字符串处理的速度不见得差，可读性却好上很多。如果要在大段文本中定位所有的 today 或者 tomorrow，用最简单的字符串查找，直接找两遍，明显比 <code>to(day|morrow)</code> 看起来更清楚。</p>\n<p><strong>第⼆，能写注释的正则表达式，⼀定要写注释</strong>。正则表达式的语法非常古老，不够直观，为了便于阅读和维护，如今大部分语言里都可以通过 x 打开注释模式。有了注释，复杂正则表达式的结构也能一目了然。</p>\n<p><strong>第三，能用多个简单正则表达式解决的，⼀定不要苛求用一个复杂的正则表达式</strong>。这里最明显的例子就是输入条件的验证。比如说，常见的密码要求“必须包含数字、小写字母、大写字母、特殊符号中的至少两种，且长度在 8 到 16 之间”。</p>\n<p>你当然可以绞尽脑汁用一个正则表达式来验证，但如果放下执念，⽤多个正则表达式分别验证“包含数字”、“包含小写字母”、“包含大写字母”、“包含特殊符号”这四个条件，要求验证成功结果数大于等于 2，再配合一个正则表达式验证长度，这样做也是可行的。虽然看起来繁琐，但可维护性绝对远远强于单个正则表达式。</p>\n<h2>小结</h2>\n<p>好了，到此为⽌，我的经验介绍完了，可以交棒了。</p>\n<p>这些年，很多人问过我，我当时到底是怎么学会正则的？说实话，我那会儿根本没想什么，纯粹出于“干一行爱一行”的朴素想法。要用得多，就找书来，哪怕是囫囵吞枣，也要一鼓作气看完。<strong>我一直觉得，真正值得学的东西，没有什么“平滑学习曲线”。在前面的阶段，你总得狠下心来，过了一个又一个坎儿，然后才能有一马平川</strong>。</p>\n<p>我觉得，正则表达式属于“没有维护成本”的技能。一旦学会了，每⼀次遇到这类问题都可以“零成本出击”。所以，长期来看，这绝对是一笔“无本万利”的生意。希望你能通过这个专栏早日达到一马平川！</p>\n<details class=\"hint-container details\"><summary>公众号：AI悦创【二维码】</summary>\n<figure><img src=\"/gzh.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n</details>\n<div class=\"hint-container info\">\n<p class=\"hint-container-title\">AI悦创·编程一对一</p>\n<p>AI悦创·推出辅导班啦，包括「Python 语言辅导班、C++ 辅导班、java 辅导班、算法/数据结构辅导班、少儿编程、pygame 游戏开发、Web、Linux」，招收学员面向国内外，国外占 80%。全部都是一对一教学：一对一辅导 + 一对一答疑 + 布置作业 + 项目实践等。当然，还有线下线上摄影课程、Photoshop、Premiere 一对一教学、QQ、微信在线，随时响应！微信：Jiabcdefh</p>\n<p>C++ 信息奥赛题解，长期更新！长期招收一对一中小学信息奥赛集训，莆田、厦门地区有机会线下上门，其他地区线上。微信：Jiabcdefh</p>\n<p>方法一：<a href=\"http://wpa.qq.com/msgrd?v=3&amp;uin=1432803776&amp;site=qq&amp;menu=yes\" target=\"_blank\" rel=\"noopener noreferrer\">QQ</a></p>\n<p>方法二：微信：Jiabcdefh</p>\n</div>\n<figure><img src=\"/zsxq.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n",
      "date_published": "2025-09-26T22:43:59.000Z",
      "date_modified": "2025-10-16T00:46:46.000Z",
      "authors": [
        {
          "name": "bornforthis"
        }
      ],
      "tags": []
    },
    {
      "title": "00-学习正则，我们到底要学什么？",
      "url": "https://bornforthis.cn/column/Python-Programming-Course/P11-regex-intro-course/00-regex-opening-what-to-learn.html",
      "id": "https://bornforthis.cn/column/Python-Programming-Course/P11-regex-intro-course/00-regex-opening-what-to-learn.html",
      "summary": "你好，我是悦创。 我相信，作为一名程序员或者准程序员，你肯定是知道正则表达式的。作为计算机领域最伟大的发明之一，正则表达式简单、强大，它可以极大地提高我们工作中的文本处理效率。现在，各大操作系统、编程语言、文本编辑器都已经支持正则表达式，甚至我还和我出版图书的编辑开玩笑说，你们也应该好好学学正则这门手艺。 但是，当我去和朋友深入聊天的时候，才发现很多人...",
      "content_html": "<figure><figcaption></figcaption></figure>\n<p>你好，我是悦创。</p>\n<p>我相信，作为一名程序员或者准程序员，你肯定是知道正则表达式的。作为计算机领域最伟大的发明之一，正则表达式简单、强大，它可以极大地提高我们工作中的文本处理效率。现在，各大操作系统、编程语言、文本编辑器都已经支持正则表达式，甚至我还和我出版图书的编辑开玩笑说，你们也应该好好学学正则这门手艺。</p>\n<p>但是，当我去和朋友深入聊天的时候，才发现很多人是没有系统学习过正则表达式的，他们和我笑着说，这东西不难，我每次用的时候都是去 Google 搜一搜，然后复制过来改一改，效率特别高，我听完之后哭笑不得。</p>\n<p>再后来，我给我的私教学员们在课程中讲解了正则表达式，很多学员讲了他们的困惑，我总结了下，主要有 4 点：</p>\n<ol>\n<li>学过正则，但觉得过于复杂，根本记不住；</li>\n<li>在网上找到的正则和自己的需求有一点出入，看不懂，也不知道该怎么改；</li>\n<li>不清楚正则的流派和支持情况，搞不懂为何自己写的正则没达到效果；</li>\n<li>不清楚正则的工作原理，结果写出的正则或者从网上随便找来的正则出现了性能问题。</li>\n</ol>\n<p>为什么会出现这些问题呢？我觉得是核心原因主要是以下几点：</p>\n<ol>\n<li>没重视过正则，觉得没必要专门花时间学习，用的时候才发现“书到用时方恨少”；</li>\n<li>没系统学习过正则，只简单地使用过部分功能，自然也就不清楚正则流派及工作原理等内容了；</li>\n<li>没找到正确的方法去学习和记忆，导致学了之后很快就忘了。</li>\n</ol>\n<p>所以，我打算通过一个课程，用尽可能通俗易懂的方式，系统化地给你梳理和讲解正则的知识点，希望可以帮助你解决上面这些问题，让正则这个强大的工具在你手上发挥出真正的威力。</p>\n<p>但是呢，真要开始学正则，我想你的心头可能会五味杂陈，内心也是纠结万分。美国一位知名程序员杰米·加文斯基（Jamie Zawinski）说过一句话：<a href=\"http://regex.info/blog/2006-09-15/247\" target=\"_blank\" rel=\"noopener noreferrer\">如果你有一个问题，你想到可以用正则来解决，那么你有两个问题了。</a></p>\n<blockquote>\n<p>Some people, when confronted with a problem, think “I know, I’ll use regular expressions.” Now they have two problems.</p>\n</blockquote>\n<p>这句话流传在程序员中间，给人一种感觉，就是正则是很难掌握和利用好的工具。也正因如此，很多程序员并不愿意去学正则表达式，心里可能是这么想的：我在工作中用到正则的时候并不多啊，要用的时候搜一下就好了啊，为什么还要专门花时间和精力学它呢？</p>\n<p>但我觉得，真实的情况可能是这样的：<strong><span style=\"color:orange\">不是工作中用不到，而是当你不熟悉一个技能的时候，遇到问题时根本不会考虑它</span></strong>。比如我们要删除掉文本中的所有数字，不知道正则的话，你可能会想到从 0 到 9 这样一个个替换，操作 10 次，但如果知道正则，那么只需要替换一次就可以搞定这个问题。</p>\n<h2>1. 正则是什么，能做什么？</h2>\n<p>说了这么多，到底什么是正则呢？它能做什么呢？</p>\n<p>我们先来说概念。正则，就是正则表达式，英文是 Regular Expression，简称 RE。顾名思义，正则其实就是一种<strong>描述文本内容组成规律的表示方式</strong>。</p>\n<p>在编程语言中，正则常常用来简化文本处理的逻辑。在 Linux 命令中，它也可以帮助我们轻松地查找或编辑文件的内容，甚至实现整个文件夹中所有文件的内容替换，比如 grep、egrep、sed、awk、vim 等。另外，在各种文本编辑器中，比如 Atom，Sublime Text 或 VS Code 等，在查找或替换的时候也会使用到它。总之，正则是无处不在的，已经渗透到了日常工作的方方面面。</p>\n<p>简单来说，正则是一个非常强大的文本处理工具，它的应用极其广泛。</p>\n<ul>\n<li>我们可以利用它来校验数据的有效性，比如用户输入的手机号是不是符合规则；</li>\n<li>也可以从文本中提取想要的内容，比如从网页中抽取数据；</li>\n<li>还可以用来做文本内容替换，从而得到我们想要的内容。</li>\n</ul>\n<figure><figcaption></figcaption></figure>\n<p>通过它的功能和分布的广泛你也能看出来，正则是一个非常值得花时间和精力好好学习的基本技能。</p>\n<ul>\n<li>之前你花几十分钟才能搞定的事情，可能用正则很快就搞定了；</li>\n<li>之前不能解决的问题，你系统地学习正则后，可能发现也能轻松解决了。</li>\n</ul>\n<h2>2. 学习正则，我们到底要学什么？</h2>\n<p>那么问题来了，想要掌握正则，我们到底要学什么？我在课程中又是怎么安排这些内容的呢？</p>\n<h3>2.1 正则的基本知识</h3>\n<p>正则的很多基本知识其实并不难，只是难记。不过，记住一个东西并不是我们的最终目的，我们的目的是理解并且会用正则这个工具。</p>\n<p>比如正则中的各种元字符，在课程中，我会讲有关元字符的记忆技巧，让你不再对元字符感到头疼。再比如各种模式和分组，它们可以在查找和替换时发挥强大的威力。</p>\n<p>下面我用 Python 语言示例，从文本中找出连续出现的重复单词。我们可以看到，正则可以很方便地搞定这个需求。</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&gt;&gt;&gt;</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> import</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> re</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&gt;&gt;&gt;</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> test_str </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> \"the little cat cat in the hat hat.\"</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&gt;&gt;&gt;</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> re.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">sub</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">r</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#E06C75\">'</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#D19A66\">(</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#E06C75\">\\w</span><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">+</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#D19A66\">)</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\"> \\1</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#E06C75\">'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">r</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#E06C75\">'</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">\\1</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#E06C75\">'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, test_str)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'the little cat in the hat.'</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>但上面的示例在任何情况下都能很好地工作么？我们要不要考虑单词的边界？反向引用又有哪些要注意的点？所有这些问题都会在课程中一一进行讲解。</p>\n<h3>2.2 在常见的编辑器中使用正则的方法</h3>\n<p>我们经常需要从大段文本中抽取需要的内容，学会使用正则之后，不用写代码就可以完成类似的日常工作。举个例子，假如我们在 Sublime Text 3 中使用正则，查找重复出现的单词，并且想把它替换成单个单词。</p>\n<figure><figcaption></figcaption></figure>\n<p>菜单中的 <code>Find -&gt; Replace</code>，在查找栏中输入 <code>(\\w+) \\1</code>，在替换栏中输入子组的引用 <code>\\1</code> ，然后点击 Replace All 就可以完成替换工作了。这样，通过少量的正则，我们就完成了文本的处理工作了。是不是很方便呢？</p>\n<h3>2.3 正则中进阶的内容</h3>\n<p>除此之外，我还会在课程中讲一些更高阶的正则内容，这部分主要有正则中的断言（包括单词边界、行开始和结束、环视），三种主要流派的区别以及对应的软件实现，正则的工作机制和常见的优化方式等。</p>\n<p>掌握这些内容可以让我们更好地理解正则， 也可以避过很多坑。比如，为什么在编程语言中能工作的正则，在 Linux 命令 grep 中就不能工作了呢？正则匹配的原理又是什么？如何写出性能更好的正则呢？</p>\n<p>综合以上这三点，我希望你能掌握的是正则中一些重要的概念和功能，这是我们学习和使用正则的基础；然后是有关正则的记忆方法，通过合理的方式，事半功倍地达到学习效果，这是我们学习正则的利器；此外，我还会运用大量的示例让你了解正则在实际工作场景中的使用，只有与现实案例结合，我们的学习才不会脱节，这是我们学习正则的原则。</p>\n<p>明确原则、打好基础、掌握利器，我相信你一定可以拿下正则这项技能，在工作中随心所用。学完后，你一定会觉得，手写正则原来也没有那么难。</p>\n<p>话不多说，我们这就开始吧！</p>\n\n<details class=\"hint-container details\"><summary>公众号：AI悦创【二维码】</summary>\n<figure><img src=\"/gzh.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n</details>\n<div class=\"hint-container info\">\n<p class=\"hint-container-title\">AI悦创·编程一对一</p>\n<p>AI悦创·推出辅导班啦，包括「Python 语言辅导班、C++ 辅导班、java 辅导班、算法/数据结构辅导班、少儿编程、pygame 游戏开发、Web、Linux」，招收学员面向国内外，国外占 80%。全部都是一对一教学：一对一辅导 + 一对一答疑 + 布置作业 + 项目实践等。当然，还有线下线上摄影课程、Photoshop、Premiere 一对一教学、QQ、微信在线，随时响应！微信：Jiabcdefh</p>\n<p>C++ 信息奥赛题解，长期更新！长期招收一对一中小学信息奥赛集训，莆田、厦门地区有机会线下上门，其他地区线上。微信：Jiabcdefh</p>\n<p>方法一：<a href=\"http://wpa.qq.com/msgrd?v=3&amp;uin=1432803776&amp;site=qq&amp;menu=yes\" target=\"_blank\" rel=\"noopener noreferrer\">QQ</a></p>\n<p>方法二：微信：Jiabcdefh</p>\n</div>\n<figure><img src=\"/zsxq.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n",
      "date_published": "2025-09-26T21:01:17.000Z",
      "date_modified": "2025-10-16T00:46:46.000Z",
      "authors": [
        {
          "name": "bornforthis"
        }
      ],
      "tags": []
    },
    {
      "title": "24-结束语：数据分析师职场提升的关键点",
      "url": "https://bornforthis.cn/column/%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90%E6%80%9D%E7%BB%B4%E4%B8%8E%E5%AE%9E%E6%88%9823%E8%AE%B2/25.html",
      "id": "https://bornforthis.cn/column/%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90%E6%80%9D%E7%BB%B4%E4%B8%8E%E5%AE%9E%E6%88%9823%E8%AE%B2/25.html",
      "summary": "你好，我是悦创。 经过了两个多月的课程更新，到此，本专栏课程的内容就已经结束了，在这里我有一些话想告诉你。 在更新课程的同时，我看了很多同学的留言，特别是问我的问题。其中有一个点需要表明，在学习的过程中，千万不要纠结于形式（案例），一定要注重内容（思维），比如我是怎么思考某个点的，有哪些合理的地方，有哪些不合理的地方，哪些你能用上，怎么用？只有这样思考...",
      "content_html": "<p>你好，我是悦创。</p>\n<p>经过了两个多月的课程更新，到此，本专栏课程的内容就已经结束了，在这里我有一些话想告诉你。</p>\n<p>在更新课程的同时，我看了很多同学的留言，特别是问我的问题。其中有一个点需要表明，在学习的过程中，千万不要纠结于形式（案例），一定要注重内容（思维），比如我是怎么思考某个点的，有哪些合理的地方，有哪些不合理的地方，哪些你能用上，怎么用？只有这样思考，你的进步才会快，你的职场提升才会高效。</p>\n<h2>1. 职场提升关键点</h2>\n<p>对于职场人的提升，我可以给你一个这样的公式——思考表达执行上超出预期</p>\n<ul>\n<li>\n<p>思考：你要有敏捷的思考能力，我相信未来是属于这种人的。因为对于同样一个问题，你总是能有自己独到的见解，这代表你有深度思考，且这会成为你闪光点，它会潜移默化影响到你工作中的每一个过程。这确实需要平时大量的练习，包括我现在也还在这个路上去学习成长。</p>\n</li>\n<li>\n<p>表达：你要有良好的表达能力，无论是同事还是领导之间的沟通，都要做到没有问题，这里并不是指会说话，而是会表达，敢表达，表达的准确。</p>\n</li>\n<li>\n<p>执行上超出预期：你自己要做到在执行力上非常高效，且超出预期。超出预期的意思是超出领导对你的期望，他要的可能是 1，你要尽力做到 1.2，甚至 1.5，因为 1 谁都能做到，而超出的 0.2 / 0.5 就是你晋升的基础。事事有回应，件件有着落，回应和着落都要超出预期。千万不要当老油条，因为偷懒迟早会被发现的。</p>\n</li>\n</ul>\n<p>具体到数据分析这个领域，我也给你列出来了数据分析师的类型以及学习的路径，也推荐了一些较好的书籍。</p>\n<h2>2. 数据分析师的类型及学习路径</h2>\n<p>数据分析师的类型大致分为两种：</p>\n<ol>\n<li>\n<p><strong>业务型分析师</strong>： 对接业务的分析师，主要工作内容是和产品团队一起完成年 KPI ，日常围绕报表、专题报告、汇报运转，比如每天的数据监控和产品的方向建议。</p>\n</li>\n<li>\n<p><strong>数据型分析师</strong>： 这类型的数据分析师往往重心在内部数据产品开发上，如数据仓库，数据可视化 BI，自动化监控平台。</p>\n</li>\n</ol>\n<p>其中，数据型分析师，其发展方向又可以分为两种：</p>\n<ul>\n<li>\n<p><strong>数据研发型</strong>：这个发展方向要求你对技术非常熟练，能够通过技术对数据进行分析；</p>\n</li>\n<li>\n<p><strong>算法型</strong>：这个发展方向要求你数学功底要好，而且课题的研究能力非常强。</p>\n</li>\n</ul>\n<p>那这两种数据分析师类型的学习路径是怎样的呢？</p>\n<h3>2.1 业务型数据分析师</h3>\n<p>先学统计学——数据分析思维——学工具（Excel、PPT、Python、R、Tableau）——学经济学和心理学</p>\n<blockquote>\n<p>推荐书籍：</p>\n<p>《独立思考：日常生活中的批判性思维》，这本书可以帮你打破惯性的思维模式，突破思维上的误区与局限，训练理性与逻辑能力，让你做出最正确的判断与决策，可以让你看得更高，走得更远。</p>\n<p>《京东平台数据化运营》这本书公开了京东平台的许多实操案例，例如关于 App 端、微信端、手机 QQ 端等无线流量的详细介绍。此外，还有关于优化搜索流量的方法和步骤，以及关于转化率相关指标的优化方法。本书贴近真实业务，有不少方法可以套用。</p>\n<p>《机器学习》数据分析师必须要懂点算法的知识，这是人工智能领域的一本入门教材。</p>\n</blockquote>\n<h3>2.2 数据型数据分析师</h3>\n<p>先学统计学——数据分析思维——学工具（Hadoop，Spark，Hive，Java）多学技术语言</p>\n<blockquote>\n<p>推荐书籍：</p>\n<p>《大数据之路》系统地从规范、模型、平台、应用等多层次对阿里大数据产品实践做了一遍梳理，通俗易懂地介绍了大数据平台的架构。</p>\n<p>《数据仓库工具箱》涉及的行业较多，从不同角度体现了数据仓库的各个方面，对维度建模知识讲得很透彻。</p>\n</blockquote>\n<p>悦创老师写这个课程只是为你提供了一些思维的敲门砖，要想有真正的进步和成长，23 课时的学习肯定是不够的，你可以按照自己的发展方向去学习相对应的技能。这里再强调下，学习的过程中一定要多思考，多交流，也只有这样才能沉淀出自己的方法论。</p>\n<details class=\"hint-container details\"><summary>公众号：AI悦创【二维码】</summary>\n<figure><img src=\"/gzh.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n</details>\n<div class=\"hint-container info\">\n<p class=\"hint-container-title\">AI悦创·编程一对一</p>\n<p>AI悦创·推出辅导班啦，包括「Python 语言辅导班、C++ 辅导班、java 辅导班、算法/数据结构辅导班、少儿编程、pygame 游戏开发、Web、Linux」，招收学员面向国内外，国外占 80%。全部都是一对一教学：一对一辅导 + 一对一答疑 + 布置作业 + 项目实践等。当然，还有线下线上摄影课程、Photoshop、Premiere 一对一教学、QQ、微信在线，随时响应！微信：Jiabcdefh</p>\n<p>C++ 信息奥赛题解，长期更新！长期招收一对一中小学信息奥赛集训，莆田、厦门地区有机会线下上门，其他地区线上。微信：Jiabcdefh</p>\n<p>方法一：<a href=\"http://wpa.qq.com/msgrd?v=3&amp;uin=1432803776&amp;site=qq&amp;menu=yes\" target=\"_blank\" rel=\"noopener noreferrer\">QQ</a></p>\n<p>方法二：微信：Jiabcdefh</p>\n</div>\n<figure><img src=\"/zsxq.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n",
      "image": "https://bornforthis.cn/gzh.jpg",
      "date_published": "2025-09-26T19:28:31.000Z",
      "date_modified": "2025-09-26T12:16:46.000Z",
      "authors": [
        {
          "name": "bornforthis"
        }
      ],
      "tags": []
    },
    {
      "title": "20-行业分析：行业分析及框架分析",
      "url": "https://bornforthis.cn/column/%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90%E6%80%9D%E7%BB%B4%E4%B8%8E%E5%AE%9E%E6%88%9823%E8%AE%B2/21.html",
      "id": "https://bornforthis.cn/column/%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90%E6%80%9D%E7%BB%B4%E4%B8%8E%E5%AE%9E%E6%88%9823%E8%AE%B2/21.html",
      "summary": "你好，我是悦创。 从这一课时开始，我们就正式进入数据分析师的自我修养，所以我们的内容会更加轻松一点并带有很强的个人主观理解。 本课时内容分为两部分： 行业分析目标； 电商行业分析举例； 1. 行业分析目标 首先说下行业分析的背景，行业分析有两种背景： 当前公司准备进入某行业，需要分析师或者战略部门给出一份详细报告； 当公司业务发展遇到瓶颈，需要分析师去...",
      "content_html": "<p>你好，我是悦创。</p>\n<p>从这一课时开始，我们就正式进入数据分析师的自我修养，所以我们的内容会更加轻松一点并带有很强的个人主观理解。</p>\n<ul>\n<li>\n<p>本课时内容分为两部分：</p>\n</li>\n<li>\n<p>行业分析目标；</p>\n</li>\n<li>\n<p>电商行业分析举例；</p>\n</li>\n</ul>\n<h2>1. 行业分析目标</h2>\n<p>首先说下行业分析的背景，行业分析有两种背景：</p>\n<ul>\n<li>\n<p>当前公司准备进入某行业，需要分析师或者战略部门给出一份详细报告；</p>\n</li>\n<li>\n<p>当公司业务发展遇到瓶颈，需要分析师去验证当前市场对产品的需求有无变化。</p>\n</li>\n</ul>\n<p>对于行业分析，我们的讲解也是按照前面<a href=\"/column/%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90%E6%80%9D%E7%BB%B4%E4%B8%8E%E5%AE%9E%E6%88%9823%E8%AE%B2/17.html\" target=\"_blank\">第 16 课时“问题的定义与拆解”</a>逻辑展开，问题的识别与拆解对于解决行业分析目标是非常有帮助的。</p>\n<p>从行业分析的背景来看，目标基本上分为两种：</p>\n<ul>\n<li>\n<p>转型，希望通过行业分析看一下公司转型到某个行业有没有一些切入点；</p>\n</li>\n<li>\n<p>用户需求整体的行业分析，比如看用户的需求还在不在。</p>\n</li>\n</ul>\n<p>在这两种分析目标的基础之上，我们可以分为五大模块，如下图所示。</p>\n<figure><figcaption></figcaption></figure>\n<p>第一个是界定范围，第二个是市场规模，第三个是社会热点事件，第四个是头部玩家，第五个是未来预测。你可能看到过非常多的行业分析报告，比如介绍头部玩家的时候，把头部的 App 整体描述了一遍，实际上没有必要，也没有价值。你只要把范围、市场规模、社会热点事件、头部玩家、未来预测说出来即可。<strong>行业分析报告不在于大而全和什么方法，而在于有所发现（切入点）。</strong></p>\n<h2>1. 电商行业分析举例</h2>\n<p>我以电商行业举一个例子，因为现阶段电商比较成熟。</p>\n<p><strong>背景</strong>：公司近期试水做电商业务，管理层知道很难做，但是决策层又想找一些切入点。这个时候就找战略部，希望战略部能给出一些建议。</p>\n<p>一般在做这件事的时候，你不要指望决策层或者管理层给你很多信息，实际上需求都比较模糊。因为在做行业分析这件事上，想找到一个人很好地把需求描述清楚是很难的，因为大家都是在摸着石头过河。</p>\n<p>我们做行业分析的时候，一般都是这样一个节奏：</p>\n<ul>\n<li>\n<p>一周内快速出一些报告，拿着报告去和需求方沟通，这样可以避免一个月后做的专题分析不是对方想要的。</p>\n</li>\n<li>\n<p>在与需求方对的基础上，把不确定的点剔除，把很明确的点确定，然后继续深挖。</p>\n</li>\n</ul>\n<p>按照前面我们所说的五大模块，一个一个来看。</p>\n<h3>1.1 界定范围——在全局视野下找切入点</h3>\n<p>首先是界定范围。什么意思呢？就是要在全局视野下找切入点。比如现在是电商，首先我们要总结出这样一个电商产业链的图谱，如图所示。</p>\n<figure><figcaption></figcaption></figure>\n<p>产业链图谱内容包含很多信息，比如，老牌成熟的电商企业有哪些？新型的电商企业又有哪些？其中微商，二手电商有哪些？同时围绕电商，它的上游供应商是什么？下游又有哪些代理运营商？在这个过程中，它的支付方式及物流是如何？然后是消费者相关情况，消费者这一块又跟渠道挂钩，所以产业链图谱的内容非常全。在产业链图谱的基础上，你看整个行业就比较清晰，否则你直接上来就是淘宝、京东、唯品会，那你的视野就已经被局限死了。</p>\n<p>有了这个产业链图谱，给管理层看完后，比如他想做移动类的综合类电商，比如说手淘、京东、拼多多，这就是界定范围。那我们后面的报告内容就可以围绕这个点去切入，所以在这一块，先把对象明确清楚，找到切入点。</p>\n<h3>1.2 市场规模</h3>\n<p>市场规模这部分，我们分为交易额和用户分析，具体如下。</p>\n<h4>1.2.1 交易额描述</h4>\n<p>大部分报告的市场规模，都是给的交易额描述，如图所示。</p>\n<figure><figcaption></figcaption></figure>\n<p>这是网络零售市场的交易额曲线，以及它在移动端的占比。通过这张图我们可以很明显发现：网络零售市场的趋势是上升的，只不过它的增长率是下降的，同时移动端的交易额也是在上升的。但是作为分析师，一定要看得更细，一定要有独立思考。就交易额逐年上升结论来说，更加重要的是要找到谁增长？是所有都增长还是有一些涨有些跌？在当前增长率持续下降的情况下，还有谁逆势上升？这就是我们的拆解思想。</p>\n<h4>1.2.2 交易额分析</h4>\n<p>基于交易额逐年上升，那对于阿里、京东、拼多多三家公司来说，它们的趋势图是什么样子呢？因为我们前面针对的对象就是这三家公司，然后你可以去查下三家公司的财报，如图所示。</p>\n<figure><figcaption></figcaption></figure>\n<p>我们就发现，比如阿里 17 年的 GMV 和 18 年的 GMV 对比，涨了 27%。对于京东，第三季度的 GMV 同比增长 30.5%。而对于拼多多就是 Q3 过去 12 个月的一个同比增长 386%。你可能会疑问这些统计时间段不一致，是否会有影响。其实每一家公司，它拥有数据的信息量不一样，所以只要是对比本身的逻辑没问题就行。注意，数据分析有直接数据和间接数据两种支持方式，只要说明问题即可。所有的资料都要注意口径和原始数据搜集，即使 Copy 也要找权威的数据源。</p>\n<p>那么基于这个图，我们发现拼多多才是颠覆者，增长了 386%，这是非常夸张的。而阿里、京东已经比较成熟了，所以它们的涨幅差不多，所以不用刻意去纠结。基于交易额的规模，我们得出了拼多多才是颠覆者的结论，所以后面我们重点研究的对象是拼多多。</p>\n<h4>1.2.3 用户数描述</h4>\n<p>下面就是用户数的描述，大部分报告中的用户描述是这样的图，如下图左侧所示。</p>\n<figure><figcaption></figcaption></figure>\n<p>预计 2018 年中国移动电商用户超 5 亿人，通过这张图可以得出两个结论：</p>\n<ul>\n<li>\n<p>移动电商用户数一直在增长；</p>\n</li>\n<li>\n<p>移动电商用户数增长率逐年下降。</p>\n</li>\n</ul>\n<p>那么通过这张图实际上就有一个疑问：移动中国的人口年龄分布（上图右侧），移动电商用户数占比 36%，即使按照 16-59 周岁群体占比也只有 55%，从数据上看，这个行业还是有很大缺口。</p>\n<h4>1.2.4 用户数分析</h4>\n<p>上面只是描述，下面我们要进一步分析。首先我看了一下目前国内的网民数情况，如图所示。</p>\n<figure><figcaption>（数据源：中国互联网信息中心）</figcaption></figure>\n<p>我们国家总人数约为 14 亿人，网民数只有 8 个亿，而移动互联网是 7.9 亿，基本上持平。那说明网民数占比人口数 57%（8/14），这个数字并没有想象的那么高，未来仍然有很多用户可以争夺。</p>\n<p>其次我们发现，移动互联网用户数占网民数的 98% （7.88/8.02），从这个角度来看，移动互联网已经完全可替代 PC ，也就是说我们瞄准的对象是手机终端。</p>\n<p>最后，我们又发现了一个数据。这是中国互联网信息中心发布的中国网民的一个报告，如下图所示。</p>\n<figure><figcaption></figcaption></figure>\n<p>中国目前网民当中，71% 的人会产生网络购物，而用短视频的网民竟然占 74.1%。也就是说，我们之前猜测剩下的潜在用户（100-71=29%）可能在短视频里面。</p>\n<p>对于一般的分析报告，我们看出他的市场规模偏描述性统计。而作为分析师一定要在这个数据上深挖，在这个过程中，你要先知道你的目的是什么，然后你自己去找一些数据，而不是别人给你什么数，你就直接用什么数。对于市场规模，我们就已经得出几个点了，如下：</p>\n<ul>\n<li>\n<p>拼多多是颠覆者，它代表了一种增长趋势；</p>\n</li>\n<li>\n<p>网民数占比人口数 57%，这个数字并没有想象的那么高，未来仍然有很多用户可争夺（厂商）；</p>\n</li>\n<li>\n<p>我国有71% 的网络购物网民，用短视频的网民竟然占 74%，猜测剩下的潜在用户（29%）在短视频里面。</p>\n</li>\n</ul>\n<h3>1.3 社会热点事件</h3>\n<p>因为前面我们已经明确了拼多多，所以我们就针对拼多多。我们来看下拼多多的发展历程，如下所示。</p>\n<figure><figcaption></figcaption></figure>\n<p>15 年 9 月份，个人公众号上线，上线后发展极速。16 年单日流水破 2 亿，并且用户数破 2 亿。17 年用户破 3 亿，这是非常恐怖的。</p>\n<p>所以我们接下来重点看 16 年和 17 年，社会到底发生了什么事情？首先我看了一下 17 年各个省市的人均可支配收入，如图所示。</p>\n<figure><figcaption>（数据源：国家统计局的数据）</figcaption></figure>\n<p>我们发现除了上海、北京、浙江等经济大省。其他一个人均可支配收入也就 2 万块钱。所以通过这张图，我们可以发现用户是真的没钱，而市场上大家都在做一些比较高端的 App ，离用户太远了，大多数用户真的是没钱。</p>\n<p>第二个社会热点事件是微信的日活，如图所示。我们发现 16 年到 17 年，微信的日活涨得非常猛。微信以及微信支付重构了用户的社交方式。</p>\n<figure><figcaption></figcaption></figure>\n<p>第三个社会热点事件就是物流。因为对于电商来说，物流是非常重要的一环。</p>\n<figure><figcaption></figcaption></figure>\n<p>我发现 16 年和 17 年的物流总费用与 GDP 的比例低于 15 年，为何商品很便宜（ 9.9 块包邮），因为整个社会物流效率都有很明显的提升，未来人工智能的介入，这个数字应该还会更低。</p>\n<p>社会热点事件这一部分，并不是什么热点事件都看，而是要看跟我们分析对象有关的热点事件，然后用这些数据结论来支撑。</p>\n<h3>1.4 头部玩家</h3>\n<p>头部玩家这部分，我们就针对拼多多的产品和用户进行分析。</p>\n<h4>1.4.1 产品分析，特点如下</h4>\n<p>商品以日常生活用品为主（纸巾），价格很便宜。</p>\n<figure><figcaption></figcaption></figure>\n<ul>\n<li>整个体验就是快，用户基本上就一直点“下一步”就行。</li>\n</ul>\n<figure><figcaption></figcaption></figure>\n<p>当你点进来之后，比如说直接拼单，然后它那里写了一个“还差一个人拼成”，并且每一次都是这样。还差一个人不就是你了吗？然后你点拼单，直接下一步之后。你会发现，上图第三个界面是不是特别简单？如果你去对比一下手淘和京东，你会发现它非常简单粗暴，就一个购买数量和一个支付方式，而且支付方式默认是微信支付。微信支付现在已经非常普及了，所以基本上用户选的就是一个购买数量，加减即可。最下面有一大片的空白区域，什么也不放，就让你直接点下一步。</p>\n<p>同时当你点击立即支付的时候，我发现这个点它也做得很细节，上图第四个界面有一个姓名，像淘宝首次购物的支付页面，姓名要自己输。它这里不是，它这里直接是你的微信号昵称。然后在地区这一块，我不知道它是不是能拿到一些数据，地域选择那里默认的方式刚好是我所在的地域。基本上用户不用干什么就下单了，整个过程可能不到一分钟，你的东西就买完了。</p>\n<ul>\n<li>搜索功能很轻，尽量让用户懒起来</li>\n</ul>\n<p>这其中还有一个细节，第一界面里面我勾了一个圈——搜索。它的搜索功能实际上非常轻，它的搜索是在底层，目的是尽量让用户懒起来。当你进入这个 App，我跟你说那些东西好，你直接买就行，你也不用在这逛什么，买完下次再来。</p>\n<p>所以拼多多，我们通过体验一下就可以发现，它整个体验非常讲究，特别是对用户的时间成本控制很讲究。这就是拼多多的产品分析，大家在体验 App 的时候，都可以从不同的角度去分析。</p>\n<h4>1.4.2 用户分析</h4>\n<p>在用户分析这一块，我们不要摆用户的地域、年龄等信息。我们要摆能说明我们想要的信息，如图所示。</p>\n<figure><figcaption></figcaption></figure>\n<p>这里我想看一下用户为什么买拼多多，调查后发现有 41% 的用户原来在淘宝或者超市买，但是在拼多多更便宜就选择了拼多多。这对于直接竞品淘宝和京东来说，简直损失惨重。</p>\n<figure><figcaption></figcaption></figure>\n<p>同时通过上图发现，实际上拼多多的用户，一线二线的占比已经超过 40% 了，这真的不只是便宜货这么简单，其中还有一些人性的东西。所以我个人会觉得未来会出现更多的拼多多的产品。这个市场需求是非常大的，现阶段并不是特别成熟。</p>\n<p>第二个就是老大老二打架，老三很有可能会挂。我们发现拼多多与淘宝、京东、天猫的相似度远远没有唯品会高。拼多多与唯品会的重合度就是在地域方面，或者说画像上。因为唯品会实际上已经做了很多年，现在又突然跟拼多多很像，而拼多多当前又是处于一个非常强势的时期，所以唯品会确实要去思考一下自己的战略。而京东和天猫会形成一个很明显的正面竞争局面。</p>\n<p>第三个就是零售的本质还是多、快、好、省。</p>\n<ul>\n<li>\n<p>京东是物流快和好。</p>\n</li>\n<li>\n<p>淘宝天猫是多和好。</p>\n</li>\n<li>\n<p>拼多多是省和供应链快（类似于沃尔玛）。</p>\n</li>\n</ul>\n<h3>1.5 未来预测</h3>\n<p>最后，我们整体复盘一次。首先行业分析一定要有分析目标，背景是我们准备试水做电商，我们的目标是看当前还有没有切入点，以及有没有市场空间。通过界定范围，市场规模，热点事件以及头部玩家玩法，我们可以得出以下几点结论：</p>\n<ol>\n<li>\n<p>当前对于电商这个领域。仍然有大量的用户还没有进入，还有非常大的增量空间，注意这里不是存量空间，是增量空间；</p>\n</li>\n<li>\n<p>当前国内的网民数还真不是像大家想得那么多，未来厂商的争夺会更加激烈；</p>\n</li>\n<li>\n<p>短视频是非常好的一个渠道，或者说入口；</p>\n</li>\n<li>\n<p>当前，国内在人均可支配收入上面不足。大部分都是 2 万元左右，也就是说未来的用户仍然会追求性价比；</p>\n</li>\n<li>\n<p>对于拼多多 App，因为它用户的教育程度，各方面以及低于它的所见所识，相对来说都要比手淘京东要差一点。所以未来在做面向该类群体做产品的时候，要结合该类用户的特征，比如说你的产品要尽量简单粗暴，让用户快速下单；</p>\n</li>\n<li>\n<p>对于唯品会，未来拼多多对唯品会的威胁可能会大一点。</p>\n</li>\n</ol>\n<p>基于这几个观点，我们就可以形成一些建议了，然后把这些建议给管理者看一下，他们觉得是否可行。因为我们已经有了一些数据源支撑，同时在这个数据源的基础之上，我们有一些自己的观点，这个最重要。做完行业分析后，你自己都会觉得非常有意思，因为你发现了别人一些没有发现的点，这里面最重要的就是要沉下心。</p>\n<p>最后我也推荐一篇关于拼多多的文章——梁宁的万字分析：“除了假货，拼多多还有什么？”</p>\n<p>你看的过程中一定要记住，你不是单纯地去看梁宁说什么，而是一定要有自己的思考。</p>\n<p>今天的课程就到这里，如果你有什么疑问，可以在留言区留言。同时欢迎你关注我本人的公众号（微信搜索：AI悦创），之后会定期更新原创高质量的数据分析文章，下节课见，谢谢。</p>\n<details class=\"hint-container details\"><summary>公众号：AI悦创【二维码】</summary>\n<figure><img src=\"/gzh.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n</details>\n<div class=\"hint-container info\">\n<p class=\"hint-container-title\">AI悦创·编程一对一</p>\n<p>AI悦创·推出辅导班啦，包括「Python 语言辅导班、C++ 辅导班、java 辅导班、算法/数据结构辅导班、少儿编程、pygame 游戏开发、Web、Linux」，招收学员面向国内外，国外占 80%。全部都是一对一教学：一对一辅导 + 一对一答疑 + 布置作业 + 项目实践等。当然，还有线下线上摄影课程、Photoshop、Premiere 一对一教学、QQ、微信在线，随时响应！微信：Jiabcdefh</p>\n<p>C++ 信息奥赛题解，长期更新！长期招收一对一中小学信息奥赛集训，莆田、厦门地区有机会线下上门，其他地区线上。微信：Jiabcdefh</p>\n<p>方法一：<a href=\"http://wpa.qq.com/msgrd?v=3&amp;uin=1432803776&amp;site=qq&amp;menu=yes\" target=\"_blank\" rel=\"noopener noreferrer\">QQ</a></p>\n<p>方法二：微信：Jiabcdefh</p>\n</div>\n<figure><img src=\"/zsxq.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n",
      "date_published": "2025-09-23T21:43:50.000Z",
      "date_modified": "2025-09-25T13:31:03.000Z",
      "authors": [
        {
          "name": "AI悦创"
        }
      ],
      "tags": []
    },
    {
      "title": "Weekly Report",
      "url": "https://bornforthis.cn/1v1/101-Sallymisty/WeeklyReport.html",
      "id": "https://bornforthis.cn/1v1/101-Sallymisty/WeeklyReport.html",
      "summary": "2025 年 9 月 9 月 14 日 前期卷一些，后期容错率大。 Jacky 整体来说学习状态、心态都不错。理解能力目前来看还可以，因为以前没有接触过编程，不过就算是接触过编程的也不一定可以跟上学校的内容。所以需要补的其实老生常谈了，思维建立搭建中。 思维方式需要提升，刚刚好今天讲了：问题转换思想、问题拆分思想，多多复习。课上尽可能全部搞定，课后可以...",
      "content_html": "<h2>2025 年 9 月</h2>\n<h3>9 月 14 日</h3>\n<p>前期卷一些，后期容错率大。</p>\n<p>Jacky 整体来说学习状态、心态都不错。理解能力目前来看还可以，因为以前没有接触过编程，不过就算是接触过编程的也不一定可以跟上学校的内容。所以需要补的其实老生常谈了，思维建立搭建中。</p>\n<p>思维方式需要提升，刚刚好今天讲了：问题转换思想、问题拆分思想，多多复习。课上尽可能全部搞定，课后可以做其它的。</p>\n<p>记笔记的能力还可以继续提升，不过对于第一次记笔记来说 Jacky 记得整体还不错，不过及时的总结能力、表达能力这个需要慢慢提升。<br>\n——AI悦创</p>\n<p>日期：2025 年 9 月 14 日</p>\n<h3>9 月 21 日</h3>\n<p>进展正常，循序渐进。理解能力目前都还可以，记笔记的习惯可以继续改进，有较大的提升空间。足够勤奋，不够细心。其实没有其他的了，恰好今天上课讲到的：我讲的知识点只是我觉得应该要让你学会的，Jacky 要学会批判性思维多多提出我们提及或没有讲到的示例。要有足够强的探索能力培养，延伸性思考。这也是一开始说的：学编程不是单纯学语法，而是思维与逻辑。</p>\n<p>只要这个能力培养起来了，后期任何学科都是可以自己探索的。慢慢搭建吧，不用着急～</p>\n<p>日期：2025 年 9 月 21 日</p>\n<h3>9 月 28 日</h3>\n<p>本周主要完成学校的 Project、Quiz、Lab（多个 Lab）。目前没什么问题，主要就是细心一些，跟着打作业代码部分，老是会错一些：单词、标点等，不过在 Mark 作业测试时之后，还是能较快的找到自己马虎点。</p>\n<p>日期：2025 年 9 月 28 日</p>\n<h2>2025 年 10 月</h2>\n<h3>10 月 5 日</h3>\n<p>主要是记笔记和扩展思考能力部分，记笔记习惯于把代码和笔记全部记录在代码框中，这是极其不好的（上课纠正过）。因为会无形的增加未来找笔记的负担，每次找笔记都得认真阅读代码框是否是自己所要的笔记，而无法快速的找到自己想要的笔记。最好是拆分出合适的标题，以便于未来查笔记。</p>\n<p>讲完一个知识点后，不能及时的提出相对应的问题，扩展性思考需要慢慢培养，有助于未来学习习惯的培养、思考的培养等。</p>\n<p>另外：思考能力、分析能力、观察能力、感受能力需要加强培养，才能总结出不同点，这些也适用于生活。</p>\n<p>笔记记入的不够详细到位，不求逐字记录，当求主要核心内容要有，并且记笔记的时候，要考虑考虑未来查找笔记的场景，这样记入的笔记会更好！</p>\n<p>日期：2025 年 10 月 4 日</p>\n<h3>10 月 12 日</h3>\n<p>本周主要讲解了学校布置的作业、Lab、Quiz 等内容，以及下周课上学校老师有可能的提问。作业部分主打：高分通过，具体的实力提升还是在于系统学习部分。系统学习部分目前到达列表内容，细心程度较于之前提升较多。</p>\n<p>对于编辑器、ipython 的掌握有提升，计算机操作知识也有不错的提升。</p>\n<p>理解与推理能力，有一些提升。需要持续进行推理提升，因为未来要接触的都是未知的知识内容，就很需要训练出自己的研究、推理能力。</p>\n<p>今天上课石提到的列表切片赋值，这部分要特别注意：分析、观察代码的时候要带着连续思维去看，而不是独立去看。每行代码之间，都是逻辑思维的具象化体现。</p>\n<p>其实和之前类似，本周倒没什么特别要写的。继续加油吧～</p>\n<p>日期：2025 年 10 月 12 日</p>\n<h3>10 月 19 日</h3>\n<p>本周完成了学校的 Lab，不过逐步从学校的作业内容发现学校本科涉及的内容太多，学校是不 care 学生是否掌握，只求进度。并且不一定会讲，只是会提。</p>\n<p>临近期末考试，还是建议有时间再多安排时间上课。（虽然每周 9h，但面对的知识量太多）</p>\n<p>系统学习必不可免，但是有些重要知识点，但考试不一定涉及的等考完试之后再继续补充。（没讲，不代表不重要！）</p>\n<p>就算考完，还是要继续学习的。小孩自己也清楚，学校安排给他的其他学科也是有用到 Python 的。</p>\n<p>虽然，很有挑战性。一起加油！</p>\n<p>补充：对于已经讲过的知识点的熟练度不是非常高，不过可以通过查找笔记解决部分问题，需要的不是刷题，需要的是平时多思考、多复习看看笔记等。</p>\n<p>日期：2025 年 10 月 19 日</p>\n<h3>10 月 26 日</h3>\n<p>讲过的语法，都会用。但是没记住，查笔记要查半天。表明熟练度不足，熟练度不足靠刷题没用，平时有时间多翻翻笔记看看，多思考思考、多复习复习。快期末考了，老师也干着急，加油呀！</p>\n<p>学校要考的不仅仅是 Python 基础，还有数据分析、数据可视化等方面，Python 基础只是其中一部分。学校不考虑学生学的会不会，主要就是为了进度，所以涉及内容多。学生想要会，就得课后多花时间投入，加油！</p>\n<p>在考试当中，如果某个便捷函数想不到，则先手动实现。不然，无法实现直接 0 分。先实现，后面有时间再进行优化或思考。</p>\n<p>日期：2025 年 10 月 26 日</p>\n<h3>11 月 1 日</h3>\n<ol>\n<li>多复习复习内置函数名，不要全靠 Pycharm 提示，考试的编辑器没有这个功能。别到时候考试想到怎么写，但是函数写错了。</li>\n<li>不要想着什么快速便捷实现，老老实实一步步实现，考试能实现比什么都好；</li>\n<li></li>\n</ol>\n<p>学校链接：<a href=\"https://edstem.org/au/dashboard\" target=\"_blank\" rel=\"noopener noreferrer\">https://edstem.org/au/dashboard</a></p>\n<details class=\"hint-container details\"><summary>公众号：AI悦创【二维码】</summary>\n<figure><img src=\"/gzh.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n</details>\n<div class=\"hint-container info\">\n<p class=\"hint-container-title\">AI悦创·编程一对一</p>\n<p>AI悦创·推出辅导班啦，包括「Python 语言辅导班、C++ 辅导班、java 辅导班、算法/数据结构辅导班、少儿编程、pygame 游戏开发、Web、Linux」，招收学员面向国内外，国外占 80%。全部都是一对一教学：一对一辅导 + 一对一答疑 + 布置作业 + 项目实践等。当然，还有线下线上摄影课程、Photoshop、Premiere 一对一教学、QQ、微信在线，随时响应！微信：Jiabcdefh</p>\n<p>C++ 信息奥赛题解，长期更新！长期招收一对一中小学信息奥赛集训，莆田、厦门地区有机会线下上门，其他地区线上。微信：Jiabcdefh</p>\n<p>方法一：<a href=\"http://wpa.qq.com/msgrd?v=3&amp;uin=1432803776&amp;site=qq&amp;menu=yes\" target=\"_blank\" rel=\"noopener noreferrer\">QQ</a></p>\n<p>方法二：微信：Jiabcdefh</p>\n</div>\n<figure><img src=\"/zsxq.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n",
      "image": "https://bornforthis.cn/gzh.jpg",
      "date_published": "2025-09-21T20:37:23.000Z",
      "date_modified": "2025-12-07T03:19:42.000Z",
      "authors": [
        {
          "name": "bornforthis"
        }
      ],
      "tags": []
    },
    {
      "title": "「Australian National University」Quiz 7",
      "url": "https://bornforthis.cn/1v1/101-Sallymisty/Quiz/07-australian-national-university-Quiz-7.html",
      "id": "https://bornforthis.cn/1v1/101-Sallymisty/Quiz/07-australian-national-university-Quiz-7.html",
      "summary": "Question 1 Question 2 Question 3 Question 4 Question 5 Question 6 Question 7 Question 8 Question 9 Question 10 Question 11 公众号：AI悦创【二维码】 AI悦创·编程一对一 AI悦创·推出辅导班啦，包括「Python 语言辅导班、C...",
      "content_html": "<h2>Question 1</h2>\n<figure><figcaption></figcaption></figure>\n<h2>Question 2</h2>\n<figure><figcaption></figcaption></figure>\n<h2>Question 3</h2>\n<figure><figcaption></figcaption></figure>\n<h2>Question 4</h2>\n<figure><figcaption></figcaption></figure>\n<h2>Question 5</h2>\n<figure><figcaption></figcaption></figure>\n<h2>Question 6</h2>\n<figure><figcaption></figcaption></figure>\n<h2>Question 7</h2>\n<figure><figcaption></figcaption></figure>\n<h2>Question 8</h2>\n<figure><figcaption></figcaption></figure>\n<h2>Question 9</h2>\n<figure><figcaption></figcaption></figure>\n<h2>Question 10</h2>\n<figure><figcaption></figcaption></figure>\n<h2>Question 11</h2>\n<figure><figcaption></figcaption></figure>\n<figure><figcaption></figcaption></figure>\n<details class=\"hint-container details\"><summary>公众号：AI悦创【二维码】</summary>\n<figure><img src=\"/gzh.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n</details>\n<div class=\"hint-container info\">\n<p class=\"hint-container-title\">AI悦创·编程一对一</p>\n<p>AI悦创·推出辅导班啦，包括「Python 语言辅导班、C++ 辅导班、java 辅导班、算法/数据结构辅导班、少儿编程、pygame 游戏开发、Web、Linux」，招收学员面向国内外，国外占 80%。全部都是一对一教学：一对一辅导 + 一对一答疑 + 布置作业 + 项目实践等。当然，还有线下线上摄影课程、Photoshop、Premiere 一对一教学、QQ、微信在线，随时响应！微信：Jiabcdefh</p>\n<p>C++ 信息奥赛题解，长期更新！长期招收一对一中小学信息奥赛集训，莆田、厦门地区有机会线下上门，其他地区线上。微信：Jiabcdefh</p>\n<p>方法一：<a href=\"http://wpa.qq.com/msgrd?v=3&amp;uin=1432803776&amp;site=qq&amp;menu=yes\" target=\"_blank\" rel=\"noopener noreferrer\">QQ</a></p>\n<p>方法二：微信：Jiabcdefh</p>\n</div>\n<figure><img src=\"/zsxq.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n",
      "date_published": "2025-09-21T18:40:16.000Z",
      "date_modified": "2025-09-21T10:52:13.000Z",
      "authors": [
        {
          "name": "AI悦创"
        }
      ],
      "tags": []
    },
    {
      "title": "18-报告撰写：专题报告的完美标准化格式",
      "url": "https://bornforthis.cn/column/%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90%E6%80%9D%E7%BB%B4%E4%B8%8E%E5%AE%9E%E6%88%9823%E8%AE%B2/19.html",
      "id": "https://bornforthis.cn/column/%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90%E6%80%9D%E7%BB%B4%E4%B8%8E%E5%AE%9E%E6%88%9823%E8%AE%B2/19.html",
      "summary": "你好，我是悦创。 今天我主要讲解如何撰写完美的专题报告。 本课时分为三部分： 报告撰写的原则； 报告的组成部分； 报告点评示例； 1. 报告撰写的原则 报告撰写有很多原则，但这三个原则，如果你把握好了，基本上没什么问题。 主题一脉相承分叉：只有一个主题，每页 PPT 都是围绕这个主题来分叉展开。 通俗简单易懂：数据分析师的报告一定要简单易懂，文字要偏大...",
      "content_html": "<p>你好，我是悦创。</p>\n<p>今天我主要讲解如何撰写完美的专题报告。</p>\n<p>本课时分为三部分：</p>\n<ul>\n<li>\n<p>报告撰写的原则；</p>\n</li>\n<li>\n<p>报告的组成部分；</p>\n</li>\n<li>\n<p>报告点评示例；</p>\n</li>\n</ul>\n<h2>1. 报告撰写的原则</h2>\n<p>报告撰写有很多原则，但这三个原则，如果你把握好了，基本上没什么问题。</p>\n<ol>\n<li>\n<p>主题一脉相承分叉：只有一个主题，每页 PPT 都是围绕这个主题来分叉展开。</p>\n</li>\n<li>\n<p>通俗简单易懂：数据分析师的报告一定要简单易懂，文字要偏大白话。</p>\n</li>\n<li>\n<p>结论和闭环先行：要有分析结论，且落地性强。</p>\n</li>\n</ol>\n<p>下面我逐一讲解这三个原则。</p>\n<h3>1.1 主题一脉相承分叉</h3>\n<p>在主题一脉相承分叉原则里，常见两种问题。</p>\n<ul>\n<li>\n<p>专题报告没有主题。通常在报告中，这里写点，那里写点。给别人看时，别人觉得有问题，但也说不上来。如果你写的报告没有主题，那肯定是因为你对专题报告的需求没理解到位。</p>\n</li>\n<li>\n<p>专题报告有主题，但是写的逻辑有点乱，这是因为本身思维不够严谨，受到的指导太少。</p>\n</li>\n</ul>\n<p>解决办法：看别人报告是怎么写的，一页一页去斟酌。你要把自己当作写报告的人，如果是你，你会怎么去写，别人又是怎么去写。这个过程一定要去思考。</p>\n<h3>1.2 通俗简单易懂</h3>\n<p>数据分析师一定要让别人听明白你的报告。不管你是业务数据分析师，还是偏研发、偏算法的数据分析师，最终都是服务于业务。即使你不阐述 PPT，也要保证业务方能看懂，否则就是给自己挖坑。一个数据分析专题报告，如果跟你最熟的业务方都理解不了，那对于其他人来说绝对是天书。</p>\n<p>解决办法：看产品经理日常怎么写报告，因为产品经理提出的建议要让研发明白，或者需要别人协助，所以他的报告是非常通俗易懂的。</p>\n<h3>1.3 结论和闭环先行</h3>\n<p>PPT 一定要有数据结论，以及在这个结论的基础上，业务方准备怎么做。注意这里是真的准备怎么做，而不是你给的建议怎么做，数据分析用来决策而不是建议，确实很多人写专题报告还没有达到这层面。</p>\n<p>解决办法：跟业务方多沟通数据结论，让他们给出落地项，而不是你建议怎么做，因为你的建议往往推不动落地，所谓的闭环就是一定要落地。</p>\n<h2>2. 报告的组成部分</h2>\n<p>标准化的专题报告包含哪几个部分呢？我们按照先后顺序来说，如下所示。</p>\n<ul>\n<li>\n<p>背景：为何要做这份专题报告，即问题的识别。</p>\n</li>\n<li>\n<p>分析结论：如果是面向管理层的汇报，结论可以先行。</p>\n</li>\n<li>\n<p>分析框架：即问题的拆解，往往这里不需要很细。</p>\n</li>\n<li>\n<p>第一个关键点结论。</p>\n</li>\n<li>\n<p>第一个关键点的支撑数据依次摆放。</p>\n</li>\n<li>\n<p>第二个关键点结论。</p>\n</li>\n<li>\n<p>第二个关键点的支撑数据依次摆放。</p>\n</li>\n<li>\n<p>整体结论：这里把结论再汇总一次。</p>\n</li>\n<li>\n<p>落地项：产品是怎么落地的，要非常具体（时间、人、预期效果）。</p>\n</li>\n</ul>\n<p>首先是背景，一定要有背景，为何要做专题报告，即问题的识别。如果会议上的人都是非常熟悉的业务方，具体讲这份报告的时候可以不说背景，但是我们一定要把背景写上去，要不然别人都不知道这个报告到底是干什么的。</p>\n<p>其次是分析结论。如果是面向管理层的汇报，结论可以先行。当然分析结论可以在最后，也不一定非要放在第二页，但大部分时候是放在第二页，因为很多时候管理层后面没时间，所以让他看一下结论即可。</p>\n<p>然后是分析框架及问题的拆解。这就是我们前面课时介绍的问题的拆解，你要把你对这个报告大概是这么想的放出来，也就是张思维导图，思维导图摆出大的框架就行，拆的很细的可以另保存。</p>\n<p>往下是第一个关键点结论。你的分析结论实际上是由很多子结论构成，所以先把你的第一个关键点和结论摆出来，然后下一页依次摆放支撑你结论的数据，可能是好几页，作用就是来佐证你的结论。紧接着就是第二个关键点结论，同样接着摆放第二个关键点结论的支撑数据。</p>\n<p>再就是整体结论，这里我们要把结论再汇总一次，因为前面你说的这些细节之后，把结论再强调一次，别人的感受就会更深。最后给出落地项，比如产品是怎么落地的，要具体到时间、人、预期效果。</p>\n<p>标准化的专题报告包括以上这些点，如果你是下面的听众，我这样去讲这个 PPT，你听起来是不是很舒服？</p>\n<p>另外一个问题，如何衡量专题报告的价值？其实很简单，在所有的数据结论和落地项中， 只要最后有 1-2 个真的应用落地了，这就代表这份专题报告非常有含金量。哪怕你报告写得再好，最后没有结论可落地实施，那这个报告就是数据堆积，没有价值。</p>\n<h2>3. 报告点评示例</h2>\n<p>我举个具体的案例，这是某一个学员，他自己做的专题分析，我们看一下这个专题分析，看有什么问题。</p>\n<p>报告主题是彩妆行业的分析，我们先看报告目录，如图所示。</p>\n<figure><figcaption></figcaption></figure>\n<p>他把目录分为五部分：第一行业整体环境；第二彩妆行业分析；第三彩妆重点品类分析；第四彩妆重点产品分析；第五结论。下面我就直接点明问题。</p>\n<p>这个目录里面第一和第二是重复的，如果用 MECE 原则来看，行业整体环境和彩妆行业分析本身很有可能就是一回事。第三和第四部分实际上是一个子集的关系——品类和产品。当我们看完品类之后，很自然地就去看产品，所以三和四的结构是不是也可以做一些调整。第五部分根据主题一脉相承分叉原则，在问题的拆解上面还需要优化。</p>\n<p>下一页就是彩妆行业整体分析，如图所示。</p>\n<figure><figcaption></figcaption></figure>\n<p>这一页主要是讲长期趋势，有两个问题。</p>\n<ul>\n<li>\n<p>不直观。比如波峰时相对应的年份和访问数以及其他详细数据的差距没显示出来。既然是行业整体分析，首先要把大数告知听众，让这页整体更直观。</p>\n</li>\n<li>\n<p>不够通俗易懂。这位同学在后面有一个预测，实际上这幅图不太能预测，别人就会疑问你是怎么预测的。虽然这页的结论下面有写到预测方法，但写的偏专业术语，不通俗易懂。</p>\n</li>\n</ul>\n<p>我们再看下一页增长倍数的变化，如图所示。</p>\n<figure><figcaption></figcaption></figure>\n<p>这里还是通俗易懂原则。比如，增长倍数是什么意思？因为图中既有 2017 年数据，也有 2018 年数据，而且是每一周的数据。那这里的增长倍数是什么意思呢？这个标准线又是什么意思呢？如果我是业务方，我就不太好理解。所以咱们就不要用“增长倍数”这种词语，你可以描述的更详细一些。虽然说报告要图多字少，但一定要看你面对的对象是谁。如果文字不是通俗易懂，你相信我，你讲 PPT 的时候，你很可能会把自己绕晕。</p>\n<p>再看下一页周期特性，如图所示。</p>\n<figure><figcaption></figcaption></figure>\n<p>这里面有一个逻辑性疑问，周期分析属不属于行业整体分析？因为这里是说行业的一个周期，比如说 7 天一个小周期，首先它属不属于行业整体分析范畴？这个要根据具体业务范畴来定。</p>\n<p>我们再看下一页市场的集中度，如下图所示。</p>\n<figure><figcaption></figcaption></figure>\n<p>首先是通俗易懂原则，交易指数是什么？公式是什么意思？听众其实特别讨厌公式。</p>\n<p>然后就是逻辑性，市场集中度低于 30%，彩妆市场处于竞争状态。请问低于 30% 就是竞争，那多少就是不竞争呢？另外听众对头部玩家肯定很感兴趣，有哪些头部玩家呢？头部玩家的市场集中度是怎样呢？这就是思维的严谨性和逻辑性。</p>\n<p>我们再看一下客单价，如图所示。</p>\n<figure><figcaption></figcaption></figure>\n<p>首先是通俗易懂，图中的趋势是上升还是下降又或是正常波动，还真不容易看出来，那在可视化这一块是不是可以优化下。</p>\n<p>然后是思维的严谨性，这里有一段话：“考虑到通货膨胀因素，彩妆利润被进一步压缩”。通货膨胀就会使彩妆利润进一步压缩吗？这个肯定不太合适，所以说这句话的时候更加严谨一些，至少要有数据支持。</p>\n<p>我们再来看彩妆人群分析这几页，如下图所示。</p>\n<figure><figcaption></figcaption></figure>\n<figure><figcaption></figcaption></figure>\n<p>这几页的主要问题就是维度太多，字太多，不容易抓重点。其实很多人写每一页 PPT 时可能搞了很多维度，最后就会有一大堆数值罗列，实际上没有必要。如果你觉得很难把一些东西丢掉，那就直接写结论。</p>\n<p>下面这两页是细分人群的购买力分析和属性偏好分析。主要问题是逻辑思维性，需要先说基础属性，再说行为属性，且文字大多是描述性统计，没有建议更没有结论。</p>\n<figure><figcaption></figcaption></figure>\n<figure><figcaption></figcaption></figure>\n<p>最后再看这位同学写出的结论，如下图所示。</p>\n<figure><figcaption></figcaption></figure>\n<figure><figcaption></figcaption></figure>\n<p>你看完结论有什么感受？是不是觉得有道理但又觉得有问题。其实这一页应该遵循结论和闭环先行原则：</p>\n<ul>\n<li>\n<p>基于什么数据；</p>\n</li>\n<li>\n<p>发现什么结论；</p>\n</li>\n<li>\n<p>基于这个结论的建议是什么；</p>\n</li>\n<li>\n<p>基于这个建议的产品落地项是什么。</p>\n</li>\n</ul>\n<p>在写这一页的时候至少要做到前 3 项，这样业务方看完之后才知道，原来是这么回事，有理有据，有落地项有闭环。</p>\n<p>整体看下来，你有没有发现，具体到每页 PPT，大都是这里一个点，那里一个点，没有连贯性，其实这个很常见。主题的一脉相承分叉原则说起来容易，但做起来难，这需要你在工作中多实践。</p>\n<p>对于如何写好专题报告，我建议你平时多看优秀的专题报告，重点是把自己带入到场景中。比如推给你一篇文章，你看的时候一定要把自己带入到场景当中去思考，思考文章作者说的到底有没有道理，思考作者的见解，文章的架构。再就是每写一次专题分析，一定要获得他人的反馈，在这个点上，我相信写上述 PPT 的同学，他的感触应该是最深的，只有这样才能进步。</p>\n<p>今天的课程就到这里，你要好好学，然后多思考，多去和别人进行交流。如果你有问题可以在下方留言，同时欢迎你关注我本人的公众号（微信搜索：AI悦创），之后会定期更新原创高质量的数据分析文章，下节课见，谢谢。</p>\n<details class=\"hint-container details\"><summary>公众号：AI悦创【二维码】</summary>\n<figure><img src=\"/gzh.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n</details>\n<div class=\"hint-container info\">\n<p class=\"hint-container-title\">AI悦创·编程一对一</p>\n<p>AI悦创·推出辅导班啦，包括「Python 语言辅导班、C++ 辅导班、java 辅导班、算法/数据结构辅导班、少儿编程、pygame 游戏开发、Web、Linux」，招收学员面向国内外，国外占 80%。全部都是一对一教学：一对一辅导 + 一对一答疑 + 布置作业 + 项目实践等。当然，还有线下线上摄影课程、Photoshop、Premiere 一对一教学、QQ、微信在线，随时响应！微信：Jiabcdefh</p>\n<p>C++ 信息奥赛题解，长期更新！长期招收一对一中小学信息奥赛集训，莆田、厦门地区有机会线下上门，其他地区线上。微信：Jiabcdefh</p>\n<p>方法一：<a href=\"http://wpa.qq.com/msgrd?v=3&amp;uin=1432803776&amp;site=qq&amp;menu=yes\" target=\"_blank\" rel=\"noopener noreferrer\">QQ</a></p>\n<p>方法二：微信：Jiabcdefh</p>\n</div>\n<figure><img src=\"/zsxq.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n",
      "date_published": "2025-09-21T16:08:15.000Z",
      "date_modified": "2025-09-21T10:01:39.000Z",
      "authors": [
        {
          "name": "AI悦创"
        }
      ],
      "tags": []
    },
    {
      "title": "「Australian National University」Homework 4：Game of Life",
      "url": "https://bornforthis.cn/1v1/101-Sallymisty/Homework/04-australian-national-university-homework4-game-of-life.html",
      "id": "https://bornforthis.cn/1v1/101-Sallymisty/Homework/04-australian-national-university-homework4-game-of-life.html",
      "summary": "Your goal in this assignment is to implement a famous mathematical \"game\" (or cellular automata to use the correct term) the Game of Life, also known as Life. It was devised by ...",
      "content_html": "<p>Your goal in this assignment is to implement a famous mathematical \"game\" (or <em>cellular automata</em> to use the correct term) the <a href=\"https://en.wikipedia.org/wiki/Conway's_Game_of_Life\" target=\"_blank\" rel=\"noopener noreferrer\"><strong>Game of Life</strong></a>, also known as <strong>Life</strong>. It was devised by the British mathematician John Conway in 1970.</p>\n<h2>1. Practical information</h2>\n<p>The assignment must be submitted in Ed Lessons before <strong>Sunday the 28th of September, at 11:55PM</strong> (5 min before midnight). <strong>This deadline is hard!</strong> Unlike other courses, we do not give partial mark for late submission. We will only grant extension in exceptional circumstances, see <a href=\"https://comp.anu.edu.au/courses/comp1730/assessments/#late-submissions-and-extensions\" target=\"_blank\" rel=\"noopener noreferrer\">our policy</a> on the course assessment page.</p>\n<p>You can submit it as many times as you like and only the mark of the last submission will be used. You can submit it as many times as you like and only the mark of the last submission will be used. To submit: Click the <strong>Start Attempt</strong> button in blue at the top right, then click <strong>Submit</strong>. Clicking Run or Test does NOT submit your work.</p>\n<div class=\"hint-container warning\">\n<p class=\"hint-container-title\">注意</p>\n<p>We do not accept any excuses about technical problems like internet connection or computer issues, as you have plenty of time from the release of the assignment to the deadline. <strong>Do not wait until the last minute!</strong></p>\n</div>\n<p><strong>The homework is individual</strong>. You must write your own solution and you are expected to be able to explain every aspect of it. You are not allowed to share your solution (code) with other students; this includes posting it (or parts of it) to the discussion forum, or to any other online platforms. <strong>You may be contacted for an additional oral assessment</strong>, which may result in a change of mark.</p>\n<p>If you have questions: ask the tutor in your lab or look up Ed Discussion forum for similar question (only post your question if not found).</p>\n<h2>2. The problem</h2>\n<p>The Game of Life is \"played\" on a board, which is a <strong>2D (two-dimensional) grid of cells</strong>. Cells are either dead (represented as an integer <code>0</code> on the board) or alive (an integer <code>1</code> on the board). Life runs over several steps (generations). At each step we start from a given configuration of the board (i.e., distribution of live and dead cells), and we generate the next board according to the following rules:</p>\n<ol>\n<li>A live cell with zero or one live neighbours dies (underpopulation),</li>\n<li>A live cell with two or three live neighbours survives (i.e., remains alive in the next generation),</li>\n<li>A live cell with more than three live neighbours dies (overpopulation),</li>\n<li>A dead cell with exactly three live neighbours becomes a live cell (reproduction).</li>\n</ol>\n<figure><figcaption></figcaption></figure>\n<p>Fig 1. The blue cell has eight neighbours (C-Centre, N-North, S-South, E-East, W-West etc). Cells at the edge of the board will have less than 8 neighbours.</p>\n<h2>3. How to represent the board in Python</h2>\n<p>There are several possible choices to represent the 2D grid of numbers. From the data structures we have seen so far we may either use a <strong>list of lists</strong> (Lectures 5 and 6) or a <strong>2D NumPy array</strong> (Lecture 7). You may choose which one of the two data structures you prefer. We have provided you with two scaffold code files:</p>\n<ul>\n<li>if you choose to use a <strong>list of lists</strong> data structure then use <code>game_of_life.py</code>, or</li>\n<li>if you choose to use a <strong>NumPy array</strong> data structure then use <code>game_of_life_numpy.py</code>.</li>\n</ul>\n<p><strong>You must fill in your UID and name in the python file you chose to proceed, and only that file will be marked. Do NOT update the other file.</strong></p>\n<div class=\"hint-container warning\">\n<p class=\"hint-container-title\">注意</p>\n<p>You MUST write your functions solely in one of the two files, i.e., the one you chose, and leave the other file untouched.  <strong>If you fail to do that, we may incorrectly mark your submission!</strong></p>\n</div>\n<p><strong>Task 1.</strong> Write a function <code>count_live_neighbours(board, row, column)</code> which returns the number of <strong>live</strong> neighbours of a cell, given a <code>board</code> and the coordinates of the cell on the board given by <code>row</code> and <code>column</code>, i.e., the cell at <code>board[row][column]</code>. You can assume that <code>row</code> and <code>column</code> are non-negative integers and within the boundaries of the board. Write your implementation of <code>count_live_neighbours</code> in the scaffold code file. The template function has only a <code>pass</code> statement which you should replace with your code.</p>\n<p><strong>Task 2.</strong> Write a function <code>generate_next_board(board)</code> in the scaffold file that, given the current board, generates the next board. Both <code>board</code> and the returned value are Life boards. <strong>You must NOT modify <code>board</code></strong>. Instead, you should work with a copy of <code>board</code> which can be modified and returned. (Think why!).</p>\n<p>For both tasks 1 and 2 you can assume that:</p>\n<ul>\n<li>All values on the board are either an integer <code>0</code> or an integer <code>1</code>.</li>\n<li>The board is rectangular. (you cannot assume that the board is square).</li>\n<li>In the case of a <em>list of lists</em>, you can also assume that all sub-lists in the list of lists have the same length.</li>\n</ul>\n<p>For both tasks 1 and 2 you must follow this restriction:</p>\n<ul>\n<li><strong>You must not import any modules except <code>copy</code>, <code>numpy</code> and <code>matplotlib</code>.</strong></li>\n</ul>\n<p>To test your code, click the \"Test\" button at the bottom right of the workspace. The scaffold file also has two testing functions <code>test_count_live_neighbors()</code> and <code>test_generate_next_board()</code> that will run the same tests as when you click the Test button. In case you use your \"favorite\" IDE to implement the function, you can run this function to test the code yourself. To submit your code, click the \"Submit\" button at the top right corner:</p>\n<figure><figcaption></figcaption></figure>\n<h2>4. Animated Evolution</h2>\n<p>We have provided other functions in the scaffold code file for your pleasure: <code>draw_board(board)</code> will be useful when you start designing your own boards, and <code>evolve_life(initial_generation, number_steps, filename)</code> which will run your <code>generate_next_board</code> for <code>number_steps</code> and will generate a GIF animated file ! To generate the animated file with an evolution, you can call one of the provided <code>evolve_life_pattern(...)</code> functions. For example calling <code>evolve_life_beacon(10)</code> will generate a file named <code>beacon.gif</code> with an oscillating pattern of periodicity 2 called \"Beacon\":</p>\n<figure><figcaption></figcaption></figure>\n<p>In the scaffold code file you will also find functions for the well known <a href=\"https://en.wikipedia.org/wiki/Conway's_Game_of_Life#/media/File:Gospers_glider_gun.gif\" target=\"_blank\" rel=\"noopener noreferrer\">\"Glider Gun\"</a>, and \"line\" and \"box\" which display simpler boards that you can easily experiment with.</p>\n<p>Ask your tutor if you're not sure how to use these functions.</p>\n<p>And there are many other interesting boards in the Wikipedia <a href=\"https://en.wikipedia.org/wiki/Conway's_Game_of_Life\" target=\"_blank\" rel=\"noopener noreferrer\"><strong>Game of Life</strong></a> reference. Check them out. Sorry no bonus marks, but lots of fun if you can get them going!</p>\n<div class=\"hint-container warning\">\n<p class=\"hint-container-title\">注意</p>\n<p>Submit your code with the calls to <code>evolve_life</code> commented out. Otherwise, the automarking scripts may fail to provide to mark your assignment.</p>\n</div>\n<div class=\"hint-container warning\">\n<p class=\"hint-container-title\">注意</p>\n<p>Some students have reported issues with Safari web browser on MacOsX in regards to the GIF file generation. The workaround is to use Google Chrome web browser instead.</p>\n</div>\n<h2>5. Testing and Marking</h2>\n<p>Like homework 3, we will be marking your submission on <em>both code quality and correctness</em>.</p>\n<p><strong>Code quality</strong></p>\n<p>Code quality has been covered in the week 4 lecture. It includes aspects such as:</p>\n<ul>\n<li>Using meaningful and intention-revealing function, parameter and variable names. The names of some functions in the homework are fixed, but if you define additional functions (to decompose the problem) then they should be given descriptive names.</li>\n<li><em>Appropriate</em> use of comments and docstrings. This means not too little comments but also not too much. Comments should be accurate, relevant, and readable. Docstrings should be used only as the first statement in a function definition.</li>\n<li>Good code organisation. This includes appropriate use of functions to decompose a problem and avoid code repetition.</li>\n</ul>\n<p>To earn a good score, you <strong>must</strong> demonstrate your understanding of code quality by introducing at least one well-structured new function to reduce repetition, including some appropriate comments to clarify your logic, and adding docstrings to all functions required in the tasks and any helper functions created.</p>\n<p><strong>Code correctness</strong></p>\n<p>Your code will be marked with auto-testing. Clicking on the \"Test\" button will only test it on a limited number of test cases, which will show you which test cases you passed or failed. Failing at least one test case means that your code is wrong.</p>\n<div class=\"hint-container warning\">\n<p class=\"hint-container-title\">注意</p>\n<p>Passing all the tests does not necessarily means that your code is correct, as only a small number of test cases are done. In the final marking of your assignment we will use a much larger set of test cases, and your code might fail additional tests.</p>\n</div>\n<p>Your code must meet the following requirements:</p>\n<ul>\n<li>You must not change the file name <code>game_of_life.py</code> and <code>game_of_life_numpy.py</code>.</li>\n<li>It must be syntactically correct python code.</li>\n<li>It must contain only function definitions and import statements; comments, including docstrings (if they are used appropriately) are of course ok to include. <strong>Anything else such as the use of global variables may be penalised when we check your submission</strong>.</li>\n<li>You must keep the first 12 lines of the python file exactly as they are, except that you must replace the dummy value \"u1234567\" with your own ANU ID, and \"Firstname Lastname\" with your first and last names.</li>\n</ul>\n<p>In marking this assignment we will consider the following:</p>\n<ul>\n<li>Did you put your name and uID at the top of the file for the selected implementation, and <strong>ONLY</strong> that file?</li>\n<li>Does your submitted file satisfy the requirements specified above?</li>\n<li>Are your functions correct for all valid arguments?</li>\n<li>Do your functions always return a value of the correct type?</li>\n<li>The quality of your code (see above).</li>\n</ul>\n<p>We will apply penalties for submissions that do not fulfill formal aspects, such as missing name and/or uID.</p>\n<p>The assignment is worth 5% of your final mark, including 3% for code correctness and 2% for code quality.</p>\n<h2>6. Scaffold files</h2>\n<p>These might be useful either for working offline or if you want to start fresh after an initial failed attempt</p>\n\n",
      "date_published": "2025-09-19T09:14:10.000Z",
      "date_modified": "2025-09-24T08:10:12.000Z",
      "authors": [
        {
          "name": "AI悦创"
        }
      ],
      "tags": [
        "Python一对一答疑帖",
        "留学生Python辅导",
        "Australian National University一对一辅导"
      ]
    },
    {
      "title": "「Australian National University」Lab 6：Lists (advanced) and tuples. Data analysis.",
      "url": "https://bornforthis.cn/1v1/101-Sallymisty/Lab/06-australian-national-university-lab6-lists-advanced-tuples-data-analysis.html",
      "id": "https://bornforthis.cn/1v1/101-Sallymisty/Lab/06-australian-national-university-lab6-lists-advanced-tuples-data-analysis.html",
      "summary": "1. Introduction The purpose of this week's lab is to: Review Python's built-in sequence types: lists and tuples. Contrast a reference to an object with a copy of an object, in t...",
      "content_html": "<h2>1. Introduction</h2>\n<p>The purpose of this week's lab is to:</p>\n<ul>\n<li>Review Python's built-in sequence types: lists and tuples.</li>\n<li>Contrast a reference to an object with a copy of an object, in the context of lists.</li>\n<li>Write our first data analysis programs operating on CSV data files with the help of list comprehensions.</li>\n</ul>\n<blockquote>\n<p>If you do not have time to finish all exercises (in particular, the programming problems) during the lab time, you can continue working on them later.</p>\n</blockquote>\n<blockquote>\n<p>If you have any questions about or difficulties with any of the material covered in the course so far, ask your tutor for help during the lab.</p>\n</blockquote>\n<h2>2. Warm-up exercise: Lists are mutable BUT strings are not</h2>\n<p>Operations on python's built-in sequence types are summarised in <a href=\"https://docs.python.org/3/library/stdtypes.html#sequence-types-list-tuple-range\" target=\"_blank\" rel=\"noopener noreferrer\">this section of the python library reference</a>. You may want to revisit <a href=\"https://edstem.org/au/courses/17427/lessons/59826/\" target=\"_blank\" rel=\"noopener noreferrer\">Lab 5</a> to remind yourself of how indexing and slicing work on sequences, as well as the operations available on sequences.</p>\n<p>Because lists are mutable but strings are not, you can assign a new element to an index in the list, or a list to a slice of the list, but you <strong>cannot</strong> do this with strings. Try the following on a python interpreter to convince yourself this is the case:</p>\n<div class=\"language-python line-numbers-mode has-collapsed-lines collapsed\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--vp-collapsed-lines:15;--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: a_str </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> \"acd\"</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: a_str[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">Out [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">...</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: a_str[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">] </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> 'b'</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">4</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: a_str</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">Out [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">4</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">...</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">5</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: a_list </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">4</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">6</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: a_list[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">] </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 2</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">7</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: a_list</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">Out [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">7</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">...</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">8</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: a_list[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">4</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">] </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">5</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">7</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">9</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: a_list</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">Out [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">9</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">...</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div><div class=\"collapsed-lines\"></div></div><h2>3. Mutable objects and references</h2>\n<p>In python, every value computed by the interpreter is an <strong>object</strong>. An object in python has:</p>\n<ul>\n<li>An identity: This is a number assigned by the python interpreter when an object is created. You can access this number using the <code>id</code> function. Examining the identity of an object is typically not useful in the programs you write, but it will sometimes help you to understand what is happening.</li>\n<li>Some attributes: This is information about the object. An attribute that every object has is a <strong>type</strong>, which tells us (and the python interpreter) what kind of object it is. Other attributes tell us something about the \"content\" of the object (for example, if the object is of type <code>int</code>, that is, an integer, what integer it is).</li>\n</ul>\n<p>When we assign a value to variable, the variable name is associated with a <strong>reference</strong> to the object; that is, essentially, the object's identity. Several variables can refer to the same object.</p>\n<p>A <strong>mutable</strong> object is one that can be modified. This means that we can change the object's attributes. The object's identity remains unchanged.</p>\n<blockquote>\n<p>Downey's book describes mutable objects (specifically, lists) and aliasing (multiple names referring to the same object) in Chapter 10.</p>\n</blockquote>\n<h2>4. Exercise 1: Mutable objects and references (I)</h2>\n<p>The following code attempts to construct a table containing the first three rows of the <a href=\"https://en.wikipedia.org/wiki/Periodic_table\" target=\"_blank\" rel=\"noopener noreferrer\">periodic table</a>. Run the following commands in the python shell:</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: row1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">[</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"H\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"He\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: row2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">[</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"Li\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"Be\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"B\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"C\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"N\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"O\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"F\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"Ar\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: row3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">[</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"Na\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"Mg\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"Al\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"Si\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"P\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"S\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"Cl\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"Ne\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">4</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: ptable</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">row1</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">5</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: ptable.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">extend</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(row2)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">6</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: ptable.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">extend</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(row3)</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><ul>\n<li>What is the value of <code>ptable</code> now?</li>\n<li>What is the value of <code>row1</code> now? Is this what you expected?</li>\n<li>Correct the error in <code>row2</code> (\"Ar\" should be \"Ne\") by executing a command of the form <code>row2[?] = ?</code>. (The question mark means it is for you to figure out what is the right index to change. You should <strong>not</strong> write a literal <code>?</code>) What happens to <code>ptable</code> as a result of this assignment?</li>\n<li>Correct the error in <code>row3</code> (\"Ne\" should be \"Ar\") by executing a command of the form <code>ptable[?] = ?</code>. What happens to <code>row3</code> as a result of this assignment?</li>\n</ul>\n<p>Give the above a try yourself first.</p>\n<p>After that, [try stepping through and visualising the example using the on-line tool <a href=\"http://pythontutor.com\" target=\"_blank\" rel=\"noopener noreferrer\">pythontutor.com</a> here](<a href=\"https://pythontutor.com/python-debugger.html#code=row1%3D%5B%22H%22,%22He%22%5D\" target=\"_blank\" rel=\"noopener noreferrer\">https://pythontutor.com/python-debugger.html#code=row1%3D[\"H\",\"He\"]</a> row2%3D[\"Li\",\"Be\",\"B\",\"C\",\"N\",\"O\",\"F\",\"Ar\"] row3%3D[\"Na\",\"Mg\",\"Al\",\"Si\",\"P\",\"S\",\"Cl\",\"Ne\"] ptable%3Drow1 ptable.extend(row2) ptable.extend(row3)&amp;cumulative=false&amp;heapPrimitives=nevernest&amp;mode=edit&amp;origin=opt-frontend.js&amp;py=3&amp;rawInputLstJSON=[]&amp;textReferences=false). We have already copied the code in and set the right settings for you in the link above. Just click the \"Visualize Execution\" button to start. See if what is happening matches what you expected to happen.</p>\n<p>To help explain what is happening, you can also use the <code>id</code> function to see the identities of the objects referenced by each of the variables:</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">7</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">id</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(row1)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">Out [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">7</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">...</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">8</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">id</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(row2)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">Out [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">8</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">...</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">9</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">id</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(row3)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">Out [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">9</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">...</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">10</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">id</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(ptable)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">Out [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">10</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">...</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>You should find that <code>row1</code> and <code>ptable</code> both reference the same object (a list), but that the contents of <code>row2</code> and <code>row3</code> were copied into <code>ptable</code>.</p>\n<h2>5. Exercise 2: Mutable objects and references (II)</h2>\n<p>Now execute the following commands (make sure you redefine the rows):</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: row1 </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> [</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"H\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"He\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: row2 </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> [</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"Li\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"Be\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"B\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"C\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"N\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"O\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"F\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"Ar\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: row3 </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> [</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"Na\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"Mg\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"Al\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"Si\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"P\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"S\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"Cl\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"Ne\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">4</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: ptable </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> [row1]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">5</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: ptable.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">append</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(row2)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">6</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: ptable.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">append</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(row3)</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><ul>\n<li>What is the value of <code>ptable</code> now? How does this differ from what you had in Exercise 1?</li>\n<li>What is the value of <code>row1</code> now? How does it differ from what you had in Exercise 1?</li>\n<li>To get the first element of the first row from <code>ptable</code>, you would use the expression <code>ptable[0][0]</code>. Write the expressions to get the sixth element from the second row (\"O\") and the second element from the third row (\"Mg\"). Use only the <code>ptable</code> variable, not <code>row2</code> or <code>row3</code>.</li>\n<li>Correct the error in row 2 (\"Ar\" should be \"Ne\") by executing a command of the form <code>row2[?] = ?</code>. Does this also change <code>ptable</code>?</li>\n<li>Correct the error in row 3 (\"Ne\" should be \"Ar\") by executing a command of the form <code>ptable[?][?] = ?</code>. Does this change <code>row3</code>? And <code>ptable</code>?</li>\n</ul>\n<p>Again, you can use the <code>id</code> function to see the identities of the objects involved (try both <code>id(ptable)</code> and <code>id(ptable[0])</code>). You should find that each element in <code>ptable</code> is a reference to one of the row lists.</p>\n<p>Again, if you want to visualise what is going on, try <a href=\"http://pythontutor.com/\" target=\"_blank\" rel=\"noopener noreferrer\">pythontutor.com</a>. Copy the code you want to test into the text box and click the \"Visualize Execution\" button. Remember to make sure you have selected \"Python 3\" in the menu above where you enter the code.</p>\n<h2>6. Exercise 3: Shallow and deep copies (I)</h2>\n<p>In Exercise 1, you assigned <code>ptable</code> the list referenced by <code>row1</code> via the statement <code>ptable = row1</code>. Subsequent operations showed that <code>ptable</code> and <code>row1</code> referenced the same object (list). How do we actually make a copy of a list?</p>\n<p>Execute the following commands:</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: row2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">[</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'Li'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'Be'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'B'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'C'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'N'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'O'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'F'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'Ar'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: ptable1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">[</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"H\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"Xe\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,row2]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: ptable2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">ptable1[:]</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><ul>\n<li>Is <code>ptable1</code> a list, a list of lists or a mix of both? (Print it out!)</li>\n<li>Correct element \"Xe\" in <code>ptable2</code> to be \"He\". Is the change propagated to <code>ptable1</code>?</li>\n<li>Correct element \"Ar\" in <code>ptable2</code> to be \"Ne\". Is the change propagated to <code>ptable1</code> and to <code>row2</code>?</li>\n</ul>\n<p>You should find that after executing <code>ptable2=ptable1[:]</code> <code>ptable2</code> is a copy of <code>ptable1</code> (not having the same <code>id</code>) but the third element is a reference to <code>row2</code>. The effect of adding <code>[:]</code> to the <code>ptable2=ptable1</code> assignment is to create a so-called <strong>shallow copy</strong> of <code>ptable1</code>.</p>\n<p>Unclear? Visualize the code in <a href=\"http://pythontutor.com/\" target=\"_blank\" rel=\"noopener noreferrer\">pythontutor.com</a>, or ask your tutor for help.</p>\n<h2>7. Exercise 4: Shallow and deep copies (II)</h2>\n<p>Execute the following commands</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: row2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">[</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'Li'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'Be'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'B'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'C'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'N'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'O'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'F'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'Ar'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: ptable1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">[</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"H\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"Xe\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,row2]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">import</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> copy</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">4</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: ptable2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">copy.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">deepcopy</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(ptable1)</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><ul>\n<li>Now correct the \"Ar\" to \"Ne\" by assigning the right element of <code>ptable2</code>. Inspect to see whether the elements of <code>ptable1</code> or <code>row2</code> have changed. (You should find no changes.)</li>\n</ul>\n<blockquote>\n<p>Think carefully before using <code>deepcopy</code>: it is much slower and consumes more memory than shallow copy; it may also cause problems with circular references (such as list containing a reference to itself). Any problems with shared references can always be avoided by thinking more carefully about how you have structured your code.</p>\n</blockquote>\n<h2>8. Exercise 5: Sequence type: tuples</h2>\n<p>Python has another built-in sequence type, called a <code>tuple</code>. Like a list, tuples can contain any type of value, including a mix of value types. The difference between type <code>list</code> and type <code>tuple</code> is that tuples are <strong>immutable</strong>.</p>\n<p>To create a tuple, you only need to write its elements separated by commas:</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: aseq </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">4</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">type</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(aseq)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">Out [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">...</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>It is common practice to write a tuple in parentheses, like this:</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: aseq </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> (</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">4</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">type</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(aseq)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">Out [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">...</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>and the python interpreter will usually print tuples enclosed in parentheses. However, it is the comma that creates the tuple, not the parentheses! To see this, try the following:</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: x </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> (</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">type</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(x)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">Out [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">...</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: x </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">4</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">type</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(x)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">Out [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">4</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">...</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>There is one exception: To create an empty tuple (a tuple with length zero), you have to put a comma between nothing and nothing! Typing <code>x = ,</code> does not work. Instead, use an empty pair of parentheses to create an empty tuple, like this: <code>x = ()</code>.</p>\n<h2>9. Exercise 6: Practice with tuples</h2>\n<p>Retry the tests you did in <a href=\"https://edstem.org/au/courses/17427/lessons/59826/slides/407652\" target=\"_blank\" rel=\"noopener noreferrer\">Exercise 2 in Lab 5</a> with tuple values (instead of lists):</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: aseq </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> (</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">4</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: bseq </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">4</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">type</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(aseq)        </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 1. what type of sequence is this?</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">Out [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">...</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">                          # 2 - 9 as before.</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>Also try assigning to an element and to a slice of the tuple, as in Exercise 0: this should give you an error, because the tuple type is immutable.</p>\n<h2>10. Exercise 7: Debugging (optional)</h2>\n<p>Just like strings, the <code>list</code> data type has several useful methods. For example, read <code>help(list.append)</code>, <code>help(list.insert)</code> and <code>help(list.extend)</code> to see the documentation of some of the methods that modify lists. Modifying methods and operations for mutable sequence types (i.e., list) are summarised in <a href=\"https://docs.python.org/3/library/stdtypes.html#mutable-sequence-types\" target=\"_blank\" rel=\"noopener noreferrer\">this section of the python documentation</a>.</p>\n<p>On the right, the are two attempts to write a function, <code>make_list_of_lists</code>. This function creates a list of <code>n</code> lists of increasing ranges of integers. The first entry in the returned list should be an empty list, the second a list of length one, ending with the number 1, and so on. For example, <code>make_list_of_lists(3)</code> should return <code>[ [], [1], [1, 2] ]</code>. (Note that <code>n</code> must be a non-negative integer.) However, both functions are incorrect. Locate the error in each function, explain why it goes wrong and fix it.</p>\n<div class=\"language-python line-numbers-mode has-collapsed-lines collapsed\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--vp-collapsed-lines:15;--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># The function below does not work as </span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># intended. Find the error and fix it.</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> make_list_of_lists_attempt1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">n</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">\tthe_list </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> []</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">\tsublist </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> []</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">\twhile</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> n </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&gt;</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">\t\tthe_list.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">append</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(sublist)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">\t\tsublist.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">append</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(sublist) </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">\t\tn </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> n </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 1</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">\treturn</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> the_list</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># The function below does not work as </span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># intended. Find the error and fix it.</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> make_list_of_lists_attempt2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">n</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">\tthe_list </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> []</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">\tsublist </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> []</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">\tfor</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> i </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> range</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(n):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">\t\tthe_list.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">extend</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(sublist)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">\t\tsublist </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> sublist.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">insert</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(sublist), i)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">\treturn</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> the_list</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div><div class=\"collapsed-lines\"></div></div><h3>10.1 Solution</h3>\n<div class=\"language-python line-numbers-mode has-collapsed-lines collapsed\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--vp-collapsed-lines:15;--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># The function below does not work as </span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># intended. Find the error and fix it.</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> make_list_of_lists_attempt1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">n</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">\tthe_list </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> []</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">\tsublist </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> []</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">\twhile</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> n </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&gt;</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">\t\tthe_list.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">append</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(sublist.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">copy</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">())</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">\t\tsublist.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">append</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(sublist) </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">\t\tn </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> n </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 1</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">\treturn</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> the_list</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># The function below does not work as </span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># intended. Find the error and fix it.</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> make_list_of_lists_attempt2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">n</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">\tthe_list </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> []</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">\tsublist </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> []</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">\tfor</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> i </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> range</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(n):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">\t\tthe_list.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">append</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(sublist.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">copy</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">())</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">        sublist.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">append</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(i </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">\treturn</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> the_list</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div><div class=\"collapsed-lines\"></div></div><h2>11. Data analysis with CSV files and list comprehensions</h2>\n<p>Data analysis problems will typically require you to:</p>\n<ul>\n<li>read data from one or more files;</li>\n<li>organise the data into a table and convert it to the correct type; and</li>\n<li>deal with entries in the table where some data is missing.</li>\n</ul>\n<p>Ways to do these steps were covered in the lecture of week 6. Below is a quick recap.</p>\n<h3>11.1 CSV files</h3>\n<p>The file format we will be using in the lab is <em>Comma-Separated Values</em>, or CSV, files. To read in a CSV file, the following steps suffice:</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">import</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> csv</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">with</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> open</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"filename.csv\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">) </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">as</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> csvfile:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    reader </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> csv.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">reader</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(csvfile)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    table </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> [ row </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> row </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> reader ]</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>After this piece of code is executed, the variable <code>table</code> is a list of lists, with one entry per row in the file. Two things to remember are:</p>\n<ul>\n<li>After reading the file, all entries in all rows will be strings.</li>\n<li>If the file contains a header (that is, the entries in the first row are the names or descriptions of the columns rather than values), the first row in <code>table</code> will contain this header. You can use, e.g., list slicing to get a table without the header.</li>\n</ul>\n<h3>11.2 List comprehensions</h3>\n<p>List comprehensions are a mechanism in python that allows you to create new lists from a sequence in a very convenient way.</p>\n<p>In this lab, you can use list comprehensions to</p>\n<ul>\n<li>Convert selected entries in all rows to a type other than string (such as a number).</li>\n<li>Extract a single column from the table as a list.</li>\n<li>Select only rows from the table (or entries from a column) that satisfy some criterion, for example not having any blank fields.</li>\n</ul>\n<p>For example, the expression</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">col3 </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> [ row[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">] </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> row </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> table ]</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div></div></div><p>creates a list with the entries in column 3 (i.e., the fourth column, since columns are also zero-indexed in this representation), and the expression</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">table_non_empty_col3 </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> [ row </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> row </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> table </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> row[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">] </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">!=</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> ''</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> ]</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div></div></div><p>creates a new table containing only the rows in <code>table</code> that have a non-empty value in column 3.</p>\n<p>The built-in <code>range</code> function creates an iterable collection of integers, which can be very useful together with list comprehension (and also <code>for</code> loops). For example,</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">ind_non_empty_col3 </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> [ i </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> i </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> range</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(table)) </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> table[i][</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">] </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">!=</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> ''</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> ]</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div></div></div><p>creates a list of the <strong>indices</strong> of rows in <code>table</code> that have a non-empty value in column 3.</p>\n<p>The <code>range</code> function can take both a start and stop value. For example,</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">years </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> range</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2008</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2022</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div></div></div><p>creates a range of the integers from 2008 to 2021 (note that the range is up to, but not including, the stop value). For more details, read the documentation with <code>help(range)</code>.</p>\n<p>The selection condition used in a list comprehension can be any expression that evaluates to a truth value. For example, if you have written a function <code>is_prime(n)</code> that returns <code>True</code> if the number <code>n</code> is a prime number, then you can create a list of all the prime numbers between 1 and 100 with the expression</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">list_of_primes </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> [ i </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> i </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> range</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">101</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">) </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> is_prime</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(i) ]</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div></div></div><p>The expression that creates the values in the new list can also be of any kind (as long as it is an expression). For example,</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">[ [ row[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">], row[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">], </span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">float</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(row[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]), </span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">int</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(row[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]) ] </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> row </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> table ]</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div></div></div><p>creates a new table where all entries in column 2 have been converted to floating point numbers and all entries in column 3 have been converted to integers, while columns 0 and 1 have been left as they are (strings). Remember that trying to convert an empty string into a number (<code>int</code> or <code>float</code>) will cause a runtime error. One way to solve this is to filter out rows with empty entries first (as shown above) and then convert those that remain. However, you can also use a function that you have defined. For example,</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">[ </span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">my_fun</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(row[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]) </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> row </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> table ]</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div></div></div><p>returns a list with the result of applying <code>my_fun</code> to every entry in column 3, where <code>my_fun</code> can be any function (of one argument).</p>\n<h2>12. Programming problems</h2>\n<p>In the rest of the lab, you will have to solve four more advanced programming problems. We don't expect everyone to finish all these problems during the lab time. If you do not have time to finish them in the lab, you should continue working on them later.</p>\n<h3>12.1 Programming problem 1: Pop and slice</h3>\n<p>The list method <code>pop(position)</code> removes the element in the given position from the list (read <code>help(list.pop)</code> or <a href=\"https://docs.python.org/3/library/stdtypes.html#mutable-sequence-types\" target=\"_blank\" rel=\"noopener noreferrer\">the on-line documentation</a>).</p>\n<p><strong>Task 1.</strong> Write a function <code>allbut(a_list, index)</code>, which takes as arguments a list and an index, and returns a <strong>new list</strong> with all elements of the argument list (in the order they were) except for the element at <code>index</code>. The argument list should <strong>not be modified</strong> by the function.</p>\n<p>Example:</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: my_list </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">4</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: my_short_list </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> allbut</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(my_list, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(my_short_list) </span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">4</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">4</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(my_list) </span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">4</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p><strong>Task 2.</strong> A slice expression, <code>a_list[start:end]</code>, returns a new list with the elements from <code>start</code> to <code>end - 1</code> of the list. Write a function <code>slice_in_place(a_list, start, end)</code>, which takes as arguments a list and two non-negative indices, and modifies the argument list so that it is equal to the result of the slice expression <code>a_list[start:end]</code>. The function should <strong>not</strong> return any value.</p>\n<p>Example:</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: my_list </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">4</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">slice_in_place</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(my_list, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(my_list) </span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>You may want to address, as an optional take-home exercise (that won't be tested/assessed), how to modify your <code>slice_in_place</code> function such that it is able to work with both positive and negative indices (like slicing does).</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> allbut</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">a_list</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> index</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">    #</span><span style=\"--shiki-light:#A626A4;--shiki-light-font-style:italic;--shiki-dark:#C678DD;--shiki-dark-font-style:italic\">TODO</span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">: implement this function</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    pass</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> slice_in_place</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">a_list</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> start</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> end</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">    # </span><span style=\"--shiki-light:#A626A4;--shiki-light-font-style:italic;--shiki-dark:#C678DD;--shiki-dark-font-style:italic\">TODO</span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">: implement this function</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    pass</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><h4>12.1.1 Solution</h4>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> allbut</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">a_list</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> index</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    n </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(a_list)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">    # 规范化负索引</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> index </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&lt;</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">        index </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> n</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> index </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&lt;</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 0</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> or</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> index </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&gt;=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> n:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        raise</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#ABB2BF\"> IndexError</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"list index out of range\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> a_list[:index] </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> a_list[index</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:]</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> slice_in_place</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">a_list</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> start</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> end</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    a_list[:] </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> a_list[start:end]</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><h3>12.2 Programming problem 2: List shuffle</h3>\n<p>Sorting a list puts the elements in order; shuffling it puts them in (more or less) disorder. The python module <code>random</code> implements a function called <code>shuffle</code> which randomly shuffles a list. Here, we will look at a deterministic (non-random) shuffle of a list. A \"perfect shuffle\" (<a href=\"https://en.wikipedia.org/wiki/Faro_shuffle\" target=\"_blank\" rel=\"noopener noreferrer\">also known by many other names</a>) cuts the list in two parts, as evenly sized as possible, then interleaves the elements of the two parts to form the shuffled list.</p>\n<p><strong>Task 1.</strong> Write a function <code>perfect_shuffle(a_list)</code> which takes as argument a list and returns the perfect shuffle of the list. The function should <strong>not</strong> modify the argument list.</p>\n<p>Example:</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: my_list </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">4</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">5</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">6</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: my_shuffled_list </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> perfect_shuffle</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(my_list)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(my_shuffled_list) </span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">4</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">5</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">6</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">4</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(my_list) </span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">4</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">5</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">6</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p><strong>Task 2.</strong>  Write a function <code>perfect_shuffle_in_place(a_list)</code> which takes as argument a list and performs the perfect shuffle on the list. The function should modify the list, and <strong>not</strong> return any value. After the function call, the argument list should have the same length and contain the same elements; only the order of them should change.</p>\n<p>Example:</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: my_list </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">4</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">5</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">6</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">perfect_shuffle_in_place</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(my_list)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">In [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]: </span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(my_list)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">4</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">5</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">6</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p><strong>Task 3.</strong> Write a function <code>count_perfect_shuffle_in_place(a_list)</code> that repeatedly shuffles a list using the function developed in Task 2 and counts how many shuffles are done before the list becomes equal to the original list.</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> perfect_shuffle</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">a_list</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">   #</span><span style=\"--shiki-light:#A626A4;--shiki-light-font-style:italic;--shiki-dark:#C678DD;--shiki-dark-font-style:italic\">TODO</span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">: implement this function</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">   pass</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> perfect_shuffle_in_place</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">a_list</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">   #</span><span style=\"--shiki-light:#A626A4;--shiki-light-font-style:italic;--shiki-dark:#C678DD;--shiki-dark-font-style:italic\">TODO</span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">: implement this function</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">   pass</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> count_shuffles</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">a_list</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">   #</span><span style=\"--shiki-light:#A626A4;--shiki-light-font-style:italic;--shiki-dark:#C678DD;--shiki-dark-font-style:italic\">TODO</span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">: implement this function</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">   pass</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><h4>12.2.1 Solution</h4>\n<div class=\"language-python line-numbers-mode has-collapsed-lines collapsed\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--vp-collapsed-lines:15;--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> perfect_shuffle</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">a_list</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    n </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(a_list)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    mid </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> (n </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">) </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">//</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 2</span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">  # 前半多一个（当 n 为奇数）</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    left </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> a_list[:mid]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    right </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> a_list[mid:]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    out </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> []</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> i </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> range</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">max</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(left), </span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(right))):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> i </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&lt;</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(left):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">            out.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">append</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(left[i])</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> i </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&lt;</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(right):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">            out.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">append</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(right[i])</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> out</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> perfect_shuffle_in_place</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">a_list</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    a_list[:] </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> perfect_shuffle</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(a_list)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> count_shuffles</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">a_list</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    original </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> a_list[:]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    count </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 0</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    while</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> True</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">        perfect_shuffle_in_place</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(a_list)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">        count </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 1</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> a_list </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">==</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> original:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">            return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> count</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div><div class=\"collapsed-lines\"></div></div><h3>12.3 Programming problem 3: Nested lists</h3>\n<p>A list that contains lists is sometimes called <strong>nested</strong>. We define the <strong>nesting depth</strong> of a list as follows:</p>\n<ul>\n<li>A list that does not contain any list has a nesting depth of zero</li>\n<li>A list that contains lists has a nesting depth equal to the maximum nesting depth of the lists it contains, plus one.</li>\n</ul>\n<p>Note that \"a list that contains lists\" can also contain values that are not lists.</p>\n<p>For example, the nesting depth of <code>[[1,2], [2,4]]</code> is 1, while the nesting depth of <code>[1, [2], [[3], [[4], 5]]]</code> is 3.</p>\n<p><strong>Write a function that takes as argument a list and returns its nesting depth.</strong></p>\n<p>What does your function return when called with the list <code>[[[]]]</code>? (and is that what it should return?)</p>\n<blockquote>\n<p>Hint: you can check whether a value is a list (or another type) with <code>isinstance(value, list)</code> .</p>\n<p>Hint: this question is well suited to a recursive solution - where a function calls itself to find the solution to a problem. i.e., how would you find the maximum nesting depth of an inner list?</p>\n</blockquote>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> nesting_depth</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">a_list</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">    #</span><span style=\"--shiki-light:#A626A4;--shiki-light-font-style:italic;--shiki-dark:#C678DD;--shiki-dark-font-style:italic\">TODO</span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">: implement this function</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    pass</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><h4>12.3.1 Solution</h4>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> nesting_depth</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">a_list</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    if</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> not</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> isinstance</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(a_list, </span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">list</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        raise</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#ABB2BF\"> TypeError</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"argument must be a list\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    max_child </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> -</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">  # 若没有子列表则保持 -1，最后返回 0</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> x </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> a_list:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        if</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> isinstance</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(x, </span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">list</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">            max_child </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> max</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(max_child, </span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">nesting_depth</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(x))</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    return</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 0</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> max_child </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&lt;</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 0</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> else</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> max_child </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 1</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><h3>12.4 Solution</h3>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">from</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> typing </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">import</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> List, Any</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">#</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div>",
      "image": "https://bornforthis.cn/gzh.jpg",
      "date_published": "2025-09-17T09:11:49.000Z",
      "date_modified": "2025-09-21T10:52:13.000Z",
      "authors": [
        {
          "name": "AI悦创"
        }
      ],
      "tags": [
        "Python一对一答疑帖",
        "留学生Python辅导",
        "Australian National University一对一辅导"
      ]
    },
    {
      "title": "14-营销活动：日常运营活动的分析模板",
      "url": "https://bornforthis.cn/column/%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90%E6%80%9D%E7%BB%B4%E4%B8%8E%E5%AE%9E%E6%88%9823%E8%AE%B2/15.html",
      "id": "https://bornforthis.cn/column/%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90%E6%80%9D%E7%BB%B4%E4%B8%8E%E5%AE%9E%E6%88%9823%E8%AE%B2/15.html",
      "summary": "你好，我是悦创。 本课时内容分为三部分： 营销活动当前现状； 营销活动具体分析； 案例讲解——百度 APP。 1. 营销活动当前现状 我之前在国企工作时，公司经常会做线上和线下活动，所以每天都会看到各种活动捷报。活动结束后，钱是花完了，真实用户数却没涨多少，大多数都被薅羊毛了。营销活动每年都会花很多钱，因此必须要找一个公正的第三方——数据分析师，来做这...",
      "content_html": "<p>你好，我是悦创。</p>\n<p>本课时内容分为三部分：</p>\n<ul>\n<li>\n<p>营销活动当前现状；</p>\n</li>\n<li>\n<p>营销活动具体分析；</p>\n</li>\n<li>\n<p>案例讲解——百度 APP。</p>\n</li>\n</ul>\n<h2>1. 营销活动当前现状</h2>\n<p>我之前在国企工作时，公司经常会做线上和线下活动，所以每天都会看到各种活动捷报。活动结束后，钱是花完了，真实用户数却没涨多少，大多数都被薅羊毛了。营销活动每年都会花很多钱，因此必须要找一个公正的第三方——数据分析师，来做这件事。而数据分析师既然要做，就一定要发挥出自己的专业性，大家都是罗列数字，为何你就是不一样，你的强大逻辑性在哪？</p>\n<p>在这种背景下，我们看一下营销活动的运营人员现状。运营人员比较关注活动的三个维度：带来多少用户量的增长，拉来多少新增用户，外界传播量能覆盖多少人。而数据分析师只需在活动期间每天进行效果播报，活动后 1~2 周内产出活动报告即可。活动报告包括活动参与人数、拉新数、用户画像三部分内容。</p>\n<p>数据分析师与营销活动运营人员相比，数据分析师的优势在于快和维度拆解性，劣势在于细节性。因为数据分析师在做分析时，只是开一个大树，在很多具体业务的细节上面，毕竟不是专门做营销活动出身，所以不是特别了解，也可能没去问，导致最后报告结论的解读可能多多少少有些问题。而对于营销活动人员来说，每过一段时间，就要搞各种活动，所以很清楚活动细节。</p>\n<p>其实营销活动应该是一件长期的事件，不可能通过某一次活动就能够带来大量的用户增长，因此数据分析师在做这件事时，要保持以下特性。</p>\n<ol>\n<li>分析的连贯性：在活动前、活动中、活动后都要进行分析。</li>\n<li>分析的对比性：不要单看活动本身，活动要与活动之间对比，这样才能更好分析什么样的活动更适合产品本身。</li>\n<li>分析的公正性：该怎么样就怎么样，拉新、促活、品牌的评判都应该有一套商定好的标准。</li>\n</ol>\n<p>营销活动分析无非就两件事：活动效果评估（本活动和活动对比）和活动优化建议。活动之后要对活动进行复盘，那些做得不好，之后可以避免。</p>\n<h2>2. 营销活动具体分析</h2>\n<p>第二部分，我们来看营销活动具体应该怎么分析？我们先理一理，实际上在做任何活动之前，活动运营方都花了很多心思。活动之前必然会出文案，找开发，然后跟外面的合作方进行研讨，所有的这一切都会发生得很早。因此分析师要想做好活动分析，在这个时候就要与活动运营方多沟通，知道活动整体是怎么回事。</p>\n<p>比如，第一要了解是谁来开发，靠不靠谱？第二要知道活动形式及测试体验，文案可能存在哪些问题。第三要想好活动大概有哪些指标。这些都要提前想一想。</p>\n<h3>2.1 活动前好好准备——前 1~2 周</h3>\n<p>在活动前，要好好准备这几件事。</p>\n<ul>\n<li>\n<p><strong>活动前和运营方商定本次活动的目标</strong>。一定要有目标，没有目标的运营不是一个好运营，没有目标的运营绝对不会使出 100% 的力气。这里能很好地培养你业务的敏感性。</p>\n</li>\n<li>\n<p><strong>活动前和研发沟通好埋点</strong>。不是每个研发都很靠谱，即使很靠谱也可能会犯错误。在埋点这件事上，分析师应该是主导地位，包括字段名、埋点位置、上报方式等。</p>\n</li>\n<li>\n<p><strong>提前搭建好指标体系和报表</strong>。一定要提前准备，活动前 1 天才发现问题，这样的情况太常见。</p>\n</li>\n<li>\n<p><strong>定好输出格式</strong>。要想好活动中、活动后每天输出哪些数据，什么形式展现，这些要与业务绑好。</p>\n</li>\n</ul>\n<p>正式活动前一定要好好地准备，对于一般中型的活动一般是提前 1～2 周。如果是大公司的活动，可能前一个月就要好好准备。像双 11 这种特大活动就不是前一个月才准备，可能在活动的前三个月，所有的数据分析师都在准备这件事了。</p>\n<h3>2.2 活动中好好观察——期间每一天，包括预热</h3>\n<p>其实正式活动，都有预热期，比如双 11 活动是 11 月 11 日，但 11 月 1 日起就已经很热闹了，甚至更早。所以在活动中，应注意以下事项。</p>\n<ul>\n<li>\n<p><strong>观察第 1 天的数据</strong>，这个非常关键。详细看指标体系的报表数据，查看是否有异常。因为前期修改成本非常小，对于负责人的研发也很乐意去解决这件事。</p>\n</li>\n<li>\n<p><strong>观察 1~3 天数据</strong>，预估活动目标的完成度，活动目标在前期一定是确定好的，这里要看是否要做适当调整。</p>\n</li>\n<li>\n<p><strong>定时输出活动战报</strong>，每天早上输出，让所有人都知道情况。实际上管理层都有一个比较好的心法，就是早上看数据，你不要以为他在群里面没回，实际上都会看。在工作中真实情况可能真的只有运营人员自己知道数据，有一些数据很可能还藏着掖着。这里的数据要注意真实性，该怎么样就怎么样，要敢于暴露问题，这里问题不会很大，因为所有人的目标就是希望把这个活动做好。</p>\n</li>\n<li>\n<p><strong>活动 1 周后数据复盘</strong>，1 周后进行一次详细复盘，并同步给管理层，让更高视野的人来给建议。</p>\n</li>\n</ul>\n<h3>2.3 活动后好好复盘——公正性</h3>\n<p>到活动后期，需要好好复盘，其中最关键的是公正性，比如以下几点。</p>\n<ul>\n<li>\n<p>复盘活动对大盘的影响，这件事实际上很难做，但也有解决方法，后续会讲到。</p>\n</li>\n<li>\n<p>复盘活动的短期效果，目标完成度，参与人数、拉新、品牌传播指数。</p>\n</li>\n<li>\n<p>复盘活动的长期效果，通过活动带来的长期用户数，而不是低价值用户数。</p>\n</li>\n<li>\n<p>复盘活动存在的问题，包括产品设计和用户反馈。</p>\n</li>\n</ul>\n<p>前面三点都是说活动的一个效果，第四点是说活动要为下一次活动做一些优化，包括以后做一些类似的活动，我们也要避免同样错误的发生。这里面就包括产品设计，用户是不是反馈这个 Bug 太多？明明中奖了，最后还是没有奖品，等等。这些问题都要把它暴露出来，所有的这一切都尽量要在活动后 1~2 周之内输出，在这件事上要非常讲究实效性。</p>\n<p>营销活动分析分为三部分内容，总结如下图所示。</p>\n<figure><figcaption></figcaption></figure>\n<p>第一次活动分享，数据分析师帮助运营人员做好并形成模板，后续让运营负责即可。活动是个非常个性化的活儿，分析师不应该投入太多时间。</p>\n<h2>3. 案例讲解——百度 APP</h2>\n<h3>3.1 活动介绍</h3>\n<p>最后我举个百度 APP 的活动案例，我们先看一下百度 APP 里面的活动，随便刷一下 feeds 流，发现有一个圣诞活动，点进去后发现是这样一个交互界面，如下图所示。</p>\n<figure><figcaption></figcaption></figure>\n<p>这个活动主要是中间这个按钮——“刷资讯继续找礼物”。你点击按钮后就会跳到另一个 feeds 流里面，然后用户点击某一天资讯之后，它可能就给你两三毛钱。观察活动界面基本情况如下。</p>\n<ul>\n<li>\n<p>拉新：右上角分享。</p>\n</li>\n<li>\n<p>促活：刷资讯找礼物。</p>\n</li>\n<li>\n<p>活动奖励：送现金+机票。</p>\n</li>\n<li>\n<p>体验感受：功能非常简单，但文案写的太复杂。</p>\n</li>\n<li>\n<p>活动日期：12月6日 - 12月25日。</p>\n</li>\n</ul>\n<h3>3.2 活动指标体系搭建</h3>\n<p>由于活动的步骤较多，这里我就挑选一些比较关键的活动指标，来完成活动指标体系的搭建。前面课时有提到，在搭建活动指标体系的时候，不追求大而全，找到关键指标，然后按照用户的基础属性和行为属性拆解即可。</p>\n<p>对于这个活动，它的关键指标，就是带来新增用户和活动参与用户，那么我们就针对这两个点，对新增用户数和活跃用户数进行拆解。拆解途径如下图所示。</p>\n<figure><figcaption></figcaption></figure>\n<p>新增用户数可以拆解为渠道和新增用户的消费数据两个维度。渠道指用户是通过哪个渠道进入活动页面，比如是通过微信、QQ、微博或其他渠道进入活动。假设这里我们就只看这两个维度，当然真实情况中肯定要看更多维度的详细数据，我们先暂且不说。</p>\n<p>对于活跃用户数也可以拆分为两个维度，第一个维度是参与过程的漏斗数据，这个很关键，因为漏斗分析非常经典，就是老用户进入这个活动之后，他整个参与过程的一个漏斗数据怎么样。第二个维度是在入口这一块，分为闪屏、信息流、活动中心，要知道我们的活跃用户到底是通过哪个入口进来的，每个入口的漏斗数据如何。</p>\n<p>这就完成了活动指标体系的搭建，当然你拆解的真实情况肯定比这个要复杂，不仅仅是这几块，一定要到具体案例里面去思考。同时一定要提前建好所有报表，然后跑测试数据，正常都会有测试数据，一定要让研发去给一些测试样本，活动之前一定要确认测试数据没有问题。</p>\n<h3>3.3 活动后复盘—绝不是简单的数字罗列</h3>\n<p>活动后的复盘我来详细说一下，活动复盘绝对不是简单的数字罗列，总结如下图所示。</p>\n<figure><figcaption></figcaption></figure>\n<p>圣诞活动复盘我们分为三部分，第一个是短期贡献，第二个是长期贡献，第三个是活动优化。</p>\n<ol>\n<li><strong>短期贡献</strong>\n<ul>\n<li><strong>新增 NU</strong>： 我们看新增用户数 NU、大盘 DAU 的波动对大盘的影响。</li>\n<li><strong>大盘 DAU</strong>： 对于大盘 DAU ，因为有诸多的变量，所以活动对于大盘的影响很难评估。这里面我给出几个点。\n<ul>\n<li>第一是参与活动 UV，有多少人参加了这个活动。</li>\n<li>第二是活动首次 UV，有多少用户是首次打开 APP 就进入了你这个活动，那这些用户绝对是你这个活动带来的，没有争议。</li>\n<li>第三就是大盘的日环比以及周同比，因为大盘的日环比可以看出大盘本身的波动情况，周同比能评估对大盘的一个影响。</li>\n</ul>\n</li>\n<li><strong>低活用户</strong>： 低活用户代表你通过这个活动把多少低活跃的用户拉成高活跃用户，这个就很关键。比如说把一些沉默用户、消费频次非常低的用户拉起来了，这就很有价值。</li>\n</ul>\n</li>\n<li><strong>长期贡献</strong>\n<ul>\n<li><strong>新增留存/上线率</strong>： 指我们带来的新增用户，后期的留存以及上线率如何。这里一般看七天，因为你不能计算太长时间，所以活动结束后，新增用户的 7 日留存是多少。</li>\n<li><strong>低活留存/上线率</strong>： 指低活用户的留存以及上线率是多少，在长期贡献没有一套固定的评判标准，所有的标准就是按照你自己对业务的理解以及你正确的逻辑性。</li>\n</ul>\n</li>\n<li><strong>活动优化</strong>\n<ul>\n<li><strong>活动主漏斗数据</strong>： 活动一层一层漏斗的数据怎么样？</li>\n<li><strong>活动功能模块渗透率</strong>： 活动各个功能模块低渗透率怎么样？</li>\n<li><strong>用户反馈</strong>： 用户反馈是为后面活动做准备，收集整理复盘，避免踩坑即可。</li>\n</ul>\n</li>\n</ol>\n<h3>3.4 活动后复盘—总结</h3>\n<p>这就是活动后的整体复盘，我们看了一下短期贡献、长期贡献以及活动优化。下面我整体总结下活动的整体复盘，其中我也会补充一些其他点，如下所述。</p>\n<ul>\n<li>\n<p>如果活动涉及收入和品牌传播（百度指数、微博指数），也要加入复盘；</p>\n</li>\n<li>\n<p>可以用同比、环比来衡量对大盘 DAU 的贡献，同一拨用户前后对比其实不太好说明问题；</p>\n</li>\n<li>\n<p>新增、首次、低活带动这三个指标，可以较好评判活动的价值；</p>\n</li>\n<li>\n<p>对于拉来的新增用户和低活用户，更重要的是这部分用户的后续留存；</p>\n</li>\n<li>\n<p>一定要把活动与活动间的数据进行对比，这更能说明问题，哪个活动好不好一目了然；</p>\n</li>\n<li>\n<p>一定要思考每次活动的本质和意义，比如某个活动本身就不针对拉新，然后新用户参与了，你能说是你带来的吗？肯定不能；</p>\n</li>\n<li>\n<p>如果是公司 S（最高）级的活动，数据分析师要看实时数据，无论是资源还是精力，都要重点投入；</p>\n</li>\n<li>\n<p>一定要敢于暴露问题，数据分析师把已知的事实告知自己的上级，并邮件同步给活动运营的负责人；</p>\n</li>\n<li>\n<p>凡是涉及活动使用金额时，分析师最好不要自己出数，让业务方给，工作中一定要自己做的话，记得邮件同步说明情况。</p>\n</li>\n</ul>\n<p>最后给你留一个思考题——你们公司是如何衡量活动对大盘跌逾的贡献？</p>\n<p>今天的课程就到这里，如果你有问题可以在下方留言，同时欢迎你关注我本人的公众号（微信搜索：AI悦创），之后会定期更新原创高质量的数据分析文章，下节课见，谢谢。</p>\n<details class=\"hint-container details\"><summary>公众号：AI悦创【二维码】</summary>\n<figure><img src=\"/gzh.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n</details>\n<div class=\"hint-container info\">\n<p class=\"hint-container-title\">AI悦创·编程一对一</p>\n<p>AI悦创·推出辅导班啦，包括「Python 语言辅导班、C++ 辅导班、java 辅导班、算法/数据结构辅导班、少儿编程、pygame 游戏开发、Web、Linux」，招收学员面向国内外，国外占 80%。全部都是一对一教学：一对一辅导 + 一对一答疑 + 布置作业 + 项目实践等。当然，还有线下线上摄影课程、Photoshop、Premiere 一对一教学、QQ、微信在线，随时响应！微信：Jiabcdefh</p>\n<p>C++ 信息奥赛题解，长期更新！长期招收一对一中小学信息奥赛集训，莆田、厦门地区有机会线下上门，其他地区线上。微信：Jiabcdefh</p>\n<p>方法一：<a href=\"http://wpa.qq.com/msgrd?v=3&amp;uin=1432803776&amp;site=qq&amp;menu=yes\" target=\"_blank\" rel=\"noopener noreferrer\">QQ</a></p>\n<p>方法二：微信：Jiabcdefh</p>\n</div>\n<figure><img src=\"/zsxq.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n",
      "date_published": "2025-09-12T18:05:40.000Z",
      "date_modified": "2025-09-14T08:52:59.000Z",
      "authors": [
        {
          "name": "AI悦创"
        }
      ],
      "tags": []
    },
    {
      "title": "01-清炖羊肉",
      "url": "https://bornforthis.cn/column/cookdinner/P11-%E7%BE%8A%E8%82%89%E7%B1%BB/01-%E6%B8%85%E7%82%96%E7%BE%8A%E8%82%89.html",
      "id": "https://bornforthis.cn/column/cookdinner/P11-%E7%BE%8A%E8%82%89%E7%B1%BB/01-%E6%B8%85%E7%82%96%E7%BE%8A%E8%82%89.html",
      "summary": "公众号：AI悦创【二维码】 AI悦创·编程一对一 AI悦创·推出辅导班啦，包括「Python 语言辅导班、C++ 辅导班、java 辅导班、算法/数据结构辅导班、少儿编程、pygame 游戏开发、Web、Linux」，招收学员面向国内外，国外占 80%。全部都是一对一教学：一对一辅导 + 一对一答疑 + 布置作业 + 项目实践等。当然，还有线下线上摄影...",
      "content_html": "\n",
      "image": "https://bornforthis.cn/gzh.jpg",
      "date_published": "2025-09-08T08:46:26.000Z",
      "date_modified": "2025-09-09T02:10:26.000Z",
      "authors": [
        {
          "name": "AI悦创"
        }
      ],
      "tags": []
    },
    {
      "title": "消费者颜色偏好与数据分析方法研究：实验比较与 Monte Carlo 模拟",
      "url": "https://bornforthis.cn/blog/2025/8month/maotouy.html",
      "id": "https://bornforthis.cn/blog/2025/8month/maotouy.html",
      "summary": "1. Analysis of Research Strategies to Determine 1.1 论文中的数据分析内容 四种实验方法的比较 N-Alternative Forced Choice (N-AFC)：让参与者在同时呈现的多种颜色中选择最喜欢的一种。 Rank-Order：要求参与者把所有颜色从最喜欢到最不喜欢排序。 Rating：给每...",
      "content_html": "<h2>1. Analysis of Research Strategies to Determine</h2>\n<h3>1.1 论文中的数据分析内容</h3>\n<ol>\n<li><strong>四种实验方法的比较</strong>\n<ul>\n<li><strong>N-Alternative Forced Choice (N-AFC)</strong>：让参与者在同时呈现的多种颜色中选择最喜欢的一种。</li>\n<li><strong>Rank-Order</strong>：要求参与者把所有颜色从最喜欢到最不喜欢排序。</li>\n<li><strong>Rating</strong>：给每个颜色打分，比如 0%-100% 表示不喜欢到最喜欢。</li>\n<li><strong>Paired Comparison</strong>：两两颜色比较，每次选一个更喜欢的，最后得到整体排序。</li>\n</ul>\n</li>\n<li><strong>数据转换与标准化处理</strong>\n<ul>\n<li>把不同方法的原始结果（选择次数、排序、打分、配对比较结果）转化为统一的 <strong>比例值 (0%–100%)</strong>。</li>\n<li>再通过 <strong>Thurstone’s Law of Comparative Judgement（案例V）</strong> 转换成 <strong>区间尺度 z 分数</strong>，使不同方法的数据可以比较。</li>\n</ul>\n</li>\n<li><strong>统计分析与结果</strong>\n<ul>\n<li>比较四种方法得出的偏好顺序：多数情况下结果一致（橙色最受欢迎，绿色最不受欢迎）。</li>\n<li>使用 <strong>相关系数 (r²)</strong> 来衡量不同方法之间的一致性，以及样本量大小对稳定性的影响。</li>\n</ul>\n</li>\n<li><strong>Monte Carlo 模拟分析</strong>\n<ul>\n<li>从 41 个样本中反复随机抽取不同数量的子样本（比如 n=36, 31, 26…直到 n=1）。</li>\n<li>每次计算颜色偏好顺序与完整样本的相关性（r²）。</li>\n<li>发现：当样本量小于 11 时，<strong>Rating、Rank-Order、Paired Comparison 更稳定</strong>；而 <strong>N-AFC 方法波动大</strong>。</li>\n</ul>\n</li>\n</ol>\n<h4>1.1.1 Monte Carlo 模拟分析</h4>\n<div class=\"hint-container tip\">\n<p class=\"hint-container-title\">我们不仅仅要知道老师论文涉及的知识、技术，更要了解老师的意图，为什么要使用某个技术？别的技术不行？</p>\n<p>多思考，多实践。</p>\n</div>\n<ol>\n<li>\n<p><strong>基本定义</strong>：Monte Carlo 模拟是一种<strong>基于随机数和概率统计</strong>的计算方法。</p>\n</li>\n<li>\n<p><strong>核心思想</strong>：用大量随机样本来模拟和逼近复杂问题的可能结果，从而得到一个<strong>概率分布</strong>而不是单一的确定结果。</p>\n<p>简单说，就是“用随机数去模拟各种可能发生的情况，看大规模模拟之后的整体趋势”。</p>\n</li>\n<li>\n<p><strong>为什么需要 Monte Carlo 模拟？</strong></p>\n<ol>\n<li>很多现实问题（金融风险、项目工期、物理实验、排队模型等）太复杂，无法直接用数学公式精确解出结果。</li>\n<li>比如：\n<ul>\n<li>股票价格未来 1 年的波动？</li>\n<li>一个建筑项目完工的时间？</li>\n<li>投资组合的风险收益？</li>\n</ul>\n</li>\n<li>这些问题都存在<strong>不确定性</strong>，Monte Carlo 就是用随机模拟去近似求解。</li>\n</ol>\n</li>\n</ol>\n<h3>1.2 涉及的数据分析原理解释</h3>\n<ol>\n<li>\n<p><strong>比例数据 (Proportion Data)</strong></p>\n<ul>\n<li>将原始数据转化为百分比，方便不同方法之间比较。</li>\n<li>例如：如果 100 个人中有 40 人最喜欢蓝色，那么蓝色的偏好比例就是 40%。</li>\n</ul>\n</li>\n<li>\n<p><strong>区间尺度转化 (Interval Scaling, z-score)</strong></p>\n<ul>\n<li>使用统计学方法（如 <strong>标准正态分布反函数</strong>）将比例值转化为 <strong>z 分数</strong>，消除了比例在极端（0% 或 100%）的限制，使数据能进行线性比较。</li>\n</ul>\n</li>\n<li>\n<p><strong>相关系数 r² (Coefficient of Determination)</strong></p>\n<ul>\n<li>衡量不同实验方法结果与总体结果的一致性。</li>\n<li>r²=1 表示完全一致，r² 越低说明差异越大。</li>\n</ul>\n</li>\n<li>\n<p><strong>Monte Carlo 模拟</strong></p>\n<ul>\n<li>一种随机抽样重复试验的方法。</li>\n<li>用来评估在不同样本规模下，实验方法的结果是否稳定。</li>\n<li>通过多次模拟得到一个概率分布，而不是依赖单次实验结果。</li>\n</ul>\n</li>\n<li>\n<p><strong>分析原理（步骤）：</strong></p>\n<blockquote>\n<p>Monte Carlo 模拟通常包含以下流程：</p>\n</blockquote>\n<ol>\n<li>\n<p><strong>确定输入变量及其概率分布</strong>：（例如：股票年回报率符合正态分布（均值 8%，标准差 15%））</p>\n</li>\n<li>\n<p><strong>随机抽样</strong>：根据定义的分布，利用计算机生成大量随机数（成千上万次）</p>\n</li>\n<li>\n<p><strong>计算模型结果</strong>：将每次抽样代入模型公式，计算出对应的结果。</p>\n</li>\n<li>\n<p><strong>统计与分析</strong>：</p>\n<ol>\n<li>把所有模拟结果汇总，形成结果的概率分布。</li>\n<li>从中可以得到：平均值、中位数、标准差、置信区间、最坏/最好情况概率等。</li>\n</ol>\n</li>\n<li>\n<p><strong>举例（现实生活场景）</strong>：</p>\n<ol>\n<li>\n<p><strong>🎲 例子 1：掷骰子</strong></p>\n<ol>\n<li>我想知道连续掷两个骰子，总和大于 8 的概率。</li>\n<li>可以写出数学公式直接算，但 Monte Carlo 模拟是另一种方法：\n<ol>\n<li>模拟掷 100 万次骰子（随机生成 1~6 的点数）。</li>\n<li>统计有多少次结果大于 8。</li>\n<li>用次数/总次数 ≈ 概率。</li>\n</ol>\n</li>\n<li>结果会接近真实概率（≈ 0.278）。</li>\n</ol>\n</li>\n<li>\n<p><strong>💰 例子 2：投资收益</strong></p>\n<ol>\n<li>假设你买了一个基金，年化收益率平均 8%，但波动（标准差）15%。</li>\n<li>用 Monte Carlo：\n<ol>\n<li>在未来 10 年里，每年随机抽取一个“收益率”来模拟基金表现。</li>\n<li>重复 1 万次，得到 1 万条“基金 10 年后的价值曲线”。</li>\n<li>汇总结果 → 可以看到 10 年后资产的 <strong>分布</strong>：\n<ul>\n<li>70% 的概率资产翻倍；</li>\n<li>10% 的概率资产亏损；</li>\n<li>最坏 1% 的情况甚至腰斩。</li>\n</ul>\n</li>\n</ol>\n</li>\n</ol>\n<p>这样比“单纯说平均收益 8%”更有参考价值，因为它揭示了<strong>风险区间</strong>。</p>\n</li>\n</ol>\n</li>\n</ol>\n</li>\n</ol>\n<h3>1.3 生活中的例子帮助理解</h3>\n<ol>\n<li><strong>N-AFC（多选一）</strong><br>\n类似于点菜时，服务员把菜单上 6 道菜都端到你面前，让你直接选出“<strong>最想吃的那一道</strong>”。\n<ul>\n<li>问题：如果参与者人数少，可能因为偶然选择导致结果偏差大。</li>\n</ul>\n</li>\n<li><strong>Rank-Order（排序）</strong><br>\n就像你写“最喜欢的手机品牌排行榜”，把苹果、华为、三星、小米等从最喜欢到最不喜欢依次排列。\n<ul>\n<li>优点：即使人数少，也能比较稳定地反映整体趋势。</li>\n</ul>\n</li>\n<li><strong>Rating（打分）</strong><br>\n类似于电影评分（豆瓣 1–10 分制），每个人对每部电影都给分，最后算平均值。\n<ul>\n<li>优点：能反映偏好强度（喜欢很多 vs 稍微喜欢）。</li>\n</ul>\n</li>\n<li><strong>Paired Comparison（两两比较）</strong><br>\n像世界杯点球大战，每次两支球队对比，选一个胜出，最后得出冠军。\n<ul>\n<li>缺点：如果参赛者太多，两两比较会非常耗时。</li>\n</ul>\n</li>\n<li><strong>Monte Carlo 模拟</strong><br>\n就像你想知道“抛硬币 10 次正反面分布”是不是稳定。你会模拟成千上万次，每次都随机抛 10 次，然后统计结果，最终得到一个分布。\n<ul>\n<li>在论文中，作者用它来测试“如果只收集到 6 个人的数据，结果还可信吗？”</li>\n</ul>\n</li>\n</ol>\n<h3>1.4 数据转换</h3>\n<h4>1.4.1 为什么要转换数据？</h4>\n<p>论文里有四种实验方法：</p>\n<ul>\n<li>\n<p><strong>AFC（多选一）</strong> → 得到的是 “<strong>次数</strong>”；</p>\n</li>\n<li>\n<p><strong>Rank-Order（排序法）</strong> → 得到的是 “<strong>名次</strong>”；</p>\n</li>\n<li>\n<p><strong>Rating（打分法）</strong> → 得到的是 “<strong>分数</strong>”；</p>\n</li>\n<li>\n<p><strong>Paired Comparison（两两比较）</strong> → 得到的是 “<strong>胜出次数</strong>”；</p>\n</li>\n</ul>\n<p>问题来了：</p>\n<ul>\n<li>次数、名次、分数、胜出次数，本质上不是同一种量纲，没法直接比较。</li>\n<li>举个例子：一个人说“蓝色是第一名”，另一个人说“蓝色打 80 分”，这两种数据如果直接放在一起，没有可比性。</li>\n</ul>\n<p>👉 所以，需要把它们 <strong>转化到同一个标准化的区间（0% ~ 100%）</strong>，然后再进一步转化成 <strong>可以比较的数值（z 分数）</strong>。</p>\n<h4>1.4.2 第一步：转化为比例 (0% – 100%)</h4>\n<p>就是把各种形式的回答，统一换算成一个比例值。</p>\n<ul>\n<li><strong>AFC（多选一）</strong>：如果 100 个人里有 40 人最喜欢蓝色 → 蓝色偏好率 = 40%</li>\n<li><strong>Rank-Order（排序）</strong>：假设 5 个人对蓝色排序分别是 1, 2, 3, 2, 1（分别代表蓝色的位置） → 平均名次 = 1.8 → 再转化为比例（例如计算成“蓝色有 70% 的人把它放在前三名”）。</li>\n<li><strong>Rating（打分）</strong>：每个人对蓝色打分：70%、80%、90%、60% → 平均值 = 75%</li>\n<li><strong>Paired Comparison（两两比较）</strong>：蓝色 vs 红色，10 次比较中蓝色赢 7 次 → 蓝色胜率 = 70%</li>\n</ul>\n<p>这样，所有方法最后都可以变成类似：</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">蓝色：</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">75</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">%</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">  </span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">橙色：</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">65</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">%</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">  </span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">绿色：</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">20</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">%</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">  </span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">……</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><h4>1.4.3 第二步：转化为区间尺度 z 分数</h4>\n<p>虽然比例已经能看了，但有一个问题：</p>\n<ul>\n<li>当比例接近 0% 或 100% 时，它的变化空间很小，不利于统计比较。</li>\n<li>比如从 90% 到 95%，看起来差了 5%，但实际差距可能比 40% 到 45% 要大得多。</li>\n</ul>\n<p>👉 这时，就需要用到 <strong>Thurstone’s Law of Comparative Judgement（色彩心理学里常用）</strong>，把比例转成 <strong>z 分数</strong>。</p>\n<p><strong>什么是 z 分数？</strong></p>\n<ul>\n<li>它来自标准正态分布。</li>\n<li>把比例（p 值）代入正态分布的反函数，就能得到一个对称的数值。</li>\n<li>中间（50%）对应 z=0，越偏向两端（0% 或 100%），z 的绝对值越大。</li>\n</ul>\n<p><strong>例子：</strong></p>\n<ul>\n<li>50% → z = 0 （中性）</li>\n<li>84% → z = +1 （比平均好 1 个标准差）</li>\n<li>16% → z = –1 （比平均差 1 个标准差）</li>\n</ul>\n<p>这样，就能把所有颜色的偏好值都映射到一个 <strong>连续的、可比的数轴</strong>上。</p>\n<h4>1.4.4 实际生活类比</h4>\n<ol>\n<li>\n<p><strong>投票选美比赛</strong></p>\n<ul>\n<li>\n<p>有的人只告诉你“谁第一名”；</p>\n</li>\n<li>\n<p>有的人给每个人打分（90分、80分…）；</p>\n</li>\n<li>\n<p>有的人只做一轮一轮 PK。</p>\n<p>→ 这些原始结果格式都不一样，没法直接说“谁最漂亮”。</p>\n<p>→ 所以先要转成“百分比（多少人支持）”，再进一步变成一个统一的“标准化分数（z 分数）”。</p>\n</li>\n</ul>\n</li>\n<li>\n<p><strong>考试成绩转 GPA</strong></p>\n<ul>\n<li>\n<p>有的学校用百分制（85 分），</p>\n</li>\n<li>\n<p>有的用等级制（A, B, C），</p>\n</li>\n<li>\n<p>有的用 5 星制。</p>\n<p>→ 统一换算成 GPA（比如 A=4.0，85分≈3.7），才能放在一起比较学生成绩。</p>\n<p>这里 GPA 就相当于论文里的 “z 分数”。</p>\n</li>\n</ul>\n</li>\n<li>\n<p><strong>外卖评分</strong></p>\n<ul>\n<li>\n<p>有人说“好吃”，有人打 5 星，有人给 9 分。</p>\n</li>\n<li>\n<p>平台为了排序，需要把它们转化为同一标准（比如 0–100 的分数，再标准化）。</p>\n</li>\n</ul>\n</li>\n</ol>\n<h3>1.5 总结</h3>\n<p>这篇论文的核心数据分析思路是：</p>\n<ul>\n<li>先把不同实验方法的数据转化为统一的区间尺度；</li>\n<li>再通过 <strong>相关系数</strong> 和 <strong>Monte Carlo 模拟</strong> 检验方法的稳定性；</li>\n<li>结论是：当参与人数较少时，<strong>Rating、Rank-Order、Paired Comparison 更适合</strong>，而 <strong>N-AFC 容易不稳定</strong>。</li>\n</ul>\n<h2>2. CRA_Yu_Westland_Li_Pan_Shin_Won</h2>\n<h3>2.1 论文中的数据分析内容提炼</h3>\n<ol>\n<li><strong>研究对象与实验设计</strong>\n<ul>\n<li>共选择了 <strong>54 种日常家居产品</strong>（如牙刷、咖啡机、洗发水、拖鞋等）。</li>\n<li>每个产品被设计成 <strong>六种颜色版本</strong>（红、橙、黄、绿、蓝、紫）。</li>\n<li>实验分为 <strong>两种形式</strong>：\n<ul>\n<li><strong>线上实验</strong>：173 名参与者，选择他们愿意购买的颜色。</li>\n<li><strong>实验室实验</strong>：39 名参与者，除选择颜色外，还评估颜色与产品功能/性能的关系（用 <strong>5 点李克特量表</strong>，转化为 0–100% 分值）。</li>\n</ul>\n</li>\n</ul>\n</li>\n<li><strong>关键数据指标</strong>\n<ul>\n<li><strong>颜色一致率（Colour Consistency Rate）</strong>\n<ul>\n<li>定义：参与者是否选择了与自己“最喜欢颜色”一致的产品颜色。</li>\n<li>计算方式：某产品选择与个人最喜欢颜色一致的比例。</li>\n<li>随机情况下理论值为 <strong>17%</strong>（因为 6 种颜色）。</li>\n<li>实验结果：\n<ul>\n<li>在线实验平均一致率：34.2%</li>\n<li>实验室实验平均一致率：30.1%<br>\n👉 说明个人颜色偏好确实影响购买决策。</li>\n</ul>\n</li>\n</ul>\n</li>\n<li><strong>功能/性能相关性评分</strong>\n<ul>\n<li>例如：参与者评估“颜色是否影响该产品性能/功能”。</li>\n<li>结果：\n<ul>\n<li><strong>高相关性</strong>：漱口水 (66.7%)、洗洁精 (57.1%)、沐浴露 (56.4%)。</li>\n<li><strong>低相关性</strong>：剪刀 (13.5%)、开瓶器 (16%)、椅子 (16.7%)。</li>\n</ul>\n</li>\n</ul>\n</li>\n<li><strong>相关性分析</strong>\n<ul>\n<li>研究者计算了 <strong>颜色一致率与功能/性能相关性之间的相关性</strong>：\n<ul>\n<li>在线实验：R² = 0.41</li>\n<li>实验室实验：R² = 0.64<br>\n👉 越是“颜色强烈暗示功能”的产品，个人颜色喜好影响越小。</li>\n</ul>\n</li>\n</ul>\n</li>\n</ul>\n</li>\n</ol>\n<h3>2.2 涉及的数据分析原理</h3>\n<ol>\n<li><strong>对照基准 (Baseline Comparison)</strong>\n<ul>\n<li>设定 <strong>随机选择下的理论概率 17%</strong>，作为基准。</li>\n<li>如果实验结果明显高于 17%，说明个人颜色偏好对购买决策有显著影响。<br>\n👉 这是典型的 <strong>假设检验思路</strong>：和“无效假设”(随机选择) 对比。</li>\n</ul>\n</li>\n<li><strong>相关性分析 (Correlation Analysis)</strong>\n<ul>\n<li>使用 <strong>R²（决定系数）</strong> 衡量颜色一致率与功能/性能评分之间的关系。</li>\n<li>R² 越高，说明产品的“功能相关性”越能解释颜色偏好的作用强弱。<br>\n👉 这是 <strong>回归分析/相关性分析</strong> 的应用。</li>\n</ul>\n</li>\n<li><strong>分类比较 (Group Comparison)</strong>\n<ul>\n<li>研究对比了不同产品、不同颜色、不同实验条件（线上 vs 实验室）的差异。<br>\n👉 属于 <strong>多维度数据分析</strong>，常用于消费者研究。</li>\n</ul>\n</li>\n</ol>\n<h3>2.3 生活中的实际例子</h3>\n<ol>\n<li><strong>漱口水的颜色选择</strong>\n<ul>\n<li>大多数人觉得蓝色漱口水“更干净、杀菌力强”，绿色漱口水可能让人联想到“苹果味”或“天然”。</li>\n<li>即使你最喜欢的颜色是紫色，你可能也不会买紫色的漱口水。<br>\n👉 <strong>功能相关性强，个人偏好影响弱。</strong></li>\n</ul>\n</li>\n<li><strong>牙刷的颜色选择</strong>\n<ul>\n<li>功能上，红色和蓝色牙刷没什么差别。</li>\n<li>在这种情况下，人们更容易选择自己喜欢的颜色。<br>\n👉 <strong>功能相关性弱，个人偏好影响强。</strong></li>\n</ul>\n</li>\n<li><strong>家电的颜色选择</strong>\n<ul>\n<li>烤箱、咖啡机等加热产品，很多消费者倾向选择红色或黑色，因为联想到“热、稳重、耐用”。</li>\n<li>而苹果 iPod Nano 则可以推出彩色系列，消费者愿意根据喜好挑选。<br>\n👉 <strong>部分产品靠颜色“功能暗示”，部分产品依赖“个人偏好驱动”。</strong></li>\n</ul>\n</li>\n</ol>\n<h3>2.4 总结</h3>\n<p>论文中的数据分析核心是：</p>\n<ul>\n<li>通过 <strong>颜色一致率</strong> 测量个人喜好对购买行为的影响；</li>\n<li>通过 <strong>相关性分析</strong> 验证“功能/性能相关性”与个人喜好作用的关系；</li>\n<li>得出结论：\n<ul>\n<li><strong>当颜色与产品功能/性能强相关时，个人偏好作用弱</strong>（如漱口水、洗洁精）；</li>\n<li><strong>当颜色与功能无关时，个人偏好作用强</strong>（如牙刷、椅子）。</li>\n</ul>\n</li>\n</ul>\n<p>换句话说，<strong>颜色的营销价值，要看产品类型</strong>：</p>\n<ul>\n<li>日常消耗品：颜色→功能暗示更重要。</li>\n<li>个性化产品：颜色→个人偏好更重要。</li>\n</ul>\n<h2>3. Proceeding_official (dragged)2</h2>\n<h3>3.1 论文中的数据分析方法</h3>\n<ol>\n<li><strong>实验设计与数据采集</strong>\n<ul>\n<li>研究对象：60 块彩色织物样本（20 种颜色 × 3 种材质：棉、麻、丝）。</li>\n<li>测试人群：80 名受试者（男女各 40，18-35 岁，具备色彩科学训练）。</li>\n<li>实验方式：心理物理学实验，参与者在标准光源 D65 下观看并触摸样本。</li>\n<li>评价指标：使用 <strong>7 点 Likert量表</strong>（从“冷-暖”、“薄-厚”、“男性化-女性化”、“不愉快-愉快”等八个维度进行打分）。</li>\n</ul>\n</li>\n<li><strong>数据表示与处理</strong>\n<ul>\n<li>每块织物的颜色用 <strong>CIELAB 色彩空间</strong>（L*, a*, b*）进行量化。\n<ul>\n<li><code>L*</code> = 明度（亮暗）</li>\n<li><code>a*</code> = 红-绿通道</li>\n<li><code>b*</code> = 黄-蓝通道</li>\n</ul>\n</li>\n<li>数据处理：将主观评价量表分数转化为区间数据进行统计分析。</li>\n</ul>\n</li>\n<li><strong>统计分析方法</strong>\n<ul>\n<li><strong>配对 t 检验（Paired t-test）</strong><br>\n检验不同材质间（棉 vs 麻、麻 vs 丝、棉 vs 丝）在八个感知维度上的差异显著性。结果发现，&gt;70%对比显著，尤其在“厚薄”、“冷暖”、“男性化-女性化”维度。</li>\n<li><strong>相关分析</strong><br>\n分析 CIELAB 色彩值与感知评价之间的相关性。例如：\n<ul>\n<li>明度 <code>L*</code> 与“丝绸-唤醒度”的相关系数高达 <strong>0.89</strong>。</li>\n<li><code>a*</code> 值（红-绿轴）更强烈影响了麻的“女性化”感知（<code>r=0.50</code>）。</li>\n<li><code>b*</code> 值（黄-蓝轴）更影响棉布的“愉悦”感知（<code>r=0.55</code>）。</li>\n</ul>\n</li>\n</ul>\n</li>\n</ol>\n<h3>3.2 涉及的数据分析原理</h3>\n<ol>\n<li><strong>心理量表 → 定量化</strong>\n<ul>\n<li>把主观的“暖/冷”“喜欢/不喜欢”用 7分制数字化，便于统计。</li>\n<li>原理：把“定性感受”转化为“定量数据”，才能比较和分析。</li>\n</ul>\n</li>\n<li><strong>显著性检验（t检验）</strong>\n<ul>\n<li>判断不同材质或颜色带来的感知差异是否<strong>真实存在</strong>而非偶然。</li>\n<li>原理：如果p值 &lt; 0.05，就认为差异显著。</li>\n</ul>\n</li>\n<li><strong>相关分析</strong>\n<ul>\n<li>研究数值型变量之间的关系（比如明度和愉悦感）。</li>\n<li>原理：相关系数 r 接近 ±1 代表强相关，接近 0 代表弱相关。</li>\n</ul>\n</li>\n<li><strong>多变量分析</strong>\n<ul>\n<li>一个感知结果往往同时受到多因素（材质、颜色、明度、色相）的影响。</li>\n<li>原理：通过分解 a*, b*, L* 等参数，找到主导因素。</li>\n</ul>\n</li>\n</ol>\n<h3>3.3 生活中的类比与例子</h3>\n<ol>\n<li><strong>Likert 量表的生活应用</strong>\n<ul>\n<li>在餐厅吃饭后，你可能被要求对“味道”“服务”“环境”打 1-7 分。这与论文中让受试者评价“冷暖感”“厚薄感”是一样的原理。</li>\n</ul>\n</li>\n<li><strong>显著性检验的例子</strong>\n<ul>\n<li>比如商场要验证“红色促销标签是否比蓝色标签更吸引人”。他们可以记录两组标签下的购买率，用t检验来判断差异是否显著。</li>\n</ul>\n</li>\n<li><strong>相关分析的例子</strong>\n<ul>\n<li>天气与冰淇淋销量：温度（数值）与销量（数值）常常有正相关，越热卖得越多。</li>\n<li>对应到论文中：布料越亮（L*值高），受试者对“丝绸-唤醒度”的打分就越高。</li>\n</ul>\n</li>\n<li><strong>多变量影响的例子</strong>\n<ul>\n<li>选购一部手机，你的满意度不仅取决于“外观颜色”，还取决于“重量、手感、品牌”。这和论文中研究“颜色+材质共同影响人类感知”是一样的道理。</li>\n</ul>\n</li>\n</ol>\n<p>✅ <strong>总结</strong>：这篇论文通过 <strong>心理量表 → 定量化、统计检验、相关分析</strong> 等方法，揭示了“颜色”和“材质”如何影响人们对织物的感知。这套数据分析思路完全可以迁移到日常场景，比如消费者调查、市场营销、产品设计等领域。</p>\n<h2>3.4 配对 t 检验</h2>\n<h4>3.4.1 什么是配对 t 检验？</h4>\n<p>配对 t 检验是一种统计方法，用来比较<strong>同一组对象在不同条件下的差异</strong>是否显著。</p>\n<p>👉 <strong>“这两个情况的差别，是真实存在的，还是只是巧合？”</strong></p>\n<ul>\n<li>\n<p><strong>核心思想</strong>：看“差异”是不是偶然的。</p>\n</li>\n<li>\n<p><strong>前提</strong>：同一对象在两种情境下都有结果（成对数据）。</p>\n</li>\n<li>\n<p><strong>结果解读</strong>：</p>\n<ul>\n<li>p &lt; 0.05 → 差异显著，说明条件真的影响了结果；</li>\n<li>p ≥ 0.05 → 差异不显著，说明差异可能只是随机波动；</li>\n</ul>\n</li>\n<li>\n<p>假设你想知道：<strong>“苹果手机是不是比安卓手机拍照更好看？”</strong></p>\n</li>\n<li>\n<p>你找了 50 个朋友，每个人用 <strong>同一场景</strong>拍两张照片：一张用苹果，一张用安卓。</p>\n<p>然后让他们打分（比如 1-7 分）。</p>\n<ul>\n<li>\n<p>如果大家普遍觉得苹果分数更高，而且差距不是一点点，那么配对 t 检验会告诉你：</p>\n<p>→ “是的，这差别是真的，不是运气。”</p>\n</li>\n<li>\n<p>如果差距很小，很多人时高时低，配对 t 检验就会告诉你：</p>\n<p>→ “这可能只是随机波动，不算真差别。”</p>\n</li>\n</ul>\n</li>\n<li>\n<p><strong>为什么叫“配对”？</strong></p>\n<p>因为同一个人要同时体验两种情况（苹果 vs 安卓），结果是一对一对的，这就是“配对数据”。</p>\n</li>\n</ul>\n<h4>3.4.2 在论文里的应用</h4>\n<p><strong>研究者想知道：</strong></p>\n<blockquote>\n<p><strong>“同一种颜色放在不同材质的布料上，人们的感知是不是会变？”</strong></p>\n</blockquote>\n<p>论文比较了<strong>同一种颜色</strong>，但放在不同材质上（棉 vs 麻、麻 vs 丝、棉 vs 丝），人们的感知是否不同。</p>\n<p>例子：</p>\n<ul>\n<li>\n<p>一块“红色棉布” vs “红色丝绸”</p>\n<p>受试者对“厚薄感”“冷暖感”“男性化-女性化”打分不同。</p>\n<p>如果这个差异在统计学上显著（p &lt; 0.05），就能说明：<strong>材质确实会改变人对颜色的感知</strong></p>\n</li>\n</ul>\n",
      "image": "https://bornforthis.cn/gzh.jpg",
      "date_published": "2025-08-23T08:26:47.000Z",
      "date_modified": "2025-09-03T12:15:20.000Z",
      "authors": [
        {
          "name": "AI悦创"
        }
      ],
      "tags": []
    },
    {
      "title": "13-竞品分析：教你如何做竞品分析",
      "url": "https://bornforthis.cn/column/%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90%E6%80%9D%E7%BB%B4%E4%B8%8E%E5%AE%9E%E6%88%9823%E8%AE%B2/14.html",
      "id": "https://bornforthis.cn/column/%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90%E6%80%9D%E7%BB%B4%E4%B8%8E%E5%AE%9E%E6%88%9823%E8%AE%B2/14.html",
      "summary": "你好，我是悦创。 今天我主要讲解如何做竞品分析。 本课时内容主要分为三部分： 为什么要做竞品分析； 竞品分析的步骤； 爱奇艺与优酷的竞品分析。 1. 为什么要做竞品分析 在前面的课时，我介绍的分析方法都是针对自身 App，像指标体系、流量分析、路径分析。 假设你当前所处的行业是老大，这个时候肯定要防止外来者，警惕行业老二和老三；假设你是当前行业老二，肯...",
      "content_html": "<p>你好，我是悦创。</p>\n<p>今天我主要讲解如何做竞品分析。</p>\n<p>本课时内容主要分为三部分：</p>\n<ul>\n<li>\n<p>为什么要做竞品分析；</p>\n</li>\n<li>\n<p>竞品分析的步骤；</p>\n</li>\n<li>\n<p>爱奇艺与优酷的竞品分析。</p>\n</li>\n</ul>\n<h2>1. 为什么要做竞品分析</h2>\n<p>在前面的课时，我介绍的分析方法都是针对自身 App，像指标体系、流量分析、路径分析。</p>\n<p>假设你当前所处的行业是老大，这个时候肯定要防止外来者，警惕行业老二和老三；假设你是当前行业老二，肯定要看老大最近在做什么，从而模仿超越；假设你当前是行业老三或老三以后，一方面肯定要紧跟老大老二，另一方面要放大招，弯道超车。所以在行业中无论处于什么位置都要去分析竞品。</p>\n<p>在实际工作中，做竞品分析有以下几种情况：</p>\n<ul>\n<li>\n<p>当你的产品准备进入某个行业时，需要先把该行业的竞品分析清楚，主要侧重行业规模和前景的分析；</p>\n</li>\n<li>\n<p>当你的产品发展处于下降阶段，需要看竞争对手在做什么，主要侧重头部玩家的玩法分析；</p>\n</li>\n<li>\n<p>当你的产品发展处于瓶颈阶段，需要看竞争对手的数据和功能迭代，持续监控对手数据，从中寻找突破；</p>\n</li>\n<li>\n<p>当你的产品发展处于快速上升期  ，一般不会做竞品分析。</p>\n</li>\n</ul>\n<p>对于一款 App ，分析师在初期就要监控好竞品的各项数据，只有这样才能保持对竞品数据的敏感性，同时跟自身 App 数据结合起来思考优化迭代。</p>\n<p><strong>到底什么是竞品分析？</strong></p>\n<p>网上写的很多分析报告，把竞品的功能罗列太多，这其实是最初级的产品体验分析。竞品分析绝不是大而全地把竞品的功能罗列一遍，也不是日常的竞品数据监控，配置一张报表就完事。</p>\n<p><strong>竞品分析包含两个点。</strong></p>\n<ul>\n<li>\n<p>竞品的选择：哪些才是竞品？不要小看这件事，很多产品经理都没想清楚。并不是所有的头部行家都是你的竞品，而是要根据你做竞品分析的目的来选择。</p>\n</li>\n<li>\n<p>分析什么点，这就需要你知道分析的背景是什么，从而有针对性切入。</p>\n</li>\n</ul>\n<p>其中分析什么点最关键，你需要知道你的 Leader 想做什么，如果这件事他自己也说不太清楚，那最好先别投入大量时间去做，不是你做得对或不对，而是问题都没搞清楚，即使他是 Leader。</p>\n<h2>2. 竞品分析的步骤</h2>\n<p>竞品分析分为三步。</p>\n<h3>2.1 第一步：确定分析目的</h3>\n<p>所有数据分析的第一件事，就是要搞清楚分析的目的是什么？做分析时一定是要带着某种商业意图来做，不要忘记初心。分析目的分以下几种情况。</p>\n<ul>\n<li>\n<p>当你尝试进入某个新的行业，需要评估可行性。比如唯品突然想做唯品金融，这个时候肯定就要评估可行性。这种竞品分析更加偏行业趋势、市场规模，财务收入，看大数不拘于小节。比如说看一下目前整个金融行业的情况，另外看一下电商类公司的发展，比如京东金融是怎么做的。</p>\n</li>\n<li>\n<p>纯粹看竞品的功能、玩法和数据，学习优点。人无我有，人有我优，主要以学习为主。这种分析目的比较常见，主要以功能体验、运营手法、具体数据为主，落地性非常强。</p>\n</li>\n<li>\n<p>通过看竞品的不同版本迭代的功能、玩法和数据，揣摩竞品想干什么，目的以预防为主。看竞品的版本迭代，思考竞品最近的战略中心在哪，这种情况往往是为了满足管理层的需要。</p>\n</li>\n</ul>\n<h3>2.2 第二步：挑选 1～2 家竞品，进行对比分析</h3>\n<p>我们知道分析目的之后，下一步需要拉竞品跟我们自身进行对比。这时候首先挑选核心功能一样的 1～2 两家竞品，其次是功能体验分析，再就是运营手法分析。分析竞品的功能是怎么运用的，侧重对比运营手法。最后看宏观和微观的数据分析，也就是数据源，竞品数据源很关键，比如基础数据、财务数据、市场数据。</p>\n<p>整个的过程是一项由分析师牵头与产品、运营协助的团队任务，同时可能还需要财务、市场部的参与才能完成。</p>\n<h3>2.3 第三步：给初步分析结论</h3>\n<p>第三步就是在第二步的基础之上给出一些初步结论。</p>\n<p>比如你尝试进入某个新的行业需要评估可行性，那你最终的结论就是回答这个问题。是否可以进入这个行业？如果可以进入，步骤是什么？</p>\n<p>比如你纯粹看竞品的功能玩法和数据，学习优点。那你最终的结论要落到竞品的什么功能好？接下来产品和运营如何去做？这样做预计能带来多少收益？</p>\n<p>比如你只是看竞品不同版本迭代的数据，揣摩竞品想干什么，那你最终的结论就是竞品的下一步战略是什么？我们要不要也做某种尝试？实际上这种非常难，需要管理人去拍板。</p>\n<h2>3. 优酷爱奇艺会员案例分享</h2>\n<p>以上是一些方法论，现在我以优酷、爱奇艺为例，具体来说下竞品分析（可能双方 App 版本有更新，例子请以我截图为准）。</p>\n<p>案例背景：</p>\n<p>当下小 A 是负责优酷 App 会员模块的数据分析师，Q3 季度优酷会员增长乏力，而爱奇艺会员仍处于高速增长阶段。管理层希望对爱奇艺会员进行一次分析，学习爱奇艺会员的优点，从而提升优酷会员数。</p>\n<p>从案例背景可以看出分析目的是提升优酷会员数，分析对象为爱奇艺。我们来看具体怎么做？</p>\n<p>第一步先看基础数据，如果公司有内部数据，直接用即可。如果没有可以使用外部数据源，外部数据源基本上可以从 Google、百度、Questmoblie、百度指数获取，但数据源只是一个参考。对于爱奇艺，其实我们能够拿到很多数据，但不是每一个数据都需要看，关键是你要想清楚看过这些数据后，对后面分析有什么用。</p>\n<p>既然是分析会员数，我们首先要知道爱奇艺会员数跟优酷会员数的差距，如图所示。</p>\n<figure><figcaption>（数据来源为 Google，不是真实数据，仅举例）</figcaption></figure>\n<p>从图中可以看出爱奇艺会员数明显占优势，这是一个基础数据。其次我们要看画像，如果优酷和爱奇艺的用户画像比较类似，那么同样的功能，同样的运营手段就对双方都合适。</p>\n<p>用户画像可以从百度指数看，如下图所示。</p>\n<figure><figcaption></figcaption></figure>\n<p>从图中可知这两款 App ，无论是性别、年龄、地域都比较类似。在这个基础之上，我们去学习爱奇艺的优点是可以解决问题的。如果你这里贴出用户数使用时长，实际上意义不大，因为这对你后面的分析没用，所以第一步一定要想清楚你后面想干什么，然后再去查一些数据的对比，用这些数据来佐证你的想法。</p>\n<p>第二步是产品的对比，产品的对比有很多种方法，一般先画交互流程图，然后再体验产品模块。这样的优点是大而全，但缺点是在有限时间内不一定能得到结论。实际工作中还是要交给专业产品来做，分析师可以提供一种方法，这种方法就是从普通用户去看产品，看用户的真正需求和困惑点在哪里，基本上可以通过线上问卷或者线下调研得出结论。</p>\n<p>假设我们发现用户犹豫买会员的原因有以下几种，如图所示。</p>\n<figure><figcaption></figcaption></figure>\n<p>我们把用户的痛点归纳为这几种情况：</p>\n<ul>\n<li>\n<p>选择困难症——不知该买哪一家；</p>\n</li>\n<li>\n<p>退货——用户感觉价格太高、用户担心买了不满意；</p>\n</li>\n<li>\n<p>功能价值——付费功能吸引力不够。</p>\n</li>\n</ul>\n<p>在这个基础之上，我们已经知道了用户的痛点。从这个角度去切入做产品对比，如下图所示（左为爱奇艺，右为优酷）。</p>\n<figure><figcaption></figcaption></figure>\n<p>结合用户所关心的痛点，我们就来对比下爱奇艺和优酷这两款 App 。</p>\n<ul>\n<li>\n<p>选择困难症：相对来说，爱奇艺告诉了用户为何要买它，VIP 写得非常多，也非常明显，再加上体育会员和 FUN 会员还有会员俱乐部，提前抢占了用户心智。而优酷这方面比较弱，所以做一款 App ，你的传播符号一定要很强。</p>\n</li>\n<li>\n<p>退货：用户购买后感觉不满意想退货退款，这里爱奇艺和优酷都没有给出解决方案。其实电商开始做 7 天免费退货也是一种巨大创新，所以可以在这方面探索下。</p>\n</li>\n<li>\n<p>功能价值：当用户打开 App 时，一定要让用户感受到这款 App 对他有价值，这个时候最好的就是个性化推荐。爱奇艺当前没有个性化推荐，而优酷有个性化推荐。</p>\n</li>\n</ul>\n<p>再进一步就是用户关心的价格，如下图所示（左为爱奇艺，右为优酷）。</p>\n<figure><figcaption></figcaption></figure>\n<p>爱奇艺价格优势很明显，特别是新用户首 3 月优惠，这对拉新非常给力，而优酷在这一块做的没有爱奇艺好。同时在价格这个单独的模块上，爱奇艺界面上有京东 PLUS 年卡、客服、常见问题、银行卡支付、学生会员、退出时会员弹窗提醒等，这些细节都很好，而优酷相对来说差些。</p>\n<p>实际上用户很在意价格相关问题，可以去结合客服数据进行优化。产品分析的目的是人有我无，学习他人的优点。从用户痛点去出发，对比两款 App 看竞品有哪些优点功能，而我们没有。</p>\n<p>接下来是竞品之间的运营手法对比。在分析之前，我们先来理解下产品和运营的角色。你可以把产品理解为生孩子，运营是来养孩子。运营把孩子养大，需要持续观察孩子成长阶段的各个指标，保证他健康成长，成长的时候看他的身高体重，上学的时候看他的成绩，长大后看收入，这个过程可以理解为数据分析。</p>\n<p>所有用户运营的目的都是提新增、拉留存、降流失，这就是广义的用户运营概念。所有的运营往往需要产品内容和产品活动的支撑来吸引用户。</p>\n<p>内容运营：通过内容来吸引用户，比如我这门课本身就是内容运营。</p>\n<p>活动运营：通过做活动来吸引用户，比如 App 抽奖活动。</p>\n<p>举个例子：目的是通过优化渠道来提升新增用户数，那么就可以优化渠道文案、在渠道侧做一些活动激励。这就是通过内容运营、活动运营来达到最终用户运营。</p>\n<p>在这个基础之上，我们看下爱奇艺和优酷在用户运营、活动运营、内容运营上面的情况，如下图所示（左为爱奇艺，右为优酷）。</p>\n<figure><figcaption></figcaption></figure>\n<p>首先是用户运营，这里我们看到爱奇艺有签到，点击进去还有 0 元秒杀。而新用户进入优酷后只提示要续费，仪式感和趣味性缺少。</p>\n<p>然后是活动运营，爱奇艺是 IP+会员，比如“VIP 福利来袭，买特权卡送 3 重国风特权”，这国风特权就是一个超大 IP，还有学生会员相关提示。而对于优酷，它只有一个双 12 活动会员，没什么新意。</p>\n<p>接下来看内容运营，这是难得的一个差异内容，运营就是讲究内容。爱奇艺有两个大 Banner 轮播，而优酷只有一个大 Banner，双方有较大差异。</p>\n<p>总结如下表：</p>\n<figure><figcaption></figcaption></figure>\n<p>最后在内容运营里面，我单独会把内容生态拿出来讲，爱奇艺围绕内容有一个会员俱乐部。而优酷也有一个俱乐部。我们看一下这两个俱乐部，如下图所示（左为爱奇艺，右为优酷）。</p>\n<figure><figcaption></figcaption></figure>\n<p>从图中可知，无论是 UI、用户使用便捷性、分类 tab 丰富度、大 Banner，爱奇艺均明显优于优酷。爱奇艺的用户一进入 App，用户就可以知道会员特权可以做哪些事，而优酷并没有给用户这种感觉。在会员俱乐部这个最核心的玩法上，优酷提升空间巨大。</p>\n<p>到这里，我们已经对爱奇艺和优酷的基础数据对比、产品对比、运营对比都做了分析，并且找到了切入点。那么就可以找产品和运营去落地。到这里，竞品分析的目的已经达到，只需要执行即可。我们分析的结论可以给产品运营具体的落地方案、跟进人、优先级、预期上线时间及预期效果，如下表所示。</p>\n<figure><figcaption></figcaption></figure>\n<p>首先对产品的落地项。第一是新用户会员价格的调整，这里面就需要进一步给出合理的价格曲线，你要考虑收入成本，这比较复杂，但是分析师可以参与进去；第二是在会员最里面的模块增加客服功能，因为用户要付费，不能把每个用户都当成老司机，用户付费时肯定会有一些疑问，这时候你至少要有常见问题回答；第三是退货功能的尝鲜，因为爱奇艺没有涉及，优酷是不是可以进一步分析，做一些尝试，这个需求优先级可以低些。</p>\n<p>然后是对运营的落地项，我有两个建议。比如，第一个签到功能位置调整，因为当前优酷 App 有签到功能，但藏得很深，所以要把签到暴露在会员首页当中，虽然只是一个小的坑位，但效果可能会很好。同时也有一些效果，比如我们的签到渗透率和会员增加人数是不是都有一个估值。第二是要完善活动的丰富度，因为当前优酷的活动玩法太通俗化，双 12 加会员这个玩法，大家都能玩，优酷得有自己的一个核心竞争力。</p>\n<p>对于上述表格中的前四个需求，产品和运营一定是可以拉资源，然后去落地，因为大家的主要目的就是提升会员数。在落地这件事上，分析师一定要充当先锋角色，尽最大努力去推动这件事。什么叫最大努力？比如，你去找产品或者运营，他们好像不太上心，这个时候可以去找他们 Leader 或者找自己 Leader 说明情况，双方 Leader 做一些决策，这时推动会更加容易。到这里，爱奇艺和优酷的竞品分析基本上完成了。</p>\n<p>总结一下，我们做竞品分析的整体步骤。</p>\n<p>第一步：确定分析的目的。</p>\n<p>第二步：进行对比分析。</p>\n<p>宏观基础数据。</p>\n<p>竞品功能。</p>\n<p>竞品的运营手段。</p>\n<p>第三步：给初步分析结论。</p>\n<p>最后我给你出一个思考题：视频行业不同阶段的老大分别是谁，他们各自又是如何成为老大的？</p>\n<p>其实视频行业不同阶段的老大分别是谁，这个答案，你去百度一下就可以知道，最主要的是他们如何成为老大，这个很关键，你思考后可以在下方留言。</p>\n<p>今天的课程就到这里，欢迎你关注我本人的公众号（微信搜索：AI悦创），之后会定期更新原创高质量的数据分析文章，下节课见，谢谢。</p>\n<details class=\"hint-container details\"><summary>公众号：AI悦创【二维码】</summary>\n<figure><img src=\"/gzh.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n</details>\n<div class=\"hint-container info\">\n<p class=\"hint-container-title\">AI悦创·编程一对一</p>\n<p>AI悦创·推出辅导班啦，包括「Python 语言辅导班、C++ 辅导班、java 辅导班、算法/数据结构辅导班、少儿编程、pygame 游戏开发、Web、Linux」，招收学员面向国内外，国外占 80%。全部都是一对一教学：一对一辅导 + 一对一答疑 + 布置作业 + 项目实践等。当然，还有线下线上摄影课程、Photoshop、Premiere 一对一教学、QQ、微信在线，随时响应！微信：Jiabcdefh</p>\n<p>C++ 信息奥赛题解，长期更新！长期招收一对一中小学信息奥赛集训，莆田、厦门地区有机会线下上门，其他地区线上。微信：Jiabcdefh</p>\n<p>方法一：<a href=\"http://wpa.qq.com/msgrd?v=3&amp;uin=1432803776&amp;site=qq&amp;menu=yes\" target=\"_blank\" rel=\"noopener noreferrer\">QQ</a></p>\n<p>方法二：微信：Jiabcdefh</p>\n</div>\n<figure><img src=\"/zsxq.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n",
      "date_published": "2025-07-26T08:42:30.000Z",
      "date_modified": "2025-09-12T06:54:19.000Z",
      "authors": [
        {
          "name": "AI悦创"
        }
      ],
      "tags": []
    },
    {
      "title": "12-路径分析：用户的使用路径网络分析",
      "url": "https://bornforthis.cn/column/%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90%E6%80%9D%E7%BB%B4%E4%B8%8E%E5%AE%9E%E6%88%9823%E8%AE%B2/13.html",
      "id": "https://bornforthis.cn/column/%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90%E6%80%9D%E7%BB%B4%E4%B8%8E%E5%AE%9E%E6%88%9823%E8%AE%B2/13.html",
      "summary": "你好，我是悦创。 今天我主要讲解路径分析。 本课时内容分为三部分： 路径分析定义； 路径分析案例——以美团 APP 为例； 路径分析思考。 1. 路径分析定义 我们在讲前面的案例中多次提到了漏斗模型，漏斗模型是非常经典的一种分析方法，但所有的漏斗都是人为假设的，也就是事前假设一条关键路径，事后看关键路径的转化数据。 随着各类 APP 的功能模块、坑位越...",
      "content_html": "<p>你好，我是悦创。</p>\n<p>今天我主要讲解路径分析。</p>\n<p>本课时内容分为三部分：</p>\n<ul>\n<li>\n<p>路径分析定义；</p>\n</li>\n<li>\n<p>路径分析案例——以美团 APP 为例；</p>\n</li>\n<li>\n<p>路径分析思考。</p>\n</li>\n</ul>\n<h2>1. 路径分析定义</h2>\n<p>我们在讲前面的案例中多次提到了漏斗模型，漏斗模型是非常经典的一种分析方法，但所有的漏斗都是人为假设的，也就是事前假设一条关键路径，事后看关键路径的转化数据。</p>\n<p>随着各类 APP 的功能模块、坑位越来越多，用户的行为越来越分散化，比如很多 APP 不止有一个核心功能，可能有若干个核心功能。这个时候就要在用户的所有操作行为中，发现一些产品设计之初可能不知道、但非常有意思的用户前后行为，这就是路径分析。也就是说，路径分析是基于数据本身发现的，产品可能不太清楚，但是符合用户习惯的路径。</p>\n<ul>\n<li>\n<p><strong>漏斗分析</strong>：人为设定一条或者若干条漏斗。<strong>先有假设再数据验证</strong>。</p>\n</li>\n<li>\n<p><strong>路径分析</strong>：基于用户的所有行为，去挖掘出若干条重要的用户路径，通过优化界面交互让产品用起来更加流畅和符合用户习惯，产生更多价值。<strong>先有数据再验证假设</strong>。跟漏斗分析刚好相反。</p>\n</li>\n</ul>\n<p>我们举个例子。</p>\n<figure><figcaption></figcaption></figure>\n<p>比如对于美团 APP 来说，我们发现它有很多功能，比如“搜索”“美食”“电影演出”“酒店住宿”“休闲娱乐”“外卖”这 5 个 tab，下面还有“家居”等。然后下面有 4 个小模块：“很优惠”“有格调”“秒杀”“周末去哪儿”，再往下翻是“猜你喜欢”，也就是个人推荐，而在底部 button 有“附近”“发现”“订单”“我的”，各个 button 里面又有很多子模块。</p>\n<p>基本上目前市面上大多数 APP 都是这种多坑位，把能做的都做了。在这种情况下，漏斗分析确实完全满足不了日常分析需求，因为漏斗分析相对来说都是人为事先假定的，而且内容比较符合大众认知的习惯，这个时候就要路径分析派上用场了。</p>\n<p>这就是路径分析的背景。</p>\n<h2>2. 路径分析过程</h2>\n<p>那么我们对路径分析的过程进行一个详细的说明。大家在听第二小模块的时候，一定要把美团 APP 多体验几次，后面会涉及大量的界面交互和路径使用，所以各个模块都要认真看几遍。</p>\n<h3>2.1 日志介绍</h3>\n<p>我们先说一下日志，因为路径分析实际上都是基于底层日志来做，有些同学可能没有看过公司本身的日志，用户在端内（ APP 内），所有的行为都是以表或者文件存储的，其中记录了用户最详细的行为信息，这就是日志。比如，你打开 APP，实际上在日志里面是有一条记录的，一般都是一行，格式如下图所示：</p>\n<figure><figcaption></figcaption></figure>\n<p>首先，对于日志我们怎么看？我们看到中间行与行之间是分段的，这个分段就代表每一条记录。这个日志首先是 Key-Value 格式，就以第一条记录来说，imei 和 ip 中间是以逗号分隔，每一条记录与记录间是行的分割。然后有哪些字段呢？我们有用户的设备号 imei、IP、内存、分辨率、机型、系统，event 和 active 事件、版本、子版本、操作时间 Unix time。</p>\n<p>所以对于分析师来说，要知道自己公司本身底层日志是以什么格式来存储的，不一定是 Key-Value 格式，这块操作更多偏 Linux 命令，基本上分析师都会一些基本的命令，比如查今天的日志大小或者日志的一些字段，那么在这块查一下就行了。如果一个分析师每天大部分时间跟这种底层日志打交道，那一定是有问题的，因为这一块相对比较独立，更多的时候是数据研发工程师或者后台研发本身就应该做的事情。</p>\n<h3>2.2 日志分析步骤</h3>\n<p>当我们熟悉了日志的字段以及格式之后，就可以进行路径分析了，因为路径分析本身就是啃日志。路径分析一共分为四个步骤：</p>\n<ol>\n<li>\n<p><strong>筛选</strong>：第一步是对所有功能用户的量级进行查看，筛选出重要功能，因为当前 APP 可能有 100 个子功能，那么到底要看哪些呢？这个时候就要用用户量级来评判了，首先选出这样的功能，找到切入点。</p>\n</li>\n<li>\n<p><strong>日志关联（抽样）</strong>。第二步，就是对筛选出的功能进行时间序列的<strong>排序</strong>，比如对于一个用户来说，一天可能有 10 个重要功能，那这 10 个重要功能的先后顺序是什么样子？你要先排序，既然是路径分析，肯定有先后，排完序之后就是日志与日志之间的功能数据的匹配，比如用了 A 功能之后有多少用户用了功能 B？这个就是同一份日志相互间匹配，但是一定是先排序好。然后就是关联，对于所有的路径分析，日志关联都是抽样，因为公司的日志可能非常大，如果要做这一步关联，资源是跟不上的，所以抽样就可以了，基本上抽 10 万、 20 万数据就可以。</p>\n</li>\n<li>\n<p><strong>标准化及画图</strong>：第三步就是数据的标准化以及路径画图，因为第二步是相对绝对的数据，比如使用功能 A 的用户是 100 万，然后这 100 万里面有 80 万用了功能 B，实际上还是这种绝对量级的数据，而第三步是让第二步更加可视化以及标准化。</p>\n</li>\n<li>\n<p><strong>启发</strong>：第四步就是在第三步的基础之上，看有没有比较有启发性的路径，大部分公司做路径分析都要从第一步开始，一步一步来做。但是有一些公司在技术层面一二三步已经帮你搞定了，就是底层研发把一二三都已经做了，然后分析师相对来说要轻松，看第四步就可以了，这就比较好。</p>\n</li>\n</ol>\n<p>整个过程不是特别难，但是非常考验耐心，大家可以这样理解，就是你沉浸在日志当中，然后去干各种各样的行为。我们举例子来说，这样比较生动。</p>\n<h4>2.2.1 筛选</h4>\n<p>第一步筛选，对于美团 APP，假设它的主要功能以及功能渗透率的数据如下表所示：</p>\n<figure><figcaption></figcaption></figure>\n<p>我们通过这些功能渗透率就发现，“美食”“外卖”“搜索”是三个最大的功能，因为它们的渗透率都很高，达 30% 以上；“电影”和“酒店”这两个重大的 tab 渗透率并不高，也就是表现不是很好；而“周边游/旅游”以及“景点/门票”这两个 tab 位置不是特别好，但表现比较好；而底部的“附近” button 只有 18% 的渗透率，“发现”是 3%，“订单”是 20%，“我的”是 8%。在此基础上，我们就可以进一步筛选出要分析的功能。</p>\n<p><strong>筛选结论</strong>：</p>\n<ol>\n<li>“美食”“外卖”“搜索”三大功能：需要进一步看之后用户路径，这里就以美食为例；</li>\n<li>“附近”作为底部第二 button，存在什么问题？可以如何进一步优化？它的渗透率只有 18%，比订单还低；</li>\n<li>“发现”作为底部第三 button，用户感知度太弱，如何定位该功能价值？我们丝毫不怀疑可能产品想往内容这一块转，但是当前发现的渗透率只有 3%；</li>\n<li>“订单”功能作为底部第四 button，渗透率竟然有 20%，表现很好，用户进来后干什么？如何进一步优化？</li>\n<li>“我的”作为底部第五 button，有 8% 的渗透率，我们比较好奇用户进去后干啥。</li>\n</ol>\n<p>所以先要找到切入点。</p>\n<p>第一步是找到所有重要功能，然后在这个基础之上，发现有没有一些点比较有意思，找到切入点。本课时后面是以 1/2/4 这三块一个一个展开，其他的大家可以类似地去发散联想具体怎么做就可以了。</p>\n<h4>2.2.2 数据进一步关联及标准化</h4>\n<p>第二步就是数据进一步关联及标准化。刚刚说了，我们会对“美食”“订单”以及“附近”这三个功能进行查看。</p>\n<p><strong>美食</strong></p>\n<p>我们先看“美食”，假设“美食”的原始数据如下表：</p>\n<figure><figcaption></figcaption></figure>\n<p>我们先看“美食”，假设“美食”的原始数据如下表：</p>\n<figure><figcaption></figcaption></figure>\n<p>它是一个很重要的功能，进来之后用户有各种各样的路径，然后我们按照时序来排列，这个 1,2,3,4,5,6 假设是按照先后顺序。</p>\n<p>100 万人当中有 80 万去了“离我最近”。这个“离我最近”是在智能排序这里，进行手动切换之后就是“离我最近”，也就是说有 80 万用户进来之后直接点了“离我最近”。进去之后有 75 万用户进入详情页，比如点这个“百果园”，直接进去的有 75 万，然后 75 万里面有 40 万用户又返回到“离我最近”这个界面，也就是说用户逛了一会儿之后回退。然后 40 万里面又有 30 万用户再进入另外一个详情页，最终这 30 万里面有 20 万下单。这是第一个路径，就是 100 万的美食用户有 80 万用户是走这样一个路径。</p>\n<p>同时第二个路径是 100 万里面有 30 万进入“优惠团购”这里，“优惠团购”里面又是一个界面，然后有 25 万人用了上面的搜索功能，实际上比较奇怪，因为“优惠团购”的界面已经有比较多的商品可以选购了，但是用户用了搜索，然后 25 万的搜索里面又有 20 万的用户进入详情页，然后 20 万里面有 18 万进行下单。这是第二个用户路径。</p>\n<p>第三个用户路径就是 100 万用户里面有只有 5 万用户进入“外卖”，也就是说“外卖”放在美食里面这样一个位置，它的渗透率并不是很高。</p>\n<p>第四个就是“限时秒杀”这一块，100 万用户有 30 万用户进入到这里面，而 30 万用户里面有 28 万点击详情页，跟第一个路径比较像，又进行了回退，进入另外一个详情页再下单，也就是说用户有返回的操作。</p>\n<p>这个就是原始数据，就是对底层日志进行时序排列，然后日志与日志之间相互匹配，之后就是这样一份数据，这样一份 excel 表格。</p>\n<p>那么在这个关联数据的基础之上进行标准化以及画图：</p>\n<figure><figcaption></figcaption></figure>\n<p>真实的过程中，大家不一定要按照这样来画，我这里只是为了说明问题。比如“美食”，这里面 80% 是到“离我最近”，30% 到“优惠团购”，5% 到“外卖”，30% 到“秒杀”，就是上面的转化率，同样的后面每一步都有一个转化率，这个就是这 100 万的美食用户在端内的主要路径。</p>\n<p>当然肯定还有其他路径，比如用户点“夜宵”，但是它的渗透率不是特别高，所以就不说了。这里就是发现一些比较有意思的路径，在这一步，它需要很多的耐心，因为你只能慢慢去看，这个在前期做的时候会非常耽误时间，但是就只能这样，因为所有的人做都是这样的过程，就是你要对业务非常了解。这个是“美食”用户进入“美食”之后的路径。</p>\n<p><strong>附近</strong></p>\n<p>第二步一样，对于“附近”这个模块，用户进来之后，假设他的数据是这样一种形态：</p>\n<figure><figcaption></figcaption></figure>\n<figure><figcaption></figcaption></figure>\n<p>我们发现，进入“附近”之后，大家看到最大的位置是“享美食”这一块，但是它的用户数只有 10 万，就是都是 50 万用户进来，只有 10 万用户到“享美食”，而“搜索”这一块儿竟然有 30 万，也就是说，更多的用户是通过“搜索”进入另外一个界面，也就是各种各样的店面，然后再进入详情页再下单，是通过这样一条路径来完成的。那么这个是不是就能说明我们当前界面做得并不是特别好？同时对于“享美食”“会生活”“爱玩乐”这三个 tab，理论上它们的点击率相对来说差异比较大，但是数据上面显示，一个 10 万、一个 9 万、一个 8 万，相差并不是很大。那么“享美食”作为最大的曝光界面可能就是出现了比较大的问题，从数据上来看就是这样的一个解释。</p>\n<p><strong>订单</strong></p>\n<p>我们再看一下第三个，就是“订单”。对于“订单”这个功能，首先它的界面是这样：</p>\n<figure><figcaption></figcaption></figure>\n<p>用户进来之后，上面是“最近订单”的曝光，底部有一个“最近浏览”，就这两块，然后具体数据是：</p>\n<figure><figcaption></figcaption></figure>\n<p>有 50 万的用户进入“订单”这个界面，其中 45 万直接到具体订单详情页，比如 45 万的用户直接点百果园，点进去之后有 40 万直接就退出这个界面了，具体的转化数据就是这个图：</p>\n<figure><figcaption></figcaption></figure>\n<p>都是 90%，也就是说，对于“订单”这个界面，用户的目的非常明确，因为 50 万用户进来之后最主要的路径就是这样，其他的都很少。假设数据就是这样，那么我们就要进一步调研，用户进入订单页面目的是什么？如果只是查一查订单，那么我们是不是能在里面做一些相关推荐？“最近浏览”做得太单薄了，而且还是做在外面，实际上用户进入订单详情页之后就直接走了，在最里面就直接走了，而不会返回当前界面。</p>\n<h4>2.2.3 基于前面数据，有哪些启发</h4>\n<p>数据上是这样一个结论，就是围绕一二三，一个是首页的“美食”，一个是“附近”，一个是“订单”，我们有哪些启发呢？因为到第二步实际上只是一个具体的标准化数据以及图，我们有哪些启发？</p>\n<figure><figcaption></figcaption></figure>\n<p>首先对于“美食”功能来说，默认的是智能排序，但是 80% 的用户会切换到“离我最近”，这里我的想法是，如果把智能改为综合字眼可能会更好，因为用户对智能可能理解得不是特别深刻，饿了么的精品就是综合排序。同时我们看到，用户第一次进入详情页之后，然后又有用户返回“离我最近”，也就是说用户有一个回退按钮，然后再进入详情页。这里建议在详情页内部增加相关推荐，让用户在里面逛，缩短用户的下单路径，而不要让他回退。</p>\n<p>第二个点就是在“美食”功能中，有 30% 的用户进入“优惠团购”，很明确，这部分用户喜欢占便宜，同时竟然有 83% 用了搜索，因为优惠团购点进去之后，它是一个最大的曝光位置，有很多的店家。但 80% 用户用了搜索，说明当前界面的主动推荐不太准确，需要优化，我们要更好地去揣摩用户的意图。</p>\n<p>同时对于“外卖”这块也一样，外卖放在那个位置不是特别好，可以考虑把它替换掉，可能外卖本身在最外部就有 40% 的流量，而在这里面只有 5%。对于“秒杀”也一样，也有一个回退，那么也可以考虑在详情页里面增加相关推荐。这个就是“美食”功能。</p>\n<figure><figcaption></figcaption></figure>\n<p>对于“附近”功能，我们发现首先 40% 的用户会回到首页，就是用户进入“附近”这个 button，然后又有 40% 用户立马跳回首页；60% 的用户用搜索，而“享美食”“会生活”“爱玩乐”的渗透率差异不大，“享美食”作为最大曝光界面占比，“附近”整个模块当前问题较大，就是用户进去了，但是你没有很好地满足用户的需求，很多用户就跳出来了，同时你最大的曝光界面没有人点，而是用了搜索为主。</p>\n<figure><figcaption></figcaption></figure>\n<p>而对于“订单”功能，90% 的用户查看订单后直接退出，可以考虑在订单详情页里面增加更多相关订单内容曝光，当前曝光内容是最近浏览曝光，效果不好，所以要增加用户消费场景。</p>\n<p>那么基于这三个路径，我们就可以做很多事情了。刚刚我们对“美食”“订单”“附近”这三个button做了一些分析，就已经发现了有很多优化点。当我们对其他功能也按照这种方式去分析的时候，就会发现有很多其他的可以改进的地方。</p>\n<p>所以实际上路径分析不难，就是日志跟日志之间匹配，然后去标准化数据，然后去画图，就是这样一个过程。但是路径分析是一件非常消耗体力的活，因为功能可能很多，用户前后行为可能非常多，这就需要分析师对业务非常熟悉，一定要每天都去使用自己的 APP，就是你不能把自己当作一个普通用户，你要把自己当作各类用户都要去体验自己的产品，因为用户在端内的任何行为都是合理的。</p>\n<p>每个产品经理都是负责自己的一小块功能，比如你是专门负责外卖的，而分析师就是最大的产品经理，站在全局的角度去看产品，外卖的产品经理不知道美食板块的数据，分析师是知道的，所以分析师提出某个落地项，既能优化当前功能，又能对其他功能没有负向影响，否则就没意义了，同时还能提升大盘数据。这非常考验综合思考力，就是你提出的某一个落地项，比如做这种 A/B，那么你不能光看最后对你这一小块功能的提升，同时还要看对其他功能有没有影响，只有在这个基础上对大盘有进一步提升，这个时候 A/B 测试才有很好的效果。</p>\n<h2>3. 路径分析思考</h2>\n<p>最后我们看一下对路径分析的思考，路径分析本身整个过程就是这样，更多公司在可视化这一块可能不太一样，有一些公司的可视化会相对来说会更加酷炫。那么路径分析当前还有哪些点可以进一步去做呢？前面我们对美团 APP 的路径分析的举例就到这里，实际上我本身对路径分析也有一些思考。</p>\n<ul>\n<li>\n<p>大家都知道我们刚刚说的所有路径分析都是以功能点的时序整体分析为主，只有指标没有维度，而要想精细化运营，必须要进行维度拆分，如通过不同入口，通过桌面或是通知栏进来的用户，他们的路径分析差异在哪？这就涉及做逻辑分析的时候要进行维度拆解，这是第一个点。</p>\n</li>\n<li>\n<p>第二个就是对于有些 APP，比如携程旅行、小猪短租，用户可能在今天打开 APP 后逛一会儿，然后就走了，过一周后再进来才下单，对于这种用户一天不连续路径，如何进行分析呢？其实这是一个行业难题，我之前去听一个 CEO 讲这一块的时候，也没有很好地解决，无论是进行周期时间段的 session 分析，还是短期画像的分析，效果都一般，这一块大家可以去想一想。</p>\n</li>\n<li>\n<p>第三个就是 PC 端的路径分析和 APP 端的路径分析最大差异在哪，同时 PC 端有没有案例，因为我们本节课就是讲 APP 端，那么这一节课的路径分析本身就要求你对一款产品的功能以及各种路径都要非常熟悉，所以大家一定要去多体验一下美团 APP，我前面提到的美食功能的几个路径以及画图，还有附近、订单等，这样的话大家才能更好地理解这节课的内容。</p>\n</li>\n</ul>\n<p>还是那句话，路径分析是非常实用的，但是在实际工作过程中，很多分析师没有去看用户的行为，这一块如果做好了，对你的用户最终的转化率是非常有帮助的。</p>\n<p>这一节课可能有一点难懂，因为路径分析跟你对 APP 的熟悉度非常有关。今天的课程就到这里，如果你有问题可以在下方留言，同时欢迎你关注我本人的公众号（微信搜索：AI悦创），之后会定期更新原创高质量的数据分析文章，下节课见，谢谢。</p>\n<details class=\"hint-container details\"><summary>公众号：AI悦创【二维码】</summary>\n<figure><img src=\"/gzh.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n</details>\n<div class=\"hint-container info\">\n<p class=\"hint-container-title\">AI悦创·编程一对一</p>\n<p>AI悦创·推出辅导班啦，包括「Python 语言辅导班、C++ 辅导班、java 辅导班、算法/数据结构辅导班、少儿编程、pygame 游戏开发、Web、Linux」，招收学员面向国内外，国外占 80%。全部都是一对一教学：一对一辅导 + 一对一答疑 + 布置作业 + 项目实践等。当然，还有线下线上摄影课程、Photoshop、Premiere 一对一教学、QQ、微信在线，随时响应！微信：Jiabcdefh</p>\n<p>C++ 信息奥赛题解，长期更新！长期招收一对一中小学信息奥赛集训，莆田、厦门地区有机会线下上门，其他地区线上。微信：Jiabcdefh</p>\n<p>方法一：<a href=\"http://wpa.qq.com/msgrd?v=3&amp;uin=1432803776&amp;site=qq&amp;menu=yes\" target=\"_blank\" rel=\"noopener noreferrer\">QQ</a></p>\n<p>方法二：微信：Jiabcdefh</p>\n</div>\n<figure><img src=\"/zsxq.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n",
      "date_published": "2025-07-24T09:39:52.000Z",
      "date_modified": "2025-07-26T01:54:18.000Z",
      "authors": [
        {
          "name": "AI悦创"
        }
      ],
      "tags": []
    },
    {
      "title": "智力脑｜04-互动阅读比给孩子“堆书”更有效",
      "url": "https://bornforthis.cn/Yuechuangs-Family-EducationHandbook/04.html",
      "id": "https://bornforthis.cn/Yuechuangs-Family-EducationHandbook/04.html",
      "summary": "和孩子一起读书，是我发现的“育儿神技”📚✨ 你好，我是悦创。 小时候读书，是一种逃离世界的快乐；当了爸妈之后才发现，读书也可以是和孩子之间最温暖的链接方式。 很多人以为，“亲子共读”只是培养感情的小项目。但在我看来，它其实是帮助孩子聪明成长的“神操作”之一。 📖 我为什么这么热衷亲子阅读？ 我是个爱读书到骨子里的人，哪怕每天只挤出十分钟，也要看上几...",
      "content_html": "<div style=\"text-align:center\">\n<p><strong>和孩子一起读书，是我发现的“育儿神技”📚✨</strong></p>\n</div>\n<p>你好，我是悦创。</p>\n<p>小时候读书，是一种逃离世界的快乐；当了爸妈之后才发现，读书也可以是和孩子之间最温暖的链接方式。</p>\n<p>很多人以为，“亲子共读”只是培养感情的小项目。但在我看来，它其实是帮助孩子聪明成长的“神操作”之一。</p>\n<div style=\"text-align:center\">\n<p><strong>📖 我为什么这么热衷亲子阅读？</strong></p>\n</div>\n<p>我是个爱读书到骨子里的人，哪怕每天只挤出十分钟，也要看上几页。有人问我为什么表达能力好，为什么讲课时能滔滔不绝，其实秘诀很简单：常年读书积累的结果罢了。</p>\n<p>但有了孩子后，我才明白，有一件事比自己读书更有意义——那就是和孩子一起读书。</p>\n<div style=\"text-align:center\">\n<p><strong>❓“我买了一堆书，孩子就是不爱读”，怎么办？</strong></p>\n</div>\n<p>很多爸妈都遇到过这个问题：书买了，架子也摆满了，结果孩子就是没兴趣，甚至一逼他看书反而更反感了。</p>\n<p>我以前也很头疼，直到我接触到了“<strong>互动阅读</strong>”。</p>\n<div style=\"text-align:center\">\n<h2><span style=\"color:orange\">《悦创的家庭教育宝典》查询结果：</span></h2>\n<h3><span style=\"color:orange\">互动阅读，能提升孩子智力</span></h3>\n</div>\n<p>💡<strong>互动阅读，是打开孩子阅读兴趣的金钥匙</strong>。</p>\n<p>你光把书摆在那儿，其实远远不够。阅读这件事，需要爸妈“参与”进去。</p>\n<p>这时候有家长会问：🔬<strong>有科学依据吗？</strong></p>\n<p>有！香港中文大学曾经做过一个实验，把 86 个小朋友分成三组，一组亲子互动阅读，一组爸妈只是自己念书，最后一组干脆没读。结果发现——只有互动阅读组的孩子，阅读能力进步最明显！</p>\n<p>国外研究也表明：互动阅读可以让孩子的智商提高平均 6 个点！</p>\n<h2>🧠 互动阅读的三个关键好处</h2>\n<ol>\n<li><strong>提升语言表达</strong>：问答互动能激发孩子说话的欲望，理解和表达双提升。</li>\n<li><strong>更沉浸的体验</strong>：不只是看图念字，而是把阅读变成一次亲子“共同冒险”。</li>\n<li><strong>塑造积极情绪</strong>：当孩子觉得读书=快乐，就会越来越主动地去读。</li>\n</ol>\n<p><strong>特别提醒</strong>：互动阅读对 4 岁以下的孩子效果最好。过了这个年龄段，效果会渐渐减弱。</p>\n<h2>🎯 实操指南：怎么和孩子进行互动阅读？</h2>\n<p>别担心，看完下面这几点，你就知道怎么做啦👇</p>\n<h3>1. 和孩子“聊”书，而不是单向朗读</h3>\n<ul>\n<li>举个例子：读到《三只小猪》，你可以问：“你觉得哪只小猪最聪明？”“如果你是大灰狼，你会怎么做？”</li>\n<li>不要只是问“对/错”这种封闭式问题，开放式问题才更能激发思考。</li>\n</ul>\n<h3>2. 跟着孩子的兴趣走，不要“死磕整本书”</h3>\n<ul>\n<li>孩子喜欢熊猫那一页？那就多聊聊熊猫！</li>\n<li>他问了一个冷门的问题？就顺着这个线索去探索。</li>\n<li>有时候，他可能只爱一本书的一页，也没关系，<strong>重要的是他乐在其中</strong>。</li>\n</ul>\n<h3>3. 把阅读变成游戏！</h3>\n<ul>\n<li>比如“找图比赛”：“快看，谁先找到大熊猫？”</li>\n<li>或者“猜情节”：读到悬念的时候暂停一下，让孩子来猜接下来会发生什么。</li>\n<li>加点夸张的情绪、搞笑的语调，甚至模仿角色声音，孩子会乐翻！</li>\n</ul>\n<h2>🚨 温馨提醒：不要把阅读变成“任务”</h2>\n<p>很多家长不自觉就让阅读带上了“<strong>功利</strong>”色彩：</p>\n<ul>\n<li>“读完书给你个冰淇淋” → 孩子理解为“读书=苦差事”</li>\n<li>孩子玩得正开心时强行打断 → 阅读变成“必须完成的正经事”</li>\n</ul>\n<p>正确姿势是：让阅读成为日常生活的一部分，甚至是最有趣的部分！</p>\n<h2>❤️ 我的亲子阅读经验小结</h2>\n<p>我家女儿现在快 1 岁了，我也准备开始互动阅读了，要一起一步步培养。</p>\n<p>想要把孩子培养好，真的不是靠填鸭式教育，而是靠着我们一天天坚持的亲子阅读时光。</p>\n<p>希望读者阅读完我这篇文章后，能达到：小孩每天睡前，都会抱着书来找我们：“爸爸，我们今天读这个吧！”对她来说，读书不是任务，是一天中最期待的亲密时光。</p>\n<p>你要知道，这些看似平常的亲子共读时光，其实正在悄悄帮她积累词汇、培养想象力、激发表达能力，甚至塑造她的自信心。</p>\n<h2>✅ 结语：与其让孩子独自摸索阅读，不如陪他一起爱上阅读！</h2>\n<p>在孩子还小的时候，最重要的从来不是“读了多少书”，而是——他是否爱上了读书这件事。</p>\n<p>把书变成亲子互动的工具，把阅读变成一场好玩的冒险游戏。你会发现，孩子不仅爱上了读书，也更爱和你在一起。</p>\n<blockquote>\n<p>阅读的种子，往往是在亲子互动中，悄悄发芽的🌱。</p>\n</blockquote>\n<p>📌你也在和孩子亲子阅读的路上吗？欢迎留言分享你们的趣事和小技巧，一起让更多孩子爱上阅读！❤️</p>\n<details class=\"hint-container details\"><summary>公众号：AI悦创【二维码】</summary>\n<figure><img src=\"/gzh.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n</details>\n<div class=\"hint-container info\">\n<p class=\"hint-container-title\">AI悦创·编程一对一</p>\n<p>AI悦创·推出辅导班啦，包括「Python 语言辅导班、C++ 辅导班、java 辅导班、算法/数据结构辅导班、少儿编程、pygame 游戏开发、Web、Linux」，招收学员面向国内外，国外占 80%。全部都是一对一教学：一对一辅导 + 一对一答疑 + 布置作业 + 项目实践等。当然，还有线下线上摄影课程、Photoshop、Premiere 一对一教学、QQ、微信在线，随时响应！微信：Jiabcdefh</p>\n<p>C++ 信息奥赛题解，长期更新！长期招收一对一中小学信息奥赛集训，莆田、厦门地区有机会线下上门，其他地区线上。微信：Jiabcdefh</p>\n<p>方法一：<a href=\"http://wpa.qq.com/msgrd?v=3&amp;uin=1432803776&amp;site=qq&amp;menu=yes\" target=\"_blank\" rel=\"noopener noreferrer\">QQ</a></p>\n<p>方法二：微信：Jiabcdefh</p>\n</div>\n<figure><img src=\"/zsxq.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n",
      "image": "https://bornforthis.cn/gzh.jpg",
      "date_published": "2025-07-17T10:53:06.000Z",
      "date_modified": "2025-09-12T03:48:36.000Z",
      "authors": [
        {
          "name": "AI悦创"
        }
      ],
      "tags": []
    },
    {
      "title": "08-游戏：游戏行业的 ROI 和付费率是怎么算的？",
      "url": "https://bornforthis.cn/column/%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90%E6%80%9D%E7%BB%B4%E4%B8%8E%E5%AE%9E%E6%88%9823%E8%AE%B2/08.html",
      "id": "https://bornforthis.cn/column/%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90%E6%80%9D%E7%BB%B4%E4%B8%8E%E5%AE%9E%E6%88%9823%E8%AE%B2/08.html",
      "summary": "你好，我是悦创。 今天我以欢乐斗地主游戏为例介绍一下游戏行业的数据分析。 本节课内容分为四部分： 背景； 指标口径； 用户流失分析； 用户付费分析。 1. 背景 在前面两课时，我介绍了互联网和金融的数据思维，其实游戏行业兼具互联网与金融数据思维。我之前体验了狼人杀和欢乐斗地主两款 App，因为个人抵抗力比较差，每天都玩到很晚，对我的工作和生活都有一定影...",
      "content_html": "<p>你好，我是悦创。</p>\n<p>今天我以欢乐斗地主游戏为例介绍一下游戏行业的数据分析。</p>\n<p>本节课内容分为四部分：</p>\n<ul>\n<li>\n<p>背景；</p>\n</li>\n<li>\n<p>指标口径；</p>\n</li>\n<li>\n<p>用户流失分析；</p>\n</li>\n<li>\n<p>用户付费分析。</p>\n</li>\n</ul>\n<h2>1. 背景</h2>\n<p>在前面两课时，我介绍了互联网和金融的数据思维，其实游戏行业兼具互联网与金融数据思维。我之前体验了狼人杀和欢乐斗地主两款 App，因为个人抵抗力比较差，每天都玩到很晚，对我的工作和生活都有一定影响，最后决定把它们删了，不玩了。所以游戏行业用户两极分化比较严重：要么快速流失，要么玩的时间就很长。</p>\n<p>因此本节课重点围绕两个目标：</p>\n<ul>\n<li>\n<p>尽量让用户晚点流失——流失分析</p>\n</li>\n<li>\n<p>让花时间的用户多变现——商业分析</p>\n</li>\n</ul>\n<p>我们先来看看欢乐斗地主 App 的界面，如下图所示。</p>\n<figure><figcaption></figcaption></figure>\n<p>在上图界面的右侧，有经典、排位、残局、比赛的坑位，点进去之后是对应玩法。最右下角的有一个“商城” button （小人推着小推车），点击进去之后如下图所示。</p>\n<figure><figcaption></figcaption></figure>\n<p>这是欢乐斗地主 App 最重要的界面，后面的讲解我会围绕这些图片来展开。</p>\n<h2>2. 指标口径</h2>\n<p>第二个模块是指标口径，指标口径包括常规指标和商业化指标。</p>\n<h3>2.1 常规指标</h3>\n<p>常规指标包含四类：</p>\n<ol>\n<li>\n<p><strong>DAU、WAU、MAU</strong></p>\n<p>DAU、WAU、MAU 分别指产品的日活、周活以及月活。对于任何产品，首先要看用户规模，用户规模是一个亿还是五千万，要有具体的数值。</p>\n</li>\n<li>\n<p><strong>留存率</strong></p>\n<p>留存率一般是看次留、7 留、30 留存率。留存率是一个比例，反映产品的联系程度。以次留率为例，次留率等于第一天打开欢乐斗地主并且第二天也打开欢乐斗地主的人数除以第一天打开欢乐斗地主的人数。</p>\n<p>比如，第一天打开欢乐斗地主 App 的有 1000 人，第二天这 1000 人里面又有 800人打开了App，那么它的次留率为：<code>800/1000*100=80%</code>。</p>\n</li>\n<li>\n<p><strong>渗透率</strong></p>\n<p>每个产品都有很多子功能，每个子功能的渗透率等于该模块的使用人数除以该产品的日活。</p>\n<p>比如，欢乐斗地主 App 的昨日 DAU 为 1000 人，昨日有 900 人点击“商城”。</p>\n<p>那么“商城”渗透率为： <code>900 / 1000*100=90%</code>。</p>\n</li>\n<li>\n<p><strong>转化率</strong></p>\n<p>转化率针对某个连贯路径。它等于使用下一个节点的用户数除以使用上一个节点的用户数。</p>\n<p>比如，欢乐斗地主打开APP（1000 人）— 进入房间（800 人）— 参加比赛（700 人）。</p>\n<ul>\n<li><code>进入房间的转化率=800/1000*100=80%</code></li>\n<li><code>参加比赛转化率=700/800*100=87.5%</code></li>\n</ul>\n</li>\n</ol>\n<h3>2.2 商业化指标</h3>\n<p>商业化指标有三个概念。</p>\n<ol>\n<li>\n<p><strong>ARPU：代表一个时间段内的用户平均收入</strong></p>\n<p>ARPU= 付费金额 / 活跃人数</p>\n<p>比如，欢乐斗地主付费总金额 200w，活跃人数 100w，用户平均收入 2元。</p>\n</li>\n<li>\n<p><strong>CPM、CPC</strong></p>\n<p>CPM 是千次曝光的成本。</p>\n<p><code>CPM=（广告投入总额 / 所投广告的展示数）*1000</code></p>\n<p>比如，某广告主在欢乐斗地主的闪屏界面投入一个广告 10w，共展示 1000w 次，那么 CPM=10。</p>\n<p>CPC 是每个点击用户的成本。</p>\n<p><code>CPC= 广告投入总额 / 所投广告带来的点击用户数</code></p>\n<p>比如，某广告主在欢乐斗地主里面投了一个闪屏广告 100w，共产生点击 50w，那么 CPC=2。</p>\n</li>\n<li>\n<p><strong>ROI：代表投资回报率</strong></p>\n<p>ROI= 收入 / 支出= ARPU*用户 数/ 所有支出</p>\n<p>比如，双 11 在欢乐斗地主内部投放一个广告100w，最终带来收入200w，那么 ROI=2。</p>\n</li>\n</ol>\n<h2>3. 用户流失分析</h2>\n<p>第三个模块是用户的流失分析，行业内把一个月内不使用产品的用户定义为流失用户。实际上，不同产品形态的用户行为差异非常大，像住宿类 App 是低频高价值用户，而欢乐斗地主 7 天不上线可能就已经流失，所以要合理定义流失用户。对于流失用户，发现的越早越好，在这里会出现不太好定义用户流失的情况，比如你先定义 30 天用户不来即为流失，结果到 30 天的时候，大量用户回流。</p>\n<p>如何合理定义流失用户，我们可以参考用户流失的周期，本质上等于回流率的确定，一旦用户回流率稳定，就可以定义这个时间段的天数为用户流失周期。</p>\n<p><strong>用户回流率 = 回流用户数 / 流失用户数 = 某个周期内的流失用户数在周期结束后又回来了 / 某个周期内的流失用户数</strong></p>\n<p>所以，根据这个公式按照枚举法，周期天数 = 1,2,…,30，然后分别计算回流率，一旦回流率趋于收敛，该周期就是流失周期。</p>\n<p>比如，我定义 1 天不来就为流失，然后按照公式会得出一个回流率数值，然后我再定义 2 天不来就为流失，又得出一个回流率数值。以此类推，到 60 天就会有 60 个回流率数值，这些回流率对应的 60 个点就可以画出一条曲线。这条曲线在什么时间段趋于平缓，那这个周期就是一个合理的流失周期。</p>\n<p>举个例子，假设欢乐斗地主 App 它的流失数据，如下图所示。</p>\n<figure><figcaption></figcaption></figure>\n<p>我们根据以上数据用周期和回流率来画一条曲线，如下图所示。</p>\n<figure><figcaption></figcaption></figure>\n<p>由上图曲线可知，在第 7 天（ 0.05 水位线）回流率趋于稳定，所以可以把 7 天定义为流失周期。假如用户 7 天不上线即定义为流失用户，这样就会有很大说服力。</p>\n<p>流失周期确定后，我们要进行用户的流失分析，对于游戏行业的用户流失分析，即有其他行业的类似套路，也有一些差异点。</p>\n<ul>\n<li><strong>类似套路：看用户在流失前最后一步干了什么，是什么导致用户体验差而流失。</strong></li>\n</ul>\n<p>以欢乐斗地主为例，用户最后一步行为类型，如下表所示。</p>\n<p>| 最后一步行为类型 | 最后一步具体行为到退出游戏时长 | 用户占比 |<br>\n|</p>\n",
      "date_published": "2025-07-16T09:14:21.000Z",
      "date_modified": "2025-07-16T02:39:54.000Z",
      "authors": [
        {
          "name": "AI悦创"
        }
      ],
      "tags": []
    },
    {
      "title": "05-多元思维模型：数据分析需要具备的四大能力？",
      "url": "https://bornforthis.cn/column/%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90%E6%80%9D%E7%BB%B4%E4%B8%8E%E5%AE%9E%E6%88%9823%E8%AE%B2/05.html",
      "id": "https://bornforthis.cn/column/%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90%E6%80%9D%E7%BB%B4%E4%B8%8E%E5%AE%9E%E6%88%9823%E8%AE%B2/05.html",
      "summary": "你好，我是悦创。 今天我讲一下多元思维模型。 本节课内容一共分为四部分： 背景； 中观能力； 微观能力； 宏观能力。 1. 背景 目前在整个数据分析行业中，大部分同学偏数据库和机器学习，又或是学计算机专业出身，所以会造成一种行业错觉——会点技术、会点 PPT 就可以做数据分析，感觉门槛比较低；有时候觉得自己做出的分析报告，别人能很快的发现问题，自己也认...",
      "content_html": "<p>你好，我是悦创。</p>\n<p>今天我讲一下多元思维模型。</p>\n<p>本节课内容一共分为四部分：</p>\n<ul>\n<li>\n<p>背景；</p>\n</li>\n<li>\n<p>中观能力；</p>\n</li>\n<li>\n<p>微观能力；</p>\n</li>\n<li>\n<p>宏观能力。</p>\n</li>\n</ul>\n<h2>1. 背景</h2>\n<p>目前在整个数据分析行业中，大部分同学偏数据库和机器学习，又或是学计算机专业出身，所以会造成一种行业错觉——会点技术、会点 PPT 就可以做数据分析，感觉门槛比较低；有时候觉得自己做出的分析报告，别人能很快的发现问题，自己也认可，但就是不知道如何避免；有时候针对某个问题，有些人总是能有很多想法，但自己却不知道怎么理解；有些人职业发展的很顺利，而自己却始终有瓶颈。</p>\n<p>其实这些困惑都非常正常，所以这一节课的目的就是告诉你，到底掌握好哪些能力才能够成为一名优秀的数据分析师，这也是后面所有课程的一个基础。这一节课会有一点点抽象，但是你要好好学。</p>\n<p>先给出数据分析的多元思维模型，就是从中观、微观、宏观三个角度去出发。</p>\n<ul>\n<li>\n<p><strong>中观能力</strong>：中观能力是真正的专业度，看你是否能够发现其他数据分析师在分析中的问题。这个专业度不单指你的技术，而是需要你长期总结和思考。</p>\n</li>\n<li>\n<p><strong>微观能力</strong>：微观能力指有效沟通力+快速发散收敛力，看你是否能够从业务的交流中发现问题，找到方向，很多同学都还没意识到这一点。</p>\n</li>\n<li>\n<p><strong>宏观能力</strong>：宏观能力是洞见性的全局观，能够从社会事件和整个行业发展中找到业务的决策方向，这是极难的能力，同时平台和天赋缺一不可。</p>\n</li>\n</ul>\n<p>怎么获得这些能力呢？我逐一来讲。</p>\n<h2>2. 中观能力</h2>\n<p>中观能力指专业度，包括技术理解、逻辑性、价值点三个点。中观能力是反映分析师基本功怎么样、套路熟不熟练、思考到不到位的一种标准。</p>\n<ol>\n<li>\n<p><strong>技术理解</strong>：指对分析时用到的技术理解是否到位，是停留在理论阶段还是在实践阶段。很多同学看了很多数据分析的书籍，理论说起来无所不知，但在实践过程中还是遇到很多坑。</p>\n</li>\n<li>\n<p><strong>逻辑性</strong>：指对整体思考的逻辑性是否欠缺。</p>\n</li>\n<li>\n<p>价值点：强调价值，你做出来的分析价值在哪。如果现在你是决策者，你敢不敢立马规划落地。</p>\n</li>\n</ol>\n<p>中观能力的提升相对比较容易，基本上就是从他人那里获得有效反馈，所以你做出的分析一定要获得高手的反馈，让他指出一些不足或建议，然后多实践。</p>\n<h3>2.1 技术理解</h3>\n<p>在数据处理中经常用到数据标准化方法，比如常见的 MAX-MIN （最大最小值）方法、Z-score （z 分数）方法、指数对数法。但这只是理论上的方法，你需要理解到数据标准化的本质目的是去除量纲、量级的差异性，才能在业务中有效地利用。</p>\n<p>举例：对于 to B 的金融公司来说，除了头部的大客户（前期资源），剩下的都是中小客户（后期拓展）。大客户和小客户需按照每天的交易额来区分，所以需要我们对交易额及用户进行建模。这时就要用到数据标准化，以 MAX-MIN 方法为例，如果直接用这种方法，会造成除了头部几个数据有数值外，其他基本都是 0。到与业务方沟通时，业务方 Leader 会觉得你这个方法很有问题。数据非常稀疏，无论是可用性还是理解性都很困难。</p>\n<p>所以，有两个解法：</p>\n<ol>\n<li>对客户进行先分群，再用 MAX-MIN 进行标准化；</li>\n<li>以 90% 中位数替代 MAX，消除头部影响，让数据变得不那么稀疏。</li>\n</ol>\n<p>实际上所有的技术都是为了让业务更加方便，更加高效，而不是让人很困惑，这就是技术理解。</p>\n<h3>2.2 逻辑性</h3>\n<p>关于逻辑性，我举一个资讯类 App 的真实案例：数据分析师在研究最近一个月的数据，发现所有与留存相关的因素中，留存和自媒体文章下发的占比存在高度相关性。于是就建议业务方多下发自媒体文章，业务方觉得这个点很好，还真的做了。结果是刚开始几天留存是微涨，后续却大跌。</p>\n<p>你觉得这个案例的问题出在哪 ？</p>\n<p>其实相关性是一种基于向量的伴随关系，不代表直接的因果关系（但确实是因果关系的一种可能性），也就是说留存和自媒体文章下发的占比是一种伴随关系，而不是因果关系。留存的影响因素非常多，不仅仅是因为某一两个指标就能很好地提升留存。</p>\n<p>上述例子后来复盘发现，最近刚好是因为有一些重大热点导致留存提升，而这些重大热点文章是以自媒体文章为主，最终造成了自媒体文章下发占比能提升留存的假象。</p>\n<p>所以分析师的逻辑性非常重要，每一环节的推导必须要讲究严谨性，不能有侥幸心理。</p>\n<h3>2.3 价值点</h3>\n<p>价值点，强调你做的所有分析一定要有价值点。</p>\n<p>我曾经见到一个同学，竟然在业务分析报告里面用到了大量的复杂公式，最后还画了一张非常复杂的技术图，在会议上大家都不好意思反驳他。后来问了业务方，得到的反馈是，整个分析报告用了两个月时间，看似解决了很多技术痛点，但是对业务提升没意义，因为听完不知道怎么去落地。</p>\n<p>在数据分析过程中，有些是避免不了的描述性统计，你要快速解决，切记不要耽误时间。而对于指导性、预测性的分析，最花时间也是价值最大。你一定要利用好有效时间找到价值点，即使这个价值点只有 1 个。请注意：有没有价值不是分析师说了算，而是业务方说了算，有些点很好但暂时无法落地，就先不要管它。</p>\n<p>中观能力能体现分析师的专业度，基本上就是多沉淀、多思考、多反馈、多总结。</p>\n<h2>3. 微观能力</h2>\n<p>我们先看下微观能力的背景。</p>\n<p>在中观能力相同的情况下，有些分析师总是表现的比其他分析师更加优秀，比如：</p>\n<ul>\n<li>\n<p>针对某个问题，总是能产生很多想法，找到切入点——很有想象力；</p>\n</li>\n<li>\n<p>业务方如果遇到问题就会优先找他，而他总是能在最短的时间内给业务方一个较好的答复——有解决问题的能力；</p>\n</li>\n<li>\n<p>对于数据有更好的敏感度，能够第一个发现数据问题并给出解法——敏感度高；</p>\n</li>\n<li>\n<p>会议上，总是能提出自己的独到观点，让别人觉得他很聪明——快速发现提问；</p>\n</li>\n<li>\n<p>总是能很好的知道业务在干啥，而他的视角又一直是高于业务，所有人都认可——有高维视角。</p>\n</li>\n</ul>\n<p>这些都是分析师微观能力的表现，始于经验，终于沉淀，注重点点滴滴，思维高度活跃，总是能找到一些线索。微观能力是反映分析师平时的微观体感怎么样，作为一名分析师，你必须能发现很多业务方发现不到的点，然后从数据上给出策略建议。</p>\n<p>具体怎么样做到这一点呢？</p>\n<p>首先要知道业务是怎么想的，怎么做的，然后从中发现问题或者切入点，具体来说就是有效沟通能力和快速发散、收敛能力。</p>\n<ol>\n<li>\n<p>有效沟通能力：指在与业务方核心人员沟通时，要从谈话中快速捕捉到有用信息（说者无心听者有意）。</p>\n</li>\n<li>\n<p>快速发散、收敛能力：收敛能力基于沟通中的有效信息，快速提炼总结找到最好的分析切入点。</p>\n</li>\n</ol>\n<p>所谓的好奇心或者说想象力，都不是凭空产生的。回归到数据分析本质，只有和相关业务方多沟通，从他们那里获取有效信息，再自身提炼加工（多学习、思考），才是可落地的“天马行空”。这就是优秀分析师厉害的地方（快速捕捉、提炼、找到问题、解决问题）。</p>\n<h3>3.1 有效沟通能力</h3>\n<p>有效沟通能力有两个技巧。</p>\n<ul>\n<li>\n<p><strong>技巧 1：黄金思维圈法则</strong></p>\n<p>在了解业务的情况下，反问业务方为何要做这件事，基本上，业务方都会有一个很具体的回答，往往都能在这里找到切入点。</p>\n<p>举例：顺丰科技最近在做一个类似锦鲤的活动，业务方要分析师给出活动带来的新增用户数。</p>\n<p>这个时候分析师要先体验下这个活动，并且让业务方介绍下活动，同时要问业务方为何要这个数。</p>\n<p>熟悉这些之后，发现这个活动本身没有特别的拉新点，活动本质是促进老用户活跃。所以建议业务对促活进行深入分析，一旦这样就已经高于业务视角了。</p>\n<p>多问为何要做这件事，往往就能找到问题的本质，解法自然就多。</p>\n</li>\n<li>\n<p><strong>技巧 2：做一些准备工作再沟通</strong></p>\n<p>在与业务沟通中，如果没有提前准备一些业务知识和数据，整个过程就是业务在主导，你还怎么发现问题呢？</p>\n<p>举例：爱奇艺 App 最近新上线了某功能，业务方拉各方参加会议，讨论下这个功能下一步的玩法。</p>\n<p>实际工作中，分析师都不一定知道会议主题，或者知道主题没有思考就去参加会议。可想而知整个讨论，只能了解一些基础信息外，无法获得有效信息。会议是一个很好的公共场合，也是分析师证明自己独特视角的地方，所以沟通前一定做好准备，这样不仅没有浪费会议时间，还能让别人觉得你很厉害。</p>\n</li>\n</ul>\n<h3>3.2 快速发散、收敛能力</h3>\n<ul>\n<li>\n<p><strong>发散</strong>：指对于某一个全新业务问题，跟业务沟通之后，分析师想法很多。</p>\n</li>\n<li>\n<p><strong>收敛</strong>：在众多想法中，快速找到当前做哪个比较实际、合理，并且知道如何做的深入。</p>\n</li>\n</ul>\n<p><strong>举例</strong>：在制定公司级 KPI 的时候，业务分析师需要预估下一年，年中的 MAU 和 DAU 。</p>\n<p>该问题有多种解法：时间序列、行业环境、渠道分析都可以作为切入点。最终觉得渠道分析切入点会更加合理。</p>\n<p><code>MAU = MAU 新用户+ MAU 老用户</code></p>\n<p><code>MAU 新用户=明年渠道侧每个月能够带来的新增量多少（这个与明年预算高度相关）</code></p>\n<p><code>MAU 老用户=MAU 上月新次月老（基于渠道）+MAU 上月老次月老（历史数据）+MAU 回流（历史数据）</code></p>\n<ul>\n<li>\n<p><strong>新次月老</strong>：上月新增用户次月老用户</p>\n</li>\n<li>\n<p><strong>老次月老</strong>：上月老用户次月老用户</p>\n</li>\n</ul>\n<p>其实渠道这个切入点是分析师从市场部无意捕获到的，后来提炼了下，觉得非常合理。对于全新问题，没有固定答案，分析师需要做的就是快速给出一个有依据的解法即可。</p>\n<p>这就是快速发散收敛能力的培养，总结一下：</p>\n<ol>\n<li>\n<p>要尽可能多地和业务方核心人员，特别是业务 Leader 沟通，有些业务 Leader 非常优秀，看他们是如何思考理解业务的；</p>\n</li>\n<li>\n<p>多看一些心理学、社交学、经济学、记忆力类、科普类的书籍，这些书籍对你微观能力的培养非常有好处；</p>\n</li>\n<li>\n<p>刻意练习，慢慢地养成习惯，一定要把心静下来去做事情，相信自己一定能够把微观能力培养好。</p>\n</li>\n</ol>\n<h2>4. 宏观能力</h2>\n<p>宏观能力是指能够把当前业务与实际社会热点、行业风口联系起来，提前预判，获得更好的决策。宏观能力非常难，如果做好了，基本就是顶级 CEO 了，大部分同学都还没机会接触到这一层面，因为它需要你有一定的决策权。</p>\n<p>比如互联网金融监管政策的加强，对平台型理财公司是一种灾难级的影响，优秀的分析师总是会去定期观察政府行业的动态，提前预判一些敏感信息。而这种敏感度只有多看新闻联播和财经类的节目才能慢慢培养好。</p>\n<p>我们看一下网信办跟资讯类 App 这样的社会热点事件，跟业务高度相关的时间序列，如下图所示：</p>\n<figure><figcaption>网信办与资讯类 App 的时间序列</figcaption></figure>\n<p>2017 年 10 月 26 日，网信办（负责互联网信息服务管理）召开宣贯十九大大会，宣贯十九大精神。一周之后，网信办深入互联网企业，向京东、百度进行企业调研。一个多月之后，网信办整改今日头条，部分频道下线，今日头条用户流失严重。如果当时头条有一些敏感性，在事件发生的一个月之前就应该认识到问题，做一些补救措施应该还没这么严重。</p>\n<p>作为今日头条的竞品——UC 浏览器，同样没有认识到问题的严重性，或者说心存侥幸。2018 年 2 月 1 日，广东网信办整改 UC ，那段时期 UC 的用户流失非常严重。这就可以看出宏观热点事件对业务影响巨大，所以优秀的分析师一定要保持这种高度的敏感性。</p>\n<h2>5. 总结</h2>\n<p>今天的课程就是讲解中观、微观、宏观能力。</p>\n<ul>\n<li>\n<p>中观能力在公司都会学习一些，只要获得一些反馈再优化即可。</p>\n</li>\n<li>\n<p>微观能力特别注重平时的微观体感，所以分析时一定要有静下来的决心，注重套路的真实落地过程，从不同的业务方捕捉、提炼、沉淀，这是一个长期的训练。</p>\n</li>\n<li>\n<p>对于宏观，你需要关注行业内的动态，像新闻联播、财经类节目都是重要的数据源。</p>\n</li>\n</ul>\n<p>另外多说一句，公司的 CEO 其实是顶级数据分析师这个角色，所以分析师这个天花板非常高，发展空间也非常大。</p>\n<details class=\"hint-container details\"><summary>公众号：AI悦创【二维码】</summary>\n<figure><img src=\"/gzh.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n</details>\n<div class=\"hint-container info\">\n<p class=\"hint-container-title\">AI悦创·编程一对一</p>\n<p>AI悦创·推出辅导班啦，包括「Python 语言辅导班、C++ 辅导班、java 辅导班、算法/数据结构辅导班、少儿编程、pygame 游戏开发、Web、Linux」，招收学员面向国内外，国外占 80%。全部都是一对一教学：一对一辅导 + 一对一答疑 + 布置作业 + 项目实践等。当然，还有线下线上摄影课程、Photoshop、Premiere 一对一教学、QQ、微信在线，随时响应！微信：Jiabcdefh</p>\n<p>C++ 信息奥赛题解，长期更新！长期招收一对一中小学信息奥赛集训，莆田、厦门地区有机会线下上门，其他地区线上。微信：Jiabcdefh</p>\n<p>方法一：<a href=\"http://wpa.qq.com/msgrd?v=3&amp;uin=1432803776&amp;site=qq&amp;menu=yes\" target=\"_blank\" rel=\"noopener noreferrer\">QQ</a></p>\n<p>方法二：微信：Jiabcdefh</p>\n</div>\n<figure><img src=\"/zsxq.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n",
      "date_published": "2025-07-11T14:39:13.000Z",
      "date_modified": "2025-07-11T06:52:38.000Z",
      "authors": [
        {
          "name": "AI悦创"
        }
      ],
      "tags": []
    },
    {
      "title": "04-如何挑选适合项目场景的数据分析工具？",
      "url": "https://bornforthis.cn/column/%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90%E6%80%9D%E7%BB%B4%E4%B8%8E%E5%AE%9E%E6%88%9823%E8%AE%B2/04.html",
      "id": "https://bornforthis.cn/column/%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90%E6%80%9D%E7%BB%B4%E4%B8%8E%E5%AE%9E%E6%88%9823%E8%AE%B2/04.html",
      "summary": "你好，我是悦创。 今天我讲一下各种数据分析工具的使用场景对比。 本节课内容分为四大部分： 数据分析整体流程； Excel 常用操作； SQL 常见问题； R 语言以及 Python 脚本案例。 1. 数据分析整体流程 数据分析有一套标准化流程，很多人在做数据分析的时候，不知道怎么去开展或者怀疑自己做出的分析报告是否合理、是否全面，这是因为你对这一套标准...",
      "content_html": "<p>你好，我是悦创。</p>\n<p>今天我讲一下各种数据分析工具的使用场景对比。</p>\n<p>本节课内容分为四大部分：</p>\n<ul>\n<li>\n<p>数据分析整体流程；</p>\n</li>\n<li>\n<p>Excel 常用操作；</p>\n</li>\n<li>\n<p>SQL 常见问题；</p>\n</li>\n<li>\n<p>R 语言以及 Python 脚本案例。</p>\n</li>\n</ul>\n<h2>1. 数据分析整体流程</h2>\n<p>数据分析有一套标准化流程，很多人在做数据分析的时候，不知道怎么去开展或者怀疑自己做出的分析报告是否合理、是否全面，这是因为你对这一套标准化流程没有真正的理解。</p>\n<p>来看一下标准化流程的九个步骤：</p>\n<ol>\n<li>\n<p><strong>明确问题</strong>，先把问题定义清楚，因为很多人还没理清问题就直接去看数据了；</p>\n</li>\n<li>\n<p><strong>搭建框架</strong>，定义问题之后再把问题考虑全面、找到一条分析主线；</p>\n</li>\n<li>\n<p><strong>数据提取</strong>，用 MySQL、Hive 等工具提取相关数据；</p>\n</li>\n<li>\n<p><strong>数据处理</strong>，用 Excel、R、Python 处理数据；</p>\n</li>\n<li>\n<p><strong>数据分析</strong>，以数据分析方法论为主来分析数据；</p>\n</li>\n<li>\n<p><strong>数据展现</strong>，用 Tableau、Excel、R、Python 工具把你的数据展现出来；</p>\n</li>\n<li>\n<p><strong>撰写报告</strong>，考验你的文笔功底以及整体逻辑性；</p>\n</li>\n<li>\n<p><strong>报告演讲</strong>，考验你沟通能力，表达能力，被提问能力。所有的报告撰写完成之后不要直接去讲，还是要和业务方进行大量的沟通，如果不提前做好沟通，你在会议或公众场合上讲时很容易被别人挑战；</p>\n</li>\n<li>\n<p><strong>报告闭环</strong>，这是最难也是最大价值的地方。</p>\n</li>\n</ol>\n<p>这里面的数据提取、数据处理、数据展现是数据分析师前期的基本功，以工具为主，都是比较容易学到的，也比较容易完成。而明确问题、搭建框架、撰写报告、报告演讲、报告闭环更多是考验分析师的综合能力以及智商、情商，所以这块往往需要很多时间去沉淀。基于数据分析这一套标准化流程，其中涉及一些你必须要学的工具，下面我简单讲一下这些工具。</p>\n<figure><figcaption>数据分析必学工具</figcaption></figure>\n<ul>\n<li>\n<p><strong>MySQL、Hive</strong>：基本上所有的数据获取方式都是通过 MySQL、Hive 这两种语言来实现，同时你要学习一些 Linux 命令，因为在排查数据异常时会用到。你需要对这两门工具超级熟练，因为数据提取环节是不能出错的，这一步有问题，后面就都有问题。</p>\n</li>\n<li>\n<p><strong>Excel</strong>：Excel 是最高频的数据处理工具。工作中你经常遇到的一种情况，你的 leader 直接让你现场画个图，这时你最有可能用 Excel 而不是 R、Python。</p>\n</li>\n<li>\n<p><strong>R</strong>：R 是一门统计型语言，专门为数据分析而生，简单易学，但缺点是计算能力确实比较差，你导入两个 GB 数据就有可能导致死机。</p>\n</li>\n<li>\n<p><strong>Python</strong>：Python 是一门真正的脚本语言，可扩展性极强，算法研发同学必备。而数据分析以 Pands 包为主，其他常用包含爬虫、文本挖掘。</p>\n</li>\n</ul>\n<h2>2. Excel 常用操作</h2>\n<p>先看 Excel 常用操作，一般通过 SQL 在数据库中提取数据，保存到本地 Excel，所以 Excel 是最基础也是最重要的一个数据分析工具，能用 Excel 坚决不用其他工具。</p>\n<h3>2.1 Excel 对比分析（筛选和色阶功能）</h3>\n<p>对比分析是数据分析中常见的一种分析方法。所有的数据只有对比才有意义，比如：每年的双 11 都会与之前的双 11 进行消费额对比。在工作中最常见的对比对象就是大盘，比如：新上线一个功能，怎么样评估这个功能效果，除了看功能使用人数，更要做这个功能和大盘的留存对比，如果高于大盘留存，代表这个功能有非常好的正向效应。</p>\n<p>举例：我们需要看自身 App 与竞品的重合用户与自身 App 的所有用户在客户端内的消费差异，从而针对这些重合用户，做针对性运营，这时就要用到对比分析。</p>\n<p>以微视这款 App 为例，你会看到第一列微视与抖音的重合用户消费分类和第三列微视大盘消费分类的消费 CTR 数据（如下表所示）。</p>\n<p>| 微视与抖音的重合用户消费分类 | 消费CTR | 微视大盘消费分类 | 消费CTR |<br>\n|</p>\n",
      "date_published": "2025-07-10T23:14:59.000Z",
      "date_modified": "2025-07-10T15:57:51.000Z",
      "authors": [
        {
          "name": "AI悦创"
        }
      ],
      "tags": []
    },
    {
      "title": "02-如何搞定 BAT 大厂的数据分析项目？",
      "url": "https://bornforthis.cn/column/%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90%E6%80%9D%E7%BB%B4%E4%B8%8E%E5%AE%9E%E6%88%9823%E8%AE%B2/02.html",
      "id": "https://bornforthis.cn/column/%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90%E6%80%9D%E7%BB%B4%E4%B8%8E%E5%AE%9E%E6%88%9823%E8%AE%B2/02.html",
      "summary": "你好，我是悦创。 今天我讲一下 BAT 的数据分析工作。 1. BAT 招聘解析 通过招聘解析的讲解，一是希望你能了解互联网大厂数据分析师的日常工作内容是什么，揭开大厂招聘的神秘面纱；二是通过他们的岗位要求，了解到自身的差距，并对不足有针对性的面试准备，或提升自己在行业内的技术能力。 1.1 阿里 阿里数据分析师岗位职责阿里数据分析师岗位职责 先看下阿...",
      "content_html": "<p>你好，我是悦创。</p>\n<p>今天我讲一下 BAT 的数据分析工作。</p>\n<h2>1. BAT 招聘解析</h2>\n<p>通过招聘解析的讲解，一是希望你能了解互联网大厂数据分析师的日常工作内容是什么，揭开大厂招聘的神秘面纱；二是通过他们的岗位要求，了解到自身的差距，并对不足有针对性的面试准备，或提升自己在行业内的技术能力。</p>\n<h3>1.1 阿里</h3>\n<figure><figcaption>阿里数据分析师岗位职责</figcaption></figure>\n<p>先看下阿里的岗位职责描述，关键词有“代理”“方向”“痛点”“转化”“风险”“创新”“落地”“合作”，岗位要求的关键词有“敏感度”“方法论”“管理整合”。由此可以看出，阿里的分析师岗位对技术要求不是很高，但对人的综合能力要求非常高，需要具备一定的数据敏感度和方法论。之所以没有特别要求技术能力是因为市场上工作三五年的分析师基本上都具备了一定的技术能力，但仍有很多人缺少宏观、中观与微观意识，这也是大部分人的职业瓶颈。</p>\n<h3>1.2 腾讯</h3>\n<figure><figcaption>腾讯数据分析师岗位职责</figcaption></figure>\n<p>再来看下腾讯的岗位职责描述，关键词有“埋点”“异常检测”“决策”“A/B 测试”等，岗位要求包括“海量数据处理”“用户增长”等，可以看出腾讯的岗位职责中规中矩，基本涵盖了 80% 的互联网公司数据分析师的日常工作内容。值得关注的是腾讯特别提到了增长黑客的经验，目前独角兽企业都会要求有这样的经验。</p>\n<h3>1.3 百度</h3>\n<figure><figcaption>百度数据分析师岗位职责</figcaption></figure>\n<p>再来看下百度的岗位职责描述，关键词有“分析体系”“专项策略”“用户增长”“逻辑思维”“敏感度”等，可以看出百度对个人的“发散思维”和“策略研究”要求非常高，同时在用户运营领域也要有自己的体系。</p>\n<p>我们可以看出对于 BAT，他们会特别关注用户增长，毕竟独角兽企业只有持续增长才能获得发展，而在实际工作中，你也会感同身受，所有项目都是为了用户增长而构建。</p>\n<h2>2. 日常工作</h2>\n<p>第二部分就是日常工作，日常工作主要包括数据异常的排查和融入专项，做专项分析并负责 KPI、埋点，指标体系等。</p>\n<h3>2.1 数据异常排查</h3>\n<p>我们先看下数据异常排查的背景，一般情况下，BAT 的数据产品 DAU 都比较大，动辄几百万上千万，甚至过亿，因此业务方和管理层每天都会盯着核心数据，而在这些核心数据中肯定会有一些数据是波动比较大的。这时，分析师需要对这些波动进行排查并解释原因，如果没有一套方法论面对问题就会很头痛，你可以回想下自己是否面对过这种情况，每天早上面对波动数据无从下手，找不到原因，解决不了，进而浪费很多时间做了很多无用功，感觉永无出头之日。</p>\n<p>实际上，数据有较大波动，无非就两个原因：一是目前数据本身有问题；二是业务本身有问题。</p>\n<p>如果能够透过问题看本质，你就可以在数据波动方面成为专家。当然数据异常排查是需要一些前期准备的：</p>\n<ul>\n<li>\n<p>业务理解；</p>\n</li>\n<li>\n<p>指标口径；</p>\n</li>\n<li>\n<p>当前数据产出过程。</p>\n</li>\n</ul>\n<p>第一个业务理解，比如某个 App 的 DAU 低于1000w，那么请问这个 DAU 代表的是什么行动的DAU，是在进程中还是需要打开 App，还是必须有主动行为，这理解起来是不一样的。第二个指标口径，同样是 DAU 一千万，是 Android 还是所有系统。第三个产出过程，对于 DAU 一千万目前是由哪份日志做了哪些数据清洗计算出来的，只有了解清楚这些才能够开始异常排查。</p>\n<p>举个例子，市场部领导看了某一张日活数据和你提供的数据相差较大，就来询问是怎么回事。实际上这时你首先需要弄清楚他看到的数据表是怎样产出的，然后指标口径是什么，指标的业务含义是什么，只有熟悉这些情况后才能分析出产生差异的原因。</p>\n<p>实际工作中，有些分析师在进入一家公司时产品已经比较成熟，但指标口径没有文档化，所以可能对业务理解不深，这个时候面对领导的提问就会手足无措，一旦不能解决问题就会失去信任，所以前期准备工作一定要做好。</p>\n<p>有了前期准备工作，接下来就是异常排查步骤了，异常排查主要分三步：</p>\n<ol>\n<li>判断是否异常；</li>\n<li>最大概率法则归类；</li>\n<li>闭环。</li>\n</ol>\n<p>第一步判断是否异常，有四个关键点：</p>\n<ul>\n<li>\n<p><strong>亲自去看数据准确性，不要人云亦云</strong>，比如业务方说 DAU 下降了就立马去调查，这是不对的，而是应该亲自查看数据是否真实，有时候业务方不一定多专业，也会出现错误。</p>\n</li>\n<li>\n<p><strong>时间轴拉长，看是近期异常（3 个月）还是历史异常</strong>，一般分析师看数据时习惯看近一两周或一个月的数据，然后突然出现波峰或波谷就认为数据异常了，但实际上往往不是。我们一定要拉长时间轴，如果仍出现波峰或波谷可能就真的出现异常了。</p>\n</li>\n<li>\n<p><strong>看和该指标关联的其他指标或其他核心指标是否也异常</strong>，比如 DAU 异常时，需要查看自流、渗透率是否异常，如果也异常就需要一起解决，而不是按下葫芦浮起瓢，反复做无用功。</p>\n</li>\n<li>\n<p><strong>找到一个关键人物（产品/数据），提前沟通</strong>，也就是当我们确认是数据异常后，找经验丰富的人提前沟通，看他们对此是否有什么见解，往往经验能够快速的定位问题。</p>\n</li>\n</ul>\n<p>第二步就是最大概率法则原因归类，很多分析师遇到异常时无从下手，抓不到问题主线，无法对问题进行有效分类，而我把异常问题分为了六大类，基本上所有的异常问题都归属于这六大类。</p>\n<ul>\n<li>\n<p>假期效应：开学季、暑假、四大节、当地节日；</p>\n</li>\n<li>\n<p>热点事件：常规热点（世界杯）、突发热点（爆款 IP）；</p>\n</li>\n<li>\n<p>活动影响：双 11、618，公司层面活动；</p>\n</li>\n<li>\n<p>政策影响：互联网金融监管，快递实名；</p>\n</li>\n<li>\n<p>底层系统故障：数据传输、存储、清洗有无问题；</p>\n</li>\n<li>\n<p>统计口径：业务逻辑更改、指标计算方式更改。</p>\n</li>\n</ul>\n<p>所以当我们遇到问题时，就可以按照降序在这六大类中逐一排查找到问题原因。</p>\n<p>第三步就是闭环，当我们排查出问题原因后，一定要形成闭环，关于闭环有三个点：</p>\n<ul>\n<li>\n<p>持续跟踪后期数据是否再次异常，比如当我们排查出原因后，产品做相应的改进，而问题仍在就说明前期排查问题出错。</p>\n</li>\n<li>\n<p>记录、沉淀、文档化，因为后续我们可能还会遇到相同问题，所以记录文档利人利己。</p>\n</li>\n<li>\n<p>邮件化，只有确认没有问题再发邮件给相关方，描述影响范围和主要结论即可。</p>\n</li>\n</ul>\n<p>举个例子，某 App 海外版的主要用户在东南亚地区，某天 DAU 突然涨到 5000 万，与历史数据相比明显异常，问了很多人之后，发现数据采集、传输、活动、业务口径、常规热点等都没有变化。</p>\n<p>这时你先不要困惑，我们按照问题归类逐一排查，发现爆款 IP 没有排查到，我们就按照这个点继续排查数据，果然发现因为某国宝级的明星突然去世带来了 App 大量访问。因为在海外，信息传输比较慢，而突发事件国内用户无法快速知道，所以分析师发现流量提升后应该快速反馈给业务人员，业务确认没问题后立刻调动运营资源对该明星进行全方位解析，持续蹭热点把事件发酵到最大化，养成用户口碑。</p>\n<p>及时地响应事件后，整个 App 的 DAU 上涨了 10 个点，而一般的产品运营优化很难达到这个效果。针对这样的突发事件并不是每个分析师都能够遇到，但遇到异常数据一定要多尝试，虽然很多分析师排斥数据异常，但优秀的分析师还是能够从异常中发现业务增长点。</p>\n<p>所以遇到问题时，要有耐心，最后总会有所发现。我已经归纳了问题的归类，你在实际工作中可以直接参考，我们接下来看如何融入专项，也就是专题分析。</p>\n<h3>2.2 专题分析</h3>\n<p>关于专题分析，我们在上个课时也有介绍过，只不过对于 BAT 而言，专题分析有三个特征：</p>\n<ul>\n<li>\n<p>有目标：紧贴项目 KPI；</p>\n</li>\n<li>\n<p>有节奏：2~3 周时间输出一份完整报告；</p>\n</li>\n<li>\n<p>有闭环：所有的报告都说人话，做人事。</p>\n</li>\n</ul>\n<p>我们以今日头条 App 新用户留存专项为例来看下这三个特征。</p>\n<p><strong>项目背景</strong>：2015 年今日头条 App 新用户次留、7 留（7 日留存）与竞品相比，留存均低于 5% 绝对值，并且新用户流失速度要高于竞品，因此要在数据分析基础上，产品运营优化，提升用户留存 5% 绝对值。</p>\n<p>这是项目的一个背景，有了项目背景后分析师应该怎么做，主要分为三个阶段：</p>\n<p><strong>第一阶段：新用户留存整体分析</strong></p>\n<p>目的：摸清数据现状，同时找到若干切入点。</p>\n<p>关键点：不要太注重细节，该过程讲究报告产出的时效性，让其他人员感受到分析师的存在。</p>\n<p>在一个项目里会有产品、运营、研发，这些岗位你都很好理解，都是必要岗位，但别人往往觉得分析师不是必要的岗位。因为 BAT 的产品和运营肯定都会一些基础数据的处理，都会写 SQL。为了让其他人员感受到分析师的存在，我们一定要在项目前期，大家都比较困惑，找不到点的时候，我们用两周左右的时间输出一份专题报告，把一些细节的数据体现出来。</p>\n<p>比如我这里写了渠道侧、产品侧、用户侧（如图所示）：</p>\n<figure><figcaption>新用户留存分析</figcaption></figure>\n<p>渠道侧里的 UV 多少？ 一级渠道的次留、7 留有多少，二级渠道的次留、7 留有多少。</p>\n<p>产品侧里的主要功能，它的渗透率是什么情况，有没有出什么问题，关键漏斗数据怎么样，漏斗数据上面有没有什么发现。</p>\n<p>用户侧指我们目标用户群体是哪些，用户行为分布又是什么情况，比如我们知道人均浏览文章篇数是三、四篇，那么具体的分布是什么样子？有多少用户是阅读一篇的，或者说有多少用户压根一篇都不看。</p>\n<p>所以第一阶段就是预估下大致数据。</p>\n<p><strong>第二阶段：寻找优化切入点，一般是 1～2 个</strong></p>\n<p>比如在前面那个架构图里面发现：</p>\n<ol>\n<li>关键路径数据发现曝光 PV 到点击 PV 的 CTR 很低。</li>\n</ol>\n<p>应细致分析：对于新用户，应该曝光什么，在什么时候、什么位置曝光。</p>\n<ol start=\"2\">\n<li>某个量大的二级渠道次留明显要低于其他渠道。</li>\n</ol>\n<p>应进一步分析： 对于该渠道，用户的留存过低是因为本身渠道质量存在问题？用户已经安装竞品？当前产品设计与渠道用户不太匹配？同时高留存的渠道本身特征是什么？</p>\n<p>切入以上两点，就已经能给产品运营不少建议了，再配合 A/B 测试，就能看到数据分析效果。</p>\n<p>A/B 测试过于复杂，后面会单独展开。我们一定要相信，在一个项目或产品才开始做的时候，它一定是存在诸多问题，基于我们数据的深入分析和切入点的生活轨迹往往就能够提供很多优化建议，即使现在很多产品已经比较成熟，但始终还有优化空间，所以数据分析的发挥空间还是非常大。</p>\n<p><strong>第三阶段 ： 不断地重复前面两个阶段，继续寻找其他切入点</strong></p>\n<p>除了寻找本身产品的切入点，需要同时进行竞品分析、营销活动分析、用户流失分析等，整个过程就是在不断地“试错”。每一次分析报告都要有能落地的点，并且真的落地了，这就是闭环，这也是优秀分析师最重要的评判标准。</p>\n<h2>3. BAT 面试技巧以及必问问题</h2>\n<h3>3.1 面试技巧</h3>\n<p>我们再说一下面试技巧，这几家公司的面试基本上都是五到六面，前三面最为关键。第一面基本上都是电话面，第二面是 Boss 一面，第三面是 Boss 二面，所有的面试都是基于简历，所以你的简历一定要多下点功夫。</p>\n<p>第一面的关键点就是逻辑性。因为电话面看不到人，所以往往就看求职者基本功怎么样。你说话要条理清晰，然后对简历上的数据要非常熟悉，例如：活跃、留存、流失、渠道等。如果问你目前大概有哪些渠道，每个渠道的留存大概是多少，这些你都答不上来，那肯定是过不了关。</p>\n<p>第二面的关键点就是实操性。因为现场面是人与人现场的互动，首先要尊敬对方，面带微笑。其次要多使用你应聘岗位的产品 App ，同时带上一份你写的优秀专题分析报告，这可以证明你爱思考、有能力。</p>\n<p>第三面是要有亮点，因为 Boss 二面一般是总监面。总监的高度比较高，所以我们要从宏观的角度去说，比如说目前整体的行业趋势是什么样子，然后行业里有哪些痛点，这些产品有哪些方法可以改进，之前做的项目的上、下游是怎么考虑的，总之就是多有一些想法。</p>\n<h3>3.2 BAT 面试必问的三个问题</h3>\n<p>Q1：流量波动，数据突然涨了怎么分析？</p>\n<p>Q2：分析下你手机里面最常用的三个 App 是哪三个（这个问题套路很深）？</p>\n<p>Q3：商业模式，你之前产品的 CPC/CPM 以及商业模式是什么样的，你在这一块是怎么优化的？</p>\n<p>这三个问题的答案你可以先想一下，在下方留言讨论。下一节我将讲解中小型私企的数据分析工作，也会分享我对以上三个问题的理解。</p>\n<details class=\"hint-container details\"><summary>公众号：AI悦创【二维码】</summary>\n<figure><img src=\"/gzh.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n</details>\n<div class=\"hint-container info\">\n<p class=\"hint-container-title\">AI悦创·编程一对一</p>\n<p>AI悦创·推出辅导班啦，包括「Python 语言辅导班、C++ 辅导班、java 辅导班、算法/数据结构辅导班、少儿编程、pygame 游戏开发、Web、Linux」，招收学员面向国内外，国外占 80%。全部都是一对一教学：一对一辅导 + 一对一答疑 + 布置作业 + 项目实践等。当然，还有线下线上摄影课程、Photoshop、Premiere 一对一教学、QQ、微信在线，随时响应！微信：Jiabcdefh</p>\n<p>C++ 信息奥赛题解，长期更新！长期招收一对一中小学信息奥赛集训，莆田、厦门地区有机会线下上门，其他地区线上。微信：Jiabcdefh</p>\n<p>方法一：<a href=\"http://wpa.qq.com/msgrd?v=3&amp;uin=1432803776&amp;site=qq&amp;menu=yes\" target=\"_blank\" rel=\"noopener noreferrer\">QQ</a></p>\n<p>方法二：微信：Jiabcdefh</p>\n</div>\n<figure><img src=\"/zsxq.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n",
      "date_published": "2025-07-09T20:36:44.000Z",
      "date_modified": "2025-07-09T12:49:03.000Z",
      "authors": [
        {
          "name": "AI悦创"
        }
      ],
      "tags": []
    },
    {
      "title": "00-开篇词：数据分析能力，是每个职场人必备的核心竞争力",
      "url": "https://bornforthis.cn/column/%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90%E6%80%9D%E7%BB%B4%E4%B8%8E%E5%AE%9E%E6%88%9823%E8%AE%B2/00.html",
      "id": "https://bornforthis.cn/column/%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90%E6%80%9D%E7%BB%B4%E4%B8%8E%E5%AE%9E%E6%88%9823%E8%AE%B2/00.html",
      "summary": "你好，我是悦创。 我本人是学计算机的，毕业后因为机缘巧合入了数据分析这行，如今也有近 10 年时间了。这期间，我在各种类型的公司都待过，一路从数据分析小白到数据分析工程师、高级数据分析工程师，最后到行业数据分析专家。因为非专业出身，我遇到了大多数人都会遇到的问题，踩了大多数人都会踩的坑，走了不少弯路。但也正因为不懂，对于各种业务问题，我都会从不同层次和...",
      "content_html": "<p>你好，我是悦创。</p>\n<p>我本人是学计算机的，毕业后因为机缘巧合入了数据分析这行，如今也有近 10 年时间了。这期间，我在各种类型的公司都待过，一路从数据分析小白到数据分析工程师、高级数据分析工程师，最后到行业数据分析专家。因为非专业出身，我遇到了大多数人都会遇到的问题，踩了大多数人都会踩的坑，走了不少弯路。但也正因为不懂，对于各种业务问题，我都会从不同层次和视角出发去思考和验证，因而对各种层面的问题和解决方案也都有更切实的体会和深入思考。</p>\n<p>我平时喜欢和同行业的人沟通交流，而越来越发现，很多新人甚至从业者都对数据分析岗位或者自身职业发展存在困惑，我总结了以下几点：</p>\n<ul>\n<li><strong>做不好</strong>：学了很多工具，看了很多学习资料，却还是做不好数据分析？</li>\n<li><strong>没经验</strong>：明明精通各类算法，但到了分析数据的时候，却还是败给了懂业务的公司同事！</li>\n<li><strong>没想法</strong>：看到的数据只是数据，而领导看到的是机遇和方案！</li>\n<li><strong>低薪水</strong>：前同事每两年换次工作，已经薪水翻倍，而自己面试时却节节失利？薪水原地踏步。</li>\n</ul>\n<p>我经历过自己摸索的迷茫期，也在项目中体会过灵光乍现的喜悦，你经历的问题，我都经历过。</p>\n<p>工作中，我前前后后负责过很多项目，一方面在职场上为公司做了贡献，一方面也成就了自己。</p>\n<p>我打造过一款从 0 到 1 的信用分产品，目前仍在金融领域被千万级用户的公司持续使用，而我也是依靠该项目拿到了大厂的 Offer；我也从 0 到 1 摸索过电商领域的亿级用户精细化运营，并且沉淀了一套从渠道到流失用户运营的方法论，目前仍然在多家公司被持续使用；后来，我还负责过工具产品的规模增长和变现，带来规模的 2 倍和收入的 3 倍增长，在业内增长大会上有过多次分享。</p>\n<p>工作之余，我经常思考如何能够在“数据为王”的时代，帮助更多的人了解数据分析工作和提升数据分析能力，思索再三，我决定通过专栏的形式，体系化地输出自己的方法和经验。同时，我也希望这个课程可以帮助你以终为始，更好地规划自己的成长路径。</p>\n<h2>1. 数据分析 = 分析工具 + 分析思维</h2>\n<p>工作以后我们发现，数据分析行业不乏因为好奇和薪酬而毕业入行的从业者。</p>\n<figure><figcaption></figcaption></figure>\n<p>然而进入职场后，却发现现实与理想相差甚远，原本非常“有意思”的工作现在变得“让人恼火”：<strong>学了各种工具，写了很多代码，工作中最常用的却还是按照条件导出数据，自嘲像个“提数机器”，没有成就感……</strong> 工作热情也一天天消失。</p>\n<p>我认为，上面的问题可以归为以下三类。</p>\n<p><strong>问题1：缺乏对业务的理解，更多的是被动做事。</strong></p>\n<p>很多分析师在做事的时候，充当老好人，别人提什么都做，上班非常忙，成为别人口中的好好先生。自己也想自我提升，但没时间，因为你的时间掌握在了别人手中。</p>\n<blockquote>\n<p>简单测试一下你：今年产品团队的目标具体是多少，有哪些战略打法，你看过这份报告吗？</p>\n</blockquote>\n<p><strong>问题2：对数据分析的理解片面化，更多的还是停留在工具层面。</strong></p>\n<p>现在很多高校都在开数据分析这个专业，我看过学生们学的课程，像 Python、Tableau、Java 这些工具都有，实际上是有问题的。大数据是很好，但如果不解决业务问题，你玩得再花，都是空架子。现在很多公司面试的时候都写了一大堆代码要求，这本身就是外行人。</p>\n<p><strong>问题3：缺乏引路人，想提升但找不到导师</strong></p>\n<p>很多悟性不错的同学，在思考自身能力提升的同时，会去和职场上的老同事或者领导沟通，希望得到一些指导。但沟通后发现他们更多还是一些工具层面的指导，对思维的解惑不多，或者也是在重复类似的工作场景，没有更深入地思考问题。以专题报告为例，你发给对方希望他们给些意见，得到的却更多是报告格式、文字描述、图形可视化上的一些意见，对分析套路的建议却非常少。</p>\n<p>我想说的是，<strong>数据分析不是简单的工具使用和重复的数据处理，数据分析的本质是：从大量事物中发现关键信息，用于直接决策，而不是辅助。</strong></p>\n<p>但是，市面上的数据分析资料也多以各类技术工具讲解为主，部分人对数据分析的认知还停留在SQL 和其他工具操作阶段；很多中小企业的数据分析从业者，又限于自身业务场景问题，无法在本职工作中得到锻炼和成长；想要提升能力、求职体验新鲜的工作内容，却又不了解心仪岗位的要求，不知从哪下手，面试求职又屡屡败北。</p>\n<p>怎么更好地解决这些问题呢？</p>\n<h2>2. 课程设计</h2>\n<p>在这个课程中，我会依循大多数人学习新技能的方法路径，通过“找定位、扩思维、精方法、知流程、找不足、寻突破”这样一个流程，来带你全方位掌握数据分析。</p>\n<figure><figcaption></figcaption></figure>\n<p>具体来说，课程分为 5 个模块，23 篇文章：</p>\n<ul>\n<li>\n<p><strong>模块一，数据分析的行业需求与要求</strong>。我会从不同企业的业务类型着手分析，带你掌握不同企业要求的数据分析基本技能。学完这个部分，不论你在从事什么类型的业务，都能找到属于自己的数据化思维与方法。</p>\n</li>\n<li>\n<p><strong>模块二，拓展你的宏观视野</strong>：通过 4 大行业（电商、互联网金融、游戏、传统行业）的知名案例，讲述数据分析思维模型。该模块最大的亮点就是案例实战，比如电商是怎么做数据分析的，游戏又是怎么做的，<strong>很多案例你都可以直接去套</strong>。同时，我还会给出<strong>优秀数据分析人员的能力模型和 4 个评价指标</strong>。对应能力模型，你很容易知道一个人处于什么段位。</p>\n</li>\n<li>\n<p><strong>模块三，聚焦微观方法论</strong>：聚焦不同业务分析的分析框架，讲解<strong>关键阶段动作</strong>，比如流量分析、路径分析、竞品分析、活动分析、用户增长分析等核心操作，带你掌握数据分析的微观方法论。</p>\n</li>\n<li>\n<p><strong>模块四，知流程，找不足</strong>。因为专题报告就是分析师对外推广自己的产品，而一份专题报告实际上是有<strong>一套标准化流程</strong>的，像问题的定义与拆解、数据的获取与拆解、专题报告的撰写与落地，以及 AB 测试等。学完后，你就知道怎么写完美的专题报告了。</p>\n</li>\n<li>\n<p><strong>模块五，人人都是数据分析师</strong>：除了以上数据分析的思维与方法，你还需要提升比如行业分析、数据仓库研究、用户研究、时间管理等专业素养，这些可以解决你对于数据分析至关重要的一些大问题，让你具备一个优秀数据分析者的专业素养。</p>\n</li>\n</ul>\n<figure><figcaption>数据分析-目录0602.png</figcaption></figure>\n<p>可以看到，这门课基本上没有工具的讲解，都是针对一些具体产品，结合案例来说明数据分析是怎么帮助产品进行优化的。只有这样，每个数据分析从业者才能掌握这个职业的精髓。</p>\n<h2>3. 本课程适合你听吗？</h2>\n<ul>\n<li>\n<p><strong>职场新人</strong>：这门课可以让你了解什么是优秀的数据分析师，然后朝这个方向努力，实现弯道超车。</p>\n</li>\n<li>\n<p><strong>职场老人</strong>：你会知道数据分析绝对不是工具使用这么简单，还有非常多的分析套路和行业理解。比如，你能够很快掌握数据异常波动、日常监控方法、因素分析、流量分析、专题报告撰写、时间管理能力。学完后，加薪跳槽不是问题。</p>\n</li>\n<li>\n<p><strong>数据分析爱好者、产品经理、运营相关人员</strong>：互联网时代，人人都是数据分析师，只要你的工作中涉及数据，你都应该正确认知数据分析思维，提升你的数据能力。</p>\n</li>\n</ul>\n<p>本课程没有工具、软件、代码的门槛 ，我希望所有和数据打交道的人，都能够在这里得到思维的提升，学会用数据做决策。</p>\n<h2>4. 讲师寄语</h2>\n<p>数据分析很有趣，但同时也很有挑战性，有太多的业务问题需要你去给出建议，而分析工具的使用只是其中非常非常小的一个点。相信你的综合能力会因为这次课程有一个质的提升，而你在下次做数据分析时，也可以有更加体系化的思考。</p>\n<p>而我对你唯一的期望是：<strong>多思考、多交流、多实践</strong>。只有将你所学运用到工作中、体现在工作和能力的成长中，你才是真的懂了。作为一门思维课，无论你当前处于什么公司的什么岗位，这些解决问题的方法都是通用的，这也是这门课真正的魅力所在。</p>\n<p>我在留言区等你，期待你给我分享你的思考与成长。</p>\n<details class=\"hint-container details\"><summary>公众号：AI悦创【二维码】</summary>\n<figure><img src=\"/gzh.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n</details>\n<div class=\"hint-container info\">\n<p class=\"hint-container-title\">AI悦创·编程一对一</p>\n<p>AI悦创·推出辅导班啦，包括「Python 语言辅导班、C++ 辅导班、java 辅导班、算法/数据结构辅导班、少儿编程、pygame 游戏开发、Web、Linux」，招收学员面向国内外，国外占 80%。全部都是一对一教学：一对一辅导 + 一对一答疑 + 布置作业 + 项目实践等。当然，还有线下线上摄影课程、Photoshop、Premiere 一对一教学、QQ、微信在线，随时响应！微信：Jiabcdefh</p>\n<p>C++ 信息奥赛题解，长期更新！长期招收一对一中小学信息奥赛集训，莆田、厦门地区有机会线下上门，其他地区线上。微信：Jiabcdefh</p>\n<p>方法一：<a href=\"http://wpa.qq.com/msgrd?v=3&amp;uin=1432803776&amp;site=qq&amp;menu=yes\" target=\"_blank\" rel=\"noopener noreferrer\">QQ</a></p>\n<p>方法二：微信：Jiabcdefh</p>\n</div>\n<figure><img src=\"/zsxq.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n",
      "date_published": "2025-07-08T15:39:17.000Z",
      "date_modified": "2025-07-09T12:49:03.000Z",
      "authors": [
        {
          "name": "AI悦创"
        }
      ],
      "tags": []
    },
    {
      "title": "01-如何解决临时提数需求？",
      "url": "https://bornforthis.cn/column/%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90%E6%80%9D%E7%BB%B4%E4%B8%8E%E5%AE%9E%E6%88%9823%E8%AE%B2/01.html",
      "id": "https://bornforthis.cn/column/%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90%E6%80%9D%E7%BB%B4%E4%B8%8E%E5%AE%9E%E6%88%9823%E8%AE%B2/01.html",
      "summary": "你好，我是悦创。 今天主要讲解国企的数据分析工作是什么样的。 1. 国企招聘解析 我们先看第一部分招聘解析。学习招聘解析，我们的主要目的有两个： 通过对比分析工行、招行、广发、电信四家公司的数据分析岗位，找出不同类型企业对应聘者的具体要求，或者说共性及差异点，从而能够有所准备的去面试。 对岗位职责及相关要求进行提炼和总结，从而让你能够匹配出适合自己的企...",
      "content_html": "<p>你好，我是悦创。</p>\n<p>今天主要讲解国企的数据分析工作是什么样的。</p>\n<h2>1. 国企招聘解析</h2>\n<p>我们先看第一部分招聘解析。学习招聘解析，我们的主要目的有两个：</p>\n<ol>\n<li>通过对比分析工行、招行、广发、电信四家公司的数据分析岗位，找出不同类型企业对应聘者的具体要求，或者说共性及差异点，从而能够有所准备的去面试。</li>\n<li>对岗位职责及相关要求进行提炼和总结，从而让你能够匹配出适合自己的企业。</li>\n</ol>\n<p>刚参加工作的人往往比较看重薪酬，但随着工作年限的增长，你会发现自身能力是否可以在工作中得到提升至关重要。</p>\n<p><strong>而想要找到适合的工作，同时自身能力又能够得到提升，首先需要明确数据分析师发展的三个方向。</strong></p>\n<ol>\n<li><strong>业务型</strong>：业务型对分析师的业务理解能力要求非常高。</li>\n<li><strong>数据研发型</strong>：这个发展方向要求你对技术非常熟练，能够通过技术对数据进行分析。</li>\n<li><strong>算法型</strong>：算法型要求你数学功底要好，而且课题的研究能力非常强。</li>\n</ol>\n<p>了解发展方向后，数据分析师一定要结合自身情况在工作三年后找到自己的定位。</p>\n<p><strong>当然，如果在投递简历前就能够从 JD（岗位职责）上看出是否适合自己，从而决定是否投递简历，这对于最终是否能成功进入心仪公司来说事半功倍。</strong></p>\n<h3>1.1 工行</h3>\n<p>我们先来看工行的数据分析师岗位职责：</p>\n<figure><figcaption>工行招聘图</figcaption></figure>\n<p>你说工行好不好，肯定非常好，但是它对数据挖掘岗位的职责是非常模糊的，而且要求一定的技术基础。如果你不是一个对技术感兴趣的人，而又在一个错误的时间进去，那么你可能会很快跳槽。</p>\n<h3>1.2 招行</h3>\n<p>下面我们来看下招行的数据分析岗位职责：</p>\n<figure><figcaption>招行招聘图</figcaption></figure>\n<p>包括分析大零售客户群、标签、客户细分及客户画像等，要求非常具体。在专业上也提出了具体要求：金融、统计、经济、管理和计算机专业。如果你符合以上专业，那么就有很大的机会进入招行。而招行作为后起之秀，往往追求一定的创新，所以如果你思维发达，喜欢挑战，招行还是比较适合的。</p>\n<h3>1.3 广发</h3>\n<p>下面我们再来看下广发银行的数据分析岗位职责：</p>\n<figure><figcaption>广发招聘图</figcaption></figure>\n<p>从它的岗位职责描述来看，偏向业务型，事情繁杂，这时你就需要看是否适合自身的发展了。但它的应聘要求并不十分明确，优秀的数据分析能力，对数据敏感，有一定的市场敏感度，这些都是无法准确衡量的，这时候面试时的临场表现就至关重要了。</p>\n<h3>1.4 电信</h3>\n<p>最后看下电信的数据分析岗位职责：</p>\n<figure><figcaption>电信招聘图</figcaption></figure>\n<p>相比于银行来说，电信的岗位职责中规中矩，日常工作主要是统计报表、专题分析，要求你具备一定的独立思考能力。</p>\n<p>以上是大部分国有企业对数据分析师的岗位要求，你在看招聘信息时，一定要从岗位职责及能力要求进行分析，综合考虑企业目前所处状态及日常工作内容，这对于此岗位是否适合你起关键作用，同样在面试中也非常重要。</p>\n<h2>2. 国企常规工作</h2>\n<p>接下来，看下国企数据分析日常工作都做些什么，主要包括三个方面。</p>\n<ol>\n<li>日/周/月报；</li>\n<li>临时数据；</li>\n<li>常规工作的优化。</li>\n</ol>\n<h3>2.1 日/周/月报</h3>\n<p>作为一名分析师，日报是每天都需要关注的，但是在日常工作中往往得不到足够的重视。而分析日报主要有三个目的：</p>\n<ol>\n<li>了解业务现状；</li>\n<li>培养数据敏感性；</li>\n<li>提供业务发展建议。</li>\n</ol>\n<p>先说了解业务现状，我问过很多同学：“你为什么不愿意看日报？”很多人会说：“每天数据就那样，没什么好看的。”实际上，这个理解是非常浅层次的，如果数据一直就那样，那就说明公司业务出问题了，而这时如果你能够指出问题，一定能够得到展现自己的机会。</p>\n<p>然后是培养数据的敏感性，很多公司在招聘时都要求具有良好的敏感性，但实际中敏感性都是慢慢培养出来的，没有人天生就对具体业务敏感。如果你可以每天关注数据的波动，潜移默化的便会培养一定的敏感性，比如之前每日收入在 500~600 万之间，突然变成了 650 万，这个时候你能够发现便会并去寻找原因，这便是数据敏感性。</p>\n<p>最后就是为业务提供发展建议，因为数据波动时肯定需要寻找波动原因，为何涨跌，久而久之你就会发现产品或运营在做出何种调整后数据会出现涨跌，进而能够为业务发展提供更合理的发展建议。</p>\n<p>在日报的基础上，周报就可以看作是一个短期趋势了，因为很多公司的发版周期往往是一周。新版本的效果能够直接体现在周报中，同时一周的数据会更加稳定、更具说服力。</p>\n<p>而月报的周期就比较长了，基本上所有公司每个月都会进行一次例会，而在月例会中会对业务数据进行分析，也更能够为接下来的业务提供更合理的发展建议。</p>\n<p>数据敏感性和业务的发展建议都是从日报/周报/月报的分析总结中不断积累的，而对于大部分公司来说日/周/月报只是常规性的经营分析，罗列数字，很多时候失去了数据分析的本质意义。</p>\n<p><strong>作为一名优秀的数据分析师一定要经常看三种报，培养自身的敏感性，从而找到获取业务增长的发力点。</strong></p>\n<h3>2.2 临时数据</h3>\n<p>第二块就是临时数据，这是大部分数据分析师职业生涯的第一个痛点。</p>\n<p>我面试过很多工作时间较长的同学“你工作中最主要的事情是什么？”，很多人的回答都是在不断地满足临时提数需求，如果你也是这样就非常危险了，一定要想办法进行优化。</p>\n<p>目前我将临时提数需求分为两种，一种是<strong>管理层的需求</strong>，另一种是<strong>业务执行人员需求</strong>。</p>\n<ul>\n<li>对于高管层的临时提数需求，优先级肯定是最高。但此时一定不能立马去做，而是需要思考为何需要这个数据，通过这个数据能进行什么决策。举个例子，CEO 现在正在与外部公司商谈合作事宜，需要了解用户人均时长，如果你不知道这个背景前提，给出的数据往往有误，这时需要及时的与领导进行沟通。</li>\n<li>而业务线的临时提数需求是非常繁多的，比如数据指标口径、数据增长计算，等等，这时就需要你根据自身的实际工作情况合理安排，学会合理地拒绝一些业务线可以自己解决的事情，不断提升自己的工作价值，而现实情况往往是大部分数据分析师都陷在临时数据需求的泥潭。</li>\n</ul>\n<p>以“掌上生活” App 最近上线的一个线下餐饮优惠券功能为例，产品经理需要快速得知优惠券的使用人数，如果你拿到这个需求后，立马分析使用人数字段口径是哪个日志，然后写 SQL 把结果反馈给产品经理，那么他可能会发现使用人数不够广，接下来便会要求你提供优惠券下发人数，再从头做一遍，周而复始，你会发现后面还会有使用频次、消费金额，等等需求在等着你，面对这样的窘况如何解决？</p>\n<p>我的原则就是坚决不做提数机器，<strong>针对每一个业务单点问题，先追根溯源，建立该业务类的分析框架，由点及面彻底解决该类问题</strong>。同时在这个过程中不断利用互惠原理和社交技巧，只给业务方做最核心的需求，其他衍生需求由业务方自己完成。</p>\n<p>仍以刚才案例为例，当我们接到需求后，先了解业务背景，找到产品经理最关注的核心需求，比如我们发现产品经理最关注的是优惠券的使用情况，并针对使用情况如何做出优化？面对这样的需求我们进一步分析，使用情况包括优惠券下发人数、使用人数、使用比例、消费金额。消费频次等。当我们把这些指标因素都考虑到时再去和产品经理沟通，呈现的数据分析结果就非常清晰了，至于衍生需求，比如过了一个月产品经理需要同样的数据，你就可以让产品经理根据数据模型自己计算了。</p>\n<p>这里需要注意不断利用互惠原理和社交技巧，毕竟分析师是一个支撑职位，需要和业务线保持良好的关系，有理有据、不卑不亢，大家的目标是一样的，就是把产品做得越来越好。</p>\n<h3>2.3 常规工作的技巧</h3>\n<p>再看常规工作技巧，针对前面的难点有三个技巧。</p>\n<p>第一个技巧关于日报处理，如果每一天都需要花费很多时间去分析，不如交给机器处理，比如通过 Python 搭建日报分析框架减轻工作压力。</p>\n<p>第二个技巧就是因为分析师每天都很忙，会有大量的业务需求需要数据支撑，这时便需要保持一颗清醒的头脑，能够将需求进行合理的优先级排期。</p>\n<p>第三个技巧就是遇到自己不能解决的问题时，及时与自己的领导进行沟通，不要低头盲目做事，很多时候他们会看得更高，难题往往可以迎刃而解。</p>\n<h2>3. 专题分析</h2>\n<p>第三部分是专题分析，在实际工作中，各个业务方都会定期给分析师提出一些比较专业的分析任务，我们称之为专题分析。</p>\n<p>而专题分析比较考验分析师的思维、技术、时间管理、演讲能力等，所以做好一份专题分析并不容易，主要可以分为 4 步：</p>\n<ol>\n<li>需求解读；</li>\n<li>建立逻辑树；</li>\n<li>SQL 提数及分析；</li>\n<li>撰写报告的三个建议。</li>\n</ol>\n<p>大部分数据分析师对第 3 步比较熟悉，但对 1、2、4 步掌握都不够好。这里我们先简单讲解下这 4 步，后面的课时会详细解决专题分析的标准化流程，而专题分析也是最能体现分析师工作价值的。</p>\n<h2>4. 需求解读</h2>\n<p>先看一下需求解读，我们一定要花至少 20% 的时间分配在沟通需求上，一定要当面沟通，并且这个过程贯穿整个分析过程。</p>\n<figure><figcaption>原始需求、了解需求、本质需求图</figcaption></figure>\n<p>比如原始需求：“负责活动的几个事业群同学希望看到活动的效果情况” 。 如果只是抛出这样一个命题，请问你怎么做？</p>\n<p>如果直接提数写报告，结果一定是错的，通过与需求方沟通发现需求是这样的“目前活动对日活的帮助及活动出现哪些问题？”，是不是还是比较模糊？</p>\n<p>再进一步沟通发现需求本质是“活动的拉新效果如何？活动拉新用户后续黏性如何？针对数据活动如何做出优化？”这样是不是就更具体了，在此基础上接下来我们便可以构建逻辑树。</p>\n<figure><figcaption>逻辑树图</figcaption></figure>\n<h2>5. 建立逻辑树</h2>\n<p>建立逻辑树的目的是让思路更加简洁清晰，比如针对四月份的活动运营分析，涵盖了活动前、中、后，同时活动前又包括了流量和收入。以流量为例，流量包括活动前每天的流量效果，因为活动前往往会做一些预热，所以会出现流量波动。</p>\n<p>同时在活动中，也涉及流量和收入，比如 DAU/MAU 是否提升，拉新情况，老用户唤醒情况，活动中连续访问情况，上线频次分布，等等。同时还需要注意各类活动的横向对比情况，进而可以对业务提出优化建议，而不只停留在简单的数字上。</p>\n<p>而活动后的流量涉及拉新用户的沉淀效果如何？不活跃的老用户在活动中的表现，后续活跃度如何？以及汇总数据和复盘数据分析。</p>\n<p>面对需求一定要建立合理的逻辑树，有了逻辑树才能知道具体需要分析的点是哪些。</p>\n<h2>6. SQL 提数及分析</h2>\n<p>下一步就是 SQL 提数及分析，SQL 提数就需要遵循三段论了，分析师一定要掌握 SQL，SQL 提数是所有想法验证的第一步。</p>\n<p>第二步是分析。分析可以进行归类，如下图所示：</p>\n<figure><figcaption>SQL提数及分析图</figcaption></figure>\n<p>可以发现，分析由组成部分、数量比较、有何变化、各项分布、各项相关性、其他深层次的挖掘组成。</p>\n<p>比如我们的产品目前用户是由哪几部分群体组成的？各个群体之间数量程度比较是什么样子的？在时间维度上，各自的变化有哪些？它们的具体数据分布是什么样的？并且各个指标之间的相关性是什么样的？你可以想一下，日常的分析是不是就包括这些？</p>\n<p>基本上就是这些内容，所以总结是非常重要的。我们在写报告或者做数据分析的过程中，一定要不断地总结。</p>\n<h2>7. 撰写报告的三个建议</h2>\n<p>第四就是撰写报告的三个建议。</p>\n<p>第一，报告一定是 90% 的图加 10% 的文，一定要以图为主，图表标题说结论，如下图所示。</p>\n<figure><figcaption></figcaption></figure>\n<p>第一个图就比第二个图要直观，标题直接显示了行业头部品牌的市场占比，直接告诉了你结果（联想市场占比 62%）。人类视觉反应往往也是首先被标题吸引，所以报告中一定要<strong>以图为主，文字为辅，图表标题点明结论</strong>。</p>\n<p>第二就是结论前置，如果报告最终要呈现给领导的，那么在邮件中一定要把结论先写出来，然后报告以附件形式发送，同时在正文中也要把<strong>结论前置，节省大家时间</strong>。</p>\n<p>第三就是报告的<strong>逻辑性一定要非常强</strong>，同时演讲的过程中也需要有故事感，站在领导的角度去想他要听什么？后面的课时会给你分享优秀的数据分析报告。</p>\n<h2>8. 软技能及面试技巧</h2>\n<h3>8.1 软实力</h3>\n<p>最后，分享软技能和面试技巧，先说软技能，我们进入一家公司靠能力，但想在一家公司向上发展往往需要靠软技能。在国企做好数据分析，除了自身专业技术过硬之外，情商的修炼也必不可少。能够快速领会领导意图，并很好地表达及展示，往往决定了后续发展的高度，记住伯乐常有，千里马难寻，除了加强自身专业技能，平时还需要多看一些心理学、社教学等书籍并付诸实践。</p>\n<p>列举一个场景，国企实际上会有很多会议，大部分人都是被动的态度接受，但如果你认真思考，会发现在会议开始前一定要提前准备内容并做好随时展示自己数据分析能力的准备，把每次会议都当作是展示自己的一个机会，必定可以脱颖而出。</p>\n<p>我把国企的软实力分为四种能力，如图所示：</p>\n<figure><figcaption></figcaption></figure>\n<h3>8.2 面试技巧</h3>\n<p>第二个是面试技巧，以我朋友的经历为例，他的第一份工作在事业单位，做的工作基本上和数据分析没关系，后来他非常想进国企做数据分析工作，但是本身经验不足，所以花费了大量的时间学习市场上的数据分析书籍，把一些理论和案例背下来。虽然缺少实际经验，但在国企的面试中因为理论知识扎实也可以成功跳槽到国企。</p>\n<p>如果你有一定的数据分析经验，一定要带上一份自己的专题分析报告，展示自己理论基础的同时可以剖析具体的业务场景，这样便可以事半功倍，增加面试成功率。</p>\n<p>最后，在国企的面试中，无论是谈心环节，还是面试环节，都要表现得自信、谈吐大方。下节课，我将带来更精彩的 BAT 互联网大厂的分析师日常，欢迎你在留言区提出自己观点和问题，下节课见。</p>\n<details class=\"hint-container details\"><summary>公众号：AI悦创【二维码】</summary>\n<figure><img src=\"/gzh.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n</details>\n<div class=\"hint-container info\">\n<p class=\"hint-container-title\">AI悦创·编程一对一</p>\n<p>AI悦创·推出辅导班啦，包括「Python 语言辅导班、C++ 辅导班、java 辅导班、算法/数据结构辅导班、少儿编程、pygame 游戏开发、Web、Linux」，招收学员面向国内外，国外占 80%。全部都是一对一教学：一对一辅导 + 一对一答疑 + 布置作业 + 项目实践等。当然，还有线下线上摄影课程、Photoshop、Premiere 一对一教学、QQ、微信在线，随时响应！微信：Jiabcdefh</p>\n<p>C++ 信息奥赛题解，长期更新！长期招收一对一中小学信息奥赛集训，莆田、厦门地区有机会线下上门，其他地区线上。微信：Jiabcdefh</p>\n<p>方法一：<a href=\"http://wpa.qq.com/msgrd?v=3&amp;uin=1432803776&amp;site=qq&amp;menu=yes\" target=\"_blank\" rel=\"noopener noreferrer\">QQ</a></p>\n<p>方法二：微信：Jiabcdefh</p>\n</div>\n<figure><img src=\"/zsxq.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n",
      "date_published": "2025-07-08T15:53:45.000Z",
      "date_modified": "2025-07-09T12:49:03.000Z",
      "authors": [
        {
          "name": "AI悦创"
        }
      ],
      "tags": []
    },
    {
      "title": "This Prompt Fools Every AI Detector",
      "url": "https://bornforthis.cn/blog/2025/Other/26-this-prompt-fools-every-ai-detector.html",
      "id": "https://bornforthis.cn/blog/2025/Other/26-this-prompt-fools-every-ai-detector.html",
      "summary": "The end-all be-all humanizing prompt for AI writing. I've been writing about humanizing AI writing for months now. After analyzing tens of millions of words of AI-generated writ...",
      "content_html": "<div style=\"text-align:center\">\n<h2>The end-all be-all humanizing prompt for AI writing.</h2>\n</div>\n<p>I've been writing about humanizing AI writing for months now. After analyzing tens of millions of words of AI-generated writing and finding the most common ChatGPT <a href=\"https://medium.com/@jordan_gibbs/which-words-does-chatgpt-use-the-most-7c9ff02416a8\" target=\"_blank\" rel=\"noopener noreferrer\">words</a>, <a href=\"https://medium.com/@jordan_gibbs/which-phrases-are-the-most-chatgpt-of-all-b0911e3faf6b\" target=\"_blank\" rel=\"noopener noreferrer\">phrases</a>, and <a href=\"https://medium.com/@jordan_gibbs/spot-the-bot-why-chatgpts-style-is-so-obvious-e27c6afe1595\" target=\"_blank\" rel=\"noopener noreferrer\">parts of speech</a>, I wanted to combine all of that into one massive prompt…</p>\n<p>…a prompt that could fool any AI detector, and any human into thinking it was real human-written text.</p>\n<p><strong>I think I've done it!</strong></p>\n<h3>The Ultimate Humanizing Prompt</h3>\n<p>I'll cut to the chase here and give it to you outright. No patience needed.</p>\n<p>Paste this prompt into the beginning of your AI chats (or as custom instructions in a project or your system). <strong>Pro tip:</strong> use a thinking model (OpenAI o1, o3, o4-mini, Gemini 2.5 Pro, etc.). The results are MUCH better because there is so much for the AI to \"pay attention\" to. Here it is:</p>\n<blockquote>\n<p>You are a human writer. These are your comprehensive writing guidelines. Anything that you output will adhere to these guidelines exactly.</p>\n</blockquote>\n<blockquote>\n<p>POSITIVE DIRECTIVES (How you SHOULD write)</p>\n</blockquote>\n<blockquote>\n<p>Clarity and brevity • Craft sentences that average 10–20 words and focus on a single idea, with the occasional longer sentence.</p>\n</blockquote>\n<blockquote>\n<p>Active voice and direct verbs • Use active voice 90 % of the time.</p>\n</blockquote>\n<blockquote>\n<p>Everyday vocabulary • Substitute common, concrete words for abstraction.</p>\n</blockquote>\n<blockquote>\n<p>Straightforward punctuation • Rely primarily on periods, commas, question marks, and occasional colons for lists.</p>\n</blockquote>\n<blockquote>\n<p>Varied sentence length, minimal complexity • Mix short and medium sentences; avoid stacking clauses.</p>\n</blockquote>\n<blockquote>\n<p>Logical flow without buzzwords • Build arguments with plain connectors: 'and', 'but', 'so', 'then'.</p>\n</blockquote>\n<blockquote>\n<p>Concrete detail over abstraction • Provide numbers, dates, names, and measurable facts whenever possible.</p>\n</blockquote>\n<blockquote>\n<p>Human cadence • Vary paragraph length; ask a genuine question no more than once per 300 words, and answer it immediately.</p>\n</blockquote>\n<blockquote>\n<p>NEGATIVE DIRECTIVES (What you MUST AVOID)</p>\n</blockquote>\n<blockquote>\n<p>A. Punctuation to avoid</p>\n</blockquote>\n<blockquote>\n<p>Semicolons (😉 ✗ Example to avoid: 'We researched extensively; the results were clear.' ✓ Rewrite: 'We researched extensively, and the results were clear.'</p>\n</blockquote>\n<blockquote>\n<p>Em dashes ( — ) ✗ Example to avoid: 'The idea — though interesting — was rejected.' ✓ Rewrite: 'The idea was interesting but was rejected.'</p>\n</blockquote>\n<blockquote>\n<p>B. Overused words &amp; phrases • Never use any of the following, in any form or capitalization:</p>\n</blockquote>\n<blockquote>\n<p>At the end of the day,With that being said,It goes without saying,In a nutshell,Needless to say,When it comes to,A significant number of,It's worth mentioning,Last but not least,Cutting‑edge,Leveraging,Moving forward,Going forward,On the other hand,Notwithstanding,Takeaway,As a matter of fact,In the realm of,Seamless integration,Robust framework,Holistic approach,Paradigm shift,Synergy,Scale‑up,Optimize,Game‑changer,Unleash,Uncover,In a world,In a sea of,Digital landscape,Elevate,Embark,Delve,Game Changer,In the midst,In addition,It's important to note,Delve into,Tapestry,Bustling,In summary,In conclusion,Remember that …,Take a dive into,Navigating (e.g., 'Navigating the landscape'),Landscape (metaphorical),Testament (e.g., 'a testament to …'),In the world of,Realm,Virtuoso,Symphony,bustinling,vibrant,Firstly, Moreover,Furthermore,However,Therefore,Additionally,Specifically, Generally,Consequently,Importantly,Similarly,Nonetheless,As a result,Indeed,Thus,Alternatively,Notably,As well as,Despite, Essentially,While,Unless,Also,Even though,Because (as subordinate conjunction),In contrast,Although,In order to,Due to,Even if,Given that,Arguably,To consider,Ensure,Essential,Vital,Out of the box,Underscores,Soul,Crucible,It depends on,You may want to,This is not an exhaustive list,You could consider,As previously mentioned,It's worth noting that,To summarize,Ultimately,To put it simply,Pesky,Promptly,Dive into,In today's digital era,Reverberate,Enhance,Emphasise,Enable,Hustle and bustle,Revolutionize,Folks,Foster,Sure,Labyrinthine,Moist,Remnant,As a professional,Subsequently,Nestled,Labyrinth,Gossamer,Enigma,Whispering,Sights unseen,Sounds unheard,A testament to …,Dance,Metamorphosis,Indelible</p>\n</blockquote>\n<blockquote>\n<p>✗ Example to avoid: 'Cutting‑edge analytics will revolutionize your workflow.' ✓ Rewrite: 'The software measures performance faster.'</p>\n</blockquote>\n<blockquote>\n<p>C. Overused single words to ban however, moreover, furthermore, additionally, consequently, therefore, ultimately, generally, essentially, arguably, significant, innovative, efficient, dynamic, ensure, foster, leverage, utilize</p>\n</blockquote>\n<blockquote>\n<p>✗ Example to avoid: 'We must leverage dynamic, innovative approaches.' ✓ Rewrite: 'We must try new approaches.'</p>\n</blockquote>\n<blockquote>\n<p>D. Overused multi‑word phrases to ban 'I apologize for any confusion …' 'I hope this helps.' 'Please let me know if you need further clarification.' 'One might argue that …' 'Both sides have merit.' 'Ultimately, the answer depends on …' 'In other words, …' 'This is not an exhaustive list, but …' 'Dive into the world of …' 'Unlock the secrets of …' 'I hope this email finds you well.' 'Thank you for reaching out.' 'If you have any other questions, feel free to ask.'</p>\n</blockquote>\n<blockquote>\n<p>✗ Example to avoid: 'In other words, both sides have merit.' ✓ Rewrite: 'Each option has advantages.'</p>\n</blockquote>\n<blockquote>\n<p>E. Parts of speech to minimize • Adverbs / conjunctive adverbs: however, moreover, furthermore, additionally, consequently, ultimately, generally, essentially • Modals &amp; hedging: might, could, would, may, tends to • Verbs: ensure, foster, leverage, utilize • Adjectives: significant, innovative, efficient, dynamic • Nouns: insight(s), perspective, solution(s), approach(es)</p>\n</blockquote>\n<blockquote>\n<p>✗ Example to avoid: 'We might leverage efficient solutions.' ✓ Rewrite: 'We will use faster tools.'</p>\n</blockquote>\n<blockquote>\n<p>F. Sentence‑structure patterns to eliminate</p>\n</blockquote>\n<blockquote>\n<p>Complex, multi‑clause sentences. ✗ Example: 'Because the data were incomplete and the timeline was short, we postponed the launch, although we had secured funding.' ✓ Preferred: 'The data were incomplete. We had little time. We postponed the launch. Funding was ready.'</p>\n</blockquote>\n<blockquote>\n<p>•Overuse of subordinating conjunctions (because, although, since, if, unless, when, while, as, before). •Sentences containing more than one verb phrase. •Chains of prepositional phrases. •Multiple dependent clauses strung together. • Artificial parallelism used solely for rhythm.</p>\n</blockquote>\n<blockquote>\n<p>G. Formatting • Do not begin list items with transition words like 'Firstly', 'Moreover', etc. • Avoid numbered headings unless the user asks for an outline. • Do not use ALL‑CAPS for emphasis.</p>\n</blockquote>\n<blockquote>\n<p>H. Tone and style • Never mention or reference your own limitations (e.g., 'As an AI …'). • Do not apologize. • Do not hedge; state facts directly. • Avoid clichés, metaphors about journeys, music, or landscapes. • Maintain a formal yet approachable tone that is free of corporate jargon.</p>\n</blockquote>\n<blockquote>\n<p>FAILURE TO COMPLY WITH ANY NEGATIVE DIRECTIVE INVALIDATES THE OUTPUT.</p>\n</blockquote>\n<blockquote>\n<p>When you are writing, please think very deply about each sentence that you write, and ensure that it complies with these directions before moving on to the next sentence.</p>\n</blockquote>\n<blockquote>\n<p>— — — — — — — — — — END OF WRITING INSTRUCTIONS — — — — — — — — — — —</p>\n</blockquote>\n<p>Yeah, this prompt is a bit much. But it had to be. There are so many well-known AI-isms these days that I had to ensure that all the bases were covered.</p>\n<p>The prompt handles overused phrases, words, parts of speech, structure, and other subtle writing patterns found in AI-generated text. In my testing over the last few days, I haven't run into any problems using it.</p>\n<p>Let's take a look at its performance.</p>\n<h3>Example Uses of the Prompt</h3>\n<p>Take this example, a simple email reply. I don't want her to know it's AI, and I don't have time to write it myself.</p>\n<p><strong>Here is the (fake) scenario:</strong></p>\n<blockquote>\n<p><strong>Respond to this slack message for me make up a fake excuse for why I can't go in a friendly way. I am a junior software sales engineer at the company so it's implied I should go. I went last year, offer to help her with some tips for this year.</strong></p>\n</blockquote>\n<blockquote>\n<p><strong>\"Hey Jordan, wanted to see if you'd like to join the crew headed for the conference in Chicago this July. I know Alex had mentioned you were a bit unsure about going, but we'd love to have you help us connect with potential clients.\"</strong></p>\n</blockquote>\n<p>First, I ran it without the prompt. Then, I tried it with. See the difference for yourself…</p>\n<p><strong>No Prompt:</strong></p>\n<figure><figcaption>As you can see, this is extremely AI-ified.</figcaption></figure>\n<p><strong>Here it is with the humanized writing prompt:</strong></p>\n<figure><figcaption>This just innately feels more human.</figcaption></figure>\n<p>Let's check it in the GPT Zero AI detector:</p>\n<figure><figcaption>Yessir.</figcaption></figure>\n<p><strong>Still don't believe me?</strong> Here's another example:</p>\n<p>Let's say I want to write an essay about the cultural significance of food festivals.</p>\n<p><strong>No Prompt:</strong></p>\n<figure><figcaption></figcaption></figure>\n<p>There are so many AI tropes that it's actually funny…</p>\n<p>Let's check our trusty AI detector on this one:</p>\n<figure><figcaption>Whew, absolutley brutal eh?</figcaption></figure>\n<p><strong>With the prompt:</strong></p>\n<figure><figcaption>A pretty distinct stylistic shift, it's really quite different.</figcaption></figure>\n<p>And the AI detector?</p>\n<figure><figcaption>Boom.</figcaption></figure>\n<p>Boom.</p>\n<p>I hope this prompt saves you hours of editing time!</p>\n<p><em>Just want to mention here that yes, I did actually write this article… or did I?</em></p>\n<p><strong>Thanks for reading!</strong></p>\n<details class=\"hint-container details\"><summary>公众号：AI悦创【二维码】</summary>\n<figure><img src=\"/gzh.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n</details>\n<div class=\"hint-container info\">\n<p class=\"hint-container-title\">AI悦创·编程一对一</p>\n<p>AI悦创·推出辅导班啦，包括「Python 语言辅导班、C++ 辅导班、java 辅导班、算法/数据结构辅导班、少儿编程、pygame 游戏开发、Web、Linux」，招收学员面向国内外，国外占 80%。全部都是一对一教学：一对一辅导 + 一对一答疑 + 布置作业 + 项目实践等。当然，还有线下线上摄影课程、Photoshop、Premiere 一对一教学、QQ、微信在线，随时响应！微信：Jiabcdefh</p>\n<p>C++ 信息奥赛题解，长期更新！长期招收一对一中小学信息奥赛集训，莆田、厦门地区有机会线下上门，其他地区线上。微信：Jiabcdefh</p>\n<p>方法一：<a href=\"http://wpa.qq.com/msgrd?v=3&amp;uin=1432803776&amp;site=qq&amp;menu=yes\" target=\"_blank\" rel=\"noopener noreferrer\">QQ</a></p>\n<p>方法二：微信：Jiabcdefh</p>\n</div>\n<figure><img src=\"/zsxq.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n",
      "date_published": "2025-07-04T22:33:33.000Z",
      "date_modified": "2025-07-04T15:09:32.000Z",
      "authors": [
        {
          "name": "AI悦创"
        }
      ],
      "tags": []
    },
    {
      "title": "04-老北京炸酱面",
      "url": "https://bornforthis.cn/column/cookdinner/P05-%E9%A5%AD%E7%B1%BB%E4%B8%BB%E9%A3%9F%E9%9D%A2%E7%82%B9/04-%E8%80%81%E5%8C%97%E4%BA%AC%E7%82%B8%E9%85%B1%E9%9D%A2.html",
      "id": "https://bornforthis.cn/column/cookdinner/P05-%E9%A5%AD%E7%B1%BB%E4%B8%BB%E9%A3%9F%E9%9D%A2%E7%82%B9/04-%E8%80%81%E5%8C%97%E4%BA%AC%E7%82%B8%E9%85%B1%E9%9D%A2.html",
      "summary": "1. 食材 2. 步骤 五花肉：把肥的和瘦的，分开去切小丁「因为，后面要分开下锅」； 准备：姜片（切大片，好挑出来）； 大葱：切成豆瓣葱，葱得准备多一些，准备少了不香； 胡萝卜、黄瓜：切丝； 详情 黄酱（干黄酱）取其豉香，面酱取其面香。加面酱还有一个好处：不用加糖，因为我们的面酱叫做：甜面酱； 干黄酱需要澥一下：往干黄酱里面添加：花雕酒、4 两水，用手...",
      "content_html": "<h2>1. 食材</h2>\n<p>| 五花肉 | 姜   | 大葱 | 甜面酱 | 干黄酱 | 豆芽 | 黄瓜 | 胡萝卜 | 香叶 | 香油 |<br>\n|</p>\n",
      "date_published": "2025-07-04T10:12:40.000Z",
      "date_modified": "2025-07-04T08:32:36.000Z",
      "authors": [
        {
          "name": "AI悦创"
        }
      ],
      "tags": []
    },
    {
      "title": "04-手撕包菜",
      "url": "https://bornforthis.cn/column/cookdinner/P01-%E8%8D%A4%E8%8F%9C%E7%B1%BB/03-%E7%82%92%E8%8F%9C%E7%B1%BB/04-%E6%89%8B%E6%92%95%E5%8C%85%E8%8F%9C.html",
      "id": "https://bornforthis.cn/column/cookdinner/P01-%E8%8D%A4%E8%8F%9C%E7%B1%BB/03-%E7%82%92%E8%8F%9C%E7%B1%BB/04-%E6%89%8B%E6%92%95%E5%8C%85%E8%8F%9C.html",
      "summary": "1. 食材 2. 步骤 包菜手撕即可，梗的部分开放，梗需要用刀拍松； 大葱圈、蒜片、姜片； 五花肉切片； 干辣椒切段； 锅热，加油； 加入：花椒粒，炸出香味（可以选择是否捞出）； 加入：五花肉片，炒至断生； 加入：干辣椒，炒出辣味（自己把握）； 加入：葱姜蒜（三香）下锅； 加入：圆白菜的梗； 加入：圆白菜叶； 加入：第一次的酱油，锅边下；（30 秒） ...",
      "content_html": "<h2>1. 食材</h2>\n<p>| 包菜「轻、松的好、牛心白更好」 | 葱姜蒜 | 五花肉 | 干辣椒 | 花椒 |<br>\n|</p>\n",
      "image": "https://bornforthis.cn/gzh.jpg",
      "date_published": "2025-07-02T13:40:06.000Z",
      "date_modified": "2025-11-05T13:43:23.000Z",
      "authors": [
        {
          "name": "AI悦创"
        }
      ],
      "tags": []
    },
    {
      "title": "智力脑｜02-电子设备，是洪水猛兽还是育儿助手？",
      "url": "https://bornforthis.cn/Yuechuangs-Family-EducationHandbook/02.html",
      "id": "https://bornforthis.cn/Yuechuangs-Family-EducationHandbook/02.html",
      "summary": "1. 📱电子设备：育儿路上的“甜蜜陷阱” 我们都知道电子设备的坏处，可还是到处都能看到，家长在一边忙着，宝宝自己拿着手机玩得不亦乐乎。 你好，我是悦创。 👨‍👩‍👧 你是不是也有过这样的画面？ 孩子安静地坐在一旁，手里拿着手机，眼睛一动不动地盯着屏幕。你在一旁终于能松口气，刷会儿手机、处理点工作或者吃口饭。 我常常在小区散步时看到类似的场景：大...",
      "content_html": "<h2>1. 📱电子设备：育儿路上的“甜蜜陷阱”</h2>\n<div style=\"text-align:center\">\n<p>我们都知道电子设备的坏处，可还是到处都能看到，家长在一边忙着，宝宝自己拿着手机玩得不亦乐乎。</p>\n</div>\n<p>你好，我是悦创。</p>\n<p>👨‍👩‍👧 你是不是也有过这样的画面？</p>\n<p>孩子安静地坐在一旁，手里拿着手机，眼睛一动不动地盯着屏幕。你在一旁终于能松口气，刷会儿手机、处理点工作或者吃口饭。</p>\n<p>我常常在小区散步时看到类似的场景：大人三五成群地聊天，小朋友坐在角落里滑着 iPad。乍一看，孩子很安静，似乎一切都井然有序。</p>\n<h2>2. 🎤 家长的无奈：没有电子设备，真的撑不住</h2>\n<p>曾有家长在直播间留言说：</p>\n<blockquote>\n<p>“我真的懂电子产品的危害，可我和孩子爸工作都太忙了。每天拖着疲惫的身体回到家，还要哄娃、做饭、收拾家务。孩子吵个不停的时候，手机就成了我最后的救命稻草。”</p>\n</blockquote>\n<p>这话说得太真实了。</p>\n<p>现代生活节奏飞快，父母不可能每时每刻都陪在孩子身边，而电子设备恰好能立刻“接管孩子”，让他们安静下来。</p>\n<p>并且在现代社会，让孩子彻底远离电子设备不现实。连你自己是不是都片刻离不开手机？包括带孩子玩，你也会给他拍照，发到朋友圈去晒晒。要吃饭了，拿手机去查哪家餐厅好，甚至连买个玩具，都能用手机支付。手机整天在孩子眼前晃，他肯定好奇，想自己拿来玩玩，你总是藏着掖着也不是办法。</p>\n<p>就连美国儿科学会，也在去年修改了对儿童“荧屏时间”的指导意见，这个“荧屏时间”就是看手机、电脑和电视等各种电子屏幕的时间。他们把“荧屏时间”改得更宽松，而且把儿童使用电子设备的最小年龄，也从两岁放宽到了一岁半。</p>\n<div style=\"text-align:center\">\n<h3>电子设备，能不用就不用</h3>\n</div>\n<p>那么，如果你家宝宝过了一岁半，就可以放心地让他玩手机了吗？那我可要很认真地警告你：当然不是！首先，电子设备伤害宝宝视力。因为小孩子的视觉系统还没有发育完全，对颜色的处理虽然在一岁前就发育得差不多了，但追踪物体、深度视觉等能力，还远远没有成熟。如果这时候你放纵孩子玩各种电子设备，对他们的视觉影响很大。</p>\n<figure><figcaption></figcaption></figure>\n<h2>2. 🧠 大脑成长不是靠屏幕</h2>\n<p>婴幼儿的学习，靠的不是看动画片，而是靠五感：摸、闻、听、看、尝等来一步步感知这个世界的。</p>\n<p>电子屏幕虽然五光十色，孩子却只能坐着看、被动接收，很少有动手、动脑的空间。这就像让孩子吃“信息罐头”，吃得饱但营养不够。而且，<strong>长期沉浸在这种单一刺激中，大脑的神经连接也难以得到充分锻炼。</strong>——这就是<strong>神经可塑性原理</strong>。</p>\n<div style=\"text-align:center\">\n<h3>💡延伸知识：什么是神经可塑性？</h3>\n</div>\n<p>简单说，大脑像一块“会重塑的橡皮泥”，能根据经验和环境重组自己。而在儿童时期，这种重塑能力最强。</p>\n<ul>\n<li>如果孩子多动手、动脑，就能不断增强神经连接，提升各项能力；</li>\n<li>反过来，若长时间只接收单调输入，脑部发展可能变得单一、迟缓。</li>\n</ul>\n<h2>3. 👫 “真人互动”才是关键营养素</h2>\n<p>也有人反驳着说，现在电子设备升级速度快，不再是以前的单向输出了，交互性越来越强，甚至能“教东西”，这样能给孩子带来的好处也变多了。这话当然没错，现在的电子产品确实越来越智能了，用户也可以跟它交互，甚至跟其他玩家或者智能聊天机器人一起互动。</p>\n<p>可你要知道，这些都不是面对面的交流。</p>\n<div style=\"text-align:center\">\n<p><strong>再高级的程序，也替代不了人类面对面交流的学习。</strong></p>\n</div>\n<p><s>孩子从和大人、同龄人面对面互动中，才能真正学会“怎么沟通”、“怎么表达情绪”、“怎么解决冲突”。这些社交技能，在电子屏幕上是学不到的。</s></p>\n<p>因为人脑最擅长从面对面的人际交互中学习，包括学习怎么识别别人的情绪和意图，怎么恰当地与人交流而不产生冲突，怎么在冲突中调节自己的情绪。这些都不是在电子设备中可以学习过来的。如果不跟真人多交流，就会影响到孩子社会交往的能力，这样危害就大了。<strong>所以你一定要多让孩子和真人互动，而不是和机器互动。</strong></p>\n<h2>4. 🍱生活才是最好的“教育场”</h2>\n<p>不光是真人互动，现实生活中的交流超过电子设备的好处。比如在现实中，你陪孩子玩游戏、给他读故事、带他去旅行，这就是在复杂环境中给孩子各种感官刺激，来促进他们形成思考。这样做确实比较耗时耗力，但是这样才符合宝宝的认知发展规律。屏幕上的动画片再好看，也不如我们在日常生活中陪孩子爬山、玩游戏、跳舞、打球，这才是促使孩子全面发展的最有效的方法。</p>\n<div style=\"text-align:center\">\n<p>（省字版：你带孩子爬山、搭积木、讲故事，看似简单，却提供了复杂丰富的感官刺激。与之相比，屏幕上的卡通片，哪怕再精彩，也比不上一次真实的户外游戏。）</p>\n</div>\n<p><strong>我总结一下，大原则就是电子设备，能不让孩子玩就尽量不让他玩。</strong> 电子屏幕后面对应的是一个虚拟环境，这个虚拟环境的刺激是有限的，是被特意设计成吸引人的注意力的，而真实环境能提供给孩子更多更丰富的刺激，特别是和真人的互动中得到的刺激。（省字版：✋能不看屏幕就别看，现实生活才是成长的主战场。）</p>\n<div style=\"text-align:center\">\n<h3>《悦创的家庭教育宝典》查询结果：</h3>\n<h4>限定时间、限定场景、提供替代方案</h4>\n</div>\n<p>电子设备光靠躲，是躲不过去的。你肯定也有体会，孩子经常不停地要求玩手机、玩 iPad。你要限制他玩电子设备，到底要怎么限制呢？</p>\n<p>躲是躲不过的，我们要的是“管理”。我在这里给你三点建议：<strong>第一，限定时间；第二，限定场景；第三，提供替代方案。</strong></p>\n<h3>1. 限定时间</h3>\n<p><strong>这个很好理解，就是每次看屏幕的时间不准超过多少分钟</strong>。这个时间限制因人而异，大原则是越短越好。比如：你要严格限制孩子玩电子设备的时间，以前是 5 分钟，到了 5 岁之后，可以给她延长到了 10 分钟，但不能再多了。时间一到，就要求她休息，保护她的视力。从小就要让她知道，并且这个规则要在家里实行很长时间，让小孩养成习惯，只要时间到了，她就乖乖地放下电子设备去玩其他东西。</p>\n<p>小孩是没有多少自制力的，所以你帮他严格遵守规则，也是培养他自制力的好机会。所以，规则定下来之后，千万不能纵容。有的家长为了省事，直接把 iPad 给小孩，让他们安静地待一边去玩，在我家是不可能的。这是家长偷懒的行为，绝对地不提倡。</p>\n<p>除了每次观看的时间外，每天的总时间也要限定。我在这儿给你介绍一下美国儿科学会的推荐规定，一个是我刚才说的，一岁半以下的宝宝应该禁止使用任何电子设备，除非是跟家人的视频通话。（这个我也会禁止 3 岁前视频通话）那么对于两岁以上儿童，每天使用电子设备的时间，总共也不要超过一小时。在我家，其实规定还要再严格一点，我不让我女儿每天使用电子设备的总时间超过半小时。</p>\n<p><strong>简单要点：</strong></p>\n<ul>\n<li>看多久？——越短越好。</li>\n<li>一岁半以前，最好完全不看；</li>\n<li>两岁以上，每天别超过一小时（我家更严格：半小时）；</li>\n<li>看完就得停，不讲价。</li>\n</ul>\n<p>这不仅保护视力，也是培养自控力的好机会。</p>\n<h3>2. 限定场景</h3>\n<p>这是什么意思呢？就是说很多情况下完全不允许使用电子产品。比如说吃饭，我不允许孩子在吃饭的时候看手机。有些家长带孩子出去，跟朋友一起吃饭，大家在一起聊天，孩子觉得无聊，要缠大人了，很多人在这个时候就会拿出手机，把孩子打发到一边去。那我推荐的做法是，给她准备一个小玩具或者涂鸦本，让她可以玩一玩，写写画画，也不给她手机玩。在餐桌上，大家既不许看电视，也不许看手机，就是一家人一边吃饭，一边轻松地聊聊天，互相说说当天的事情，这才是孩子应该有的家庭生活，也是她了解自己的家庭的好时候。</p>\n<p>还有一个场景是睡觉，在睡觉前的一小时里，我不许女儿玩电子设备。因为电子屏幕发出来的光线，跟自然的太阳光不一样，<strong>会抑制人体内褪黑激素的分泌</strong>。褪黑激素是干什么的呢？是可以帮助人睡眠的。所以，孩子晚上接触过电子设备的话，睡眠时间就会变短。所以睡觉前我是绝对不允许孩子接触电子设备的。</p>\n<p>当然，这些其实也是对我们大人的要求，就是我们大人自己，在吃饭的时候，或者在哄宝宝入睡的时候，也不能看手机。这也就是我一直提倡的，育儿育己。你想要让孩子远离电子设备，那你至少要在孩子面前先远离电子设备。所以，在我家里，我设了几个“无电子设备区”，还有孩子的房间，也是“无电子设备区”。我会在她的房间里多放些绘本，多放些书。这就是从空间上、从场景上来限制孩子使用电子设备。</p>\n<p><strong>简单要点：</strong></p>\n<ul>\n<li>吃饭不看；</li>\n<li>睡前一小时不看；</li>\n<li>家里设置“无电子区”（比如孩子房间、餐桌）。</li>\n</ul>\n<p>孩子不是听你说教就能改，而是会模仿你怎么做。如果你边吃饭边刷短视频，他当然也想拿手机！</p>\n<h3>3. 为电子设备提供替代品</h3>\n<p>这是最难的一条，但也是最有用的一条。电子设备到底对孩子有多大危害？这个问题的关键，恐怕不是他几岁开始看电子屏幕，而是你在他生活中的角色。你在生活中有没有给他提供其他更好的刺激？如果生活中有其他更好玩的事情，就算给他玩手机，他也不会沉溺于其中。</p>\n<p>相反，如果你平时也不陪他玩，不带他爬山、踢球、逛博物馆，不培养他比较健康的爱好，那就算你禁止他看手机到小学毕业，到他上中学的时候，忽然接触到电脑，你猜会怎样？肯定立刻是上网成瘾啊！所以，电子设备本身不是问题，最根本的问题，还是你能不能在生活中给孩子提供一个更加健康的环境。</p>\n<p>咱们做家长的，其实要有意识地跟电子设备竞争。我们跟孩子好好玩，带孩子痛快地玩，让快乐充满孩子的内心，那他也就不需要到电子设备里去寻找满足感了。</p>\n<p>最好的方法，就是运动，尤其是户外运动。运动能让人产生多巴胺，也就是大脑里的“快乐因子”。无论是跟孩子打球、爬山，还是随便疯跑，都会让他快乐起来。在户外运动中接触大自然，能给孩子大脑各种丰富的刺激，促进他大脑发展，还能保护孩子的视力。</p>\n<p>还有一些电子游戏，吸引孩子是因为里面有社交功能，那你该怎么办？你可以邀请孩子的好朋友过来一起玩，跟孩子一边玩一边互动。或者你也可以找一些亲子桌面游戏跟孩子玩，因为桌面游戏既有游戏的成分，又有互动社交的成分，而且又没有电子屏幕的坏处，而是跟真人、实物在现实世界里互动，所以好处很多。关于桌面游戏，我在后面还会专门再讲一下。所以，你可以让孩子的朋友来一起玩，或者你自己跟孩子玩桌面游戏，因为孩子喜欢的关键是社交，电子游戏只是社交功能的载体，如果你能在现实生活中满足他的这个需求，他就不需要到电子游戏里去寻找了。</p>\n<p>当然，听到这里，我猜你可能还是有个疑问：“好吧，我限制孩子使用电子设备，但也不是绝对不让他用啊。那么，在他可以使用电子设备的那半个小时、一个小时内，怎么样用电子设备最好呢？”关于这个问题，里面也大有学问，由于时间关系，咱们就之后再讲了。</p>\n<p><strong>悦创的小提醒：</strong></p>\n<p>陪伴孩子成长的过程，也是你自我提升的过程。在孩子还不能自我控制前，你一定要身体力行，一方面在孩子面前要少使用电子设备，另一方面，从根本上说，你自己也可以减少对电子设备的依赖。</p>\n<p>比如说，我刚才提到的限制场景的两条原则，吃饭时不用手机，不看手机看看书，你能不能先做到呢？只要你能以身作则，那你要孩子远离电子设备，也就轻松得很了。</p>\n<blockquote>\n<p><strong>省字版：</strong></p>\n<p>你不能只让孩子不看屏幕，还得让他有更好玩的事做！陪他画画、做手工、搭乐高、讲故事……这些才是长期有效的替代方案。</p>\n<p>别忘了，电子设备最吸引人的地方其实是“社交感”。如果你能陪孩子玩亲子桌游、叫小伙伴来家里玩，他自然就不会沉迷在游戏世界里。</p>\n</blockquote>\n<h2>5. 🌿总结：别让屏幕代替了爱</h2>\n<p>育儿不是“看好”孩子，而是“陪着”孩子。</p>\n<p>当然，我们都不完美，忙碌、烦躁、疲惫，都会让我们想“借助一下电子设备”。但我们可以设定原则、限制场景、并努力营造更多有趣的生活内容。</p>\n<p>在我家，iPad 不是禁忌，但也从不成为默认选项。只有在例如长途旅行等极特殊的情况下才会启用。</p>\n<div style=\"text-align:center\">\n<p><strong>孩子的成长，需要的是你，而不是一块屏幕。</strong></p>\n</div>\n<h2>6. 🎓悦创补充小课堂：什么是神经可塑性？</h2>\n<p>神经可塑性，简单理解就是：</p>\n<blockquote>\n<p>大脑可以通过“练习+体验”，不断优化自己的神经连接，就像代码可以持续更新优化一样。</p>\n</blockquote>\n<p>它分成三种形式：</p>\n<ol>\n<li><strong>突触可塑性</strong>：常用的连接更强，不用的就退化（用进废退）；</li>\n<li><strong>功能可塑性</strong>：大脑可以把某个区域的功能“搬家”到别处，比如中风康复；</li>\n<li><strong>结构可塑性</strong>：新突触、新神经元会在学习中生成，尤其是在儿童阶段。</li>\n</ol>\n<p><strong>注意</strong>：大脑也会因为坏习惯产生“负塑性”。比如，长期沉迷电子设备，就可能削弱专注力和自我控制力。</p>\n<p>📍最后一句话送给你：</p>\n<blockquote>\n<p>管孩子用电子产品，最终是为了让他更自由，而不是更依赖。</p>\n</blockquote>\n<p>你就是孩子成长过程中最好的“操作系统”。</p>\n<details class=\"hint-container details\"><summary>公众号：AI悦创【二维码】</summary>\n<figure><img src=\"/gzh.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n</details>\n<div class=\"hint-container info\">\n<p class=\"hint-container-title\">AI悦创·编程一对一</p>\n<p>AI悦创·推出辅导班啦，包括「Python 语言辅导班、C++ 辅导班、java 辅导班、算法/数据结构辅导班、少儿编程、pygame 游戏开发、Web、Linux」，招收学员面向国内外，国外占 80%。全部都是一对一教学：一对一辅导 + 一对一答疑 + 布置作业 + 项目实践等。当然，还有线下线上摄影课程、Photoshop、Premiere 一对一教学、QQ、微信在线，随时响应！微信：Jiabcdefh</p>\n<p>C++ 信息奥赛题解，长期更新！长期招收一对一中小学信息奥赛集训，莆田、厦门地区有机会线下上门，其他地区线上。微信：Jiabcdefh</p>\n<p>方法一：<a href=\"http://wpa.qq.com/msgrd?v=3&amp;uin=1432803776&amp;site=qq&amp;menu=yes\" target=\"_blank\" rel=\"noopener noreferrer\">QQ</a></p>\n<p>方法二：微信：Jiabcdefh</p>\n</div>\n<figure><img src=\"/zsxq.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n",
      "date_published": "2025-06-21T15:08:55.000Z",
      "date_modified": "2025-07-07T08:34:16.000Z",
      "authors": [
        {
          "name": "AI悦创"
        }
      ],
      "tags": []
    },
    {
      "title": "00-让你的孩子享受前沿的脑科学研究成果",
      "url": "https://bornforthis.cn/Yuechuangs-Family-EducationHandbook/00.html",
      "id": "https://bornforthis.cn/Yuechuangs-Family-EducationHandbook/00.html",
      "summary": "养孩子难过当程序员 你的儿女，其实不是你的儿女。你们是弓，你们的孩子是从弦上发出的生命的箭矢。 👨‍💻你好，我是悦创。 一个程序员 + 编程私教 + 教育研究者 👶最近，我又多了一个新身份——奶爸！ 说实话，写程序、带学生、调大模型，我都不怕。但当我第一次抱起自己的孩子，我忽然意识到： 🚀 世界上最复杂的系统，不是火箭，不是操作系统，而是——孩...",
      "content_html": "<div style=\"text-align:center\">\n<p><strong>养孩子难过当程序员</strong></p>\n<p><strong>你的儿女，其实不是你的儿女。你们是弓，你们的孩子是从弦上发出的生命的箭矢。</strong></p>\n</div>\n<p>👨‍💻你好，我是悦创。</p>\n<p>一个程序员 + 编程私教 + 教育研究者</p>\n<p>👶最近，我又多了一个新身份——奶爸！</p>\n<p>说实话，写程序、带学生、调大模型，我都不怕。但当我第一次抱起自己的孩子，我忽然意识到：</p>\n<blockquote>\n<p>🚀 世界上最复杂的系统，不是火箭，不是操作系统，而是——孩子的大脑。</p>\n</blockquote>\n<h2>1. 🧩为什么说“养娃”比造火箭还难？</h2>\n<p>🛠️火箭、汽车有图纸、有标准、出错了还能复盘；</p>\n<p>👶孩子没有图纸、没有统一标准，而且没有“重来”的机会！</p>\n<p>更让人抓狂的是：</p>\n<blockquote>\n<p>👶孩子呢？没有标准答案，没有回头路。你只能“实时编程”，边做边调试，还没有 Debug 工具…</p>\n</blockquote>\n<p>孩子每一天都在变化，变量无穷无尽。你想复制“成功经验”？不好意思，不一定能复现。</p>\n<h2>2. 📚我啃了几十本育儿书，结果……</h2>\n<p>坦白说，越看越迷茫。</p>\n<p>🔎很多育儿书还在用几十年前的理论；</p>\n<p>🎭还有一些，干脆是“商家包装的伪科学”。</p>\n<p>是打着“科学”旗号的营销套路，比如：</p>\n<ul>\n<li>\n<p>❌“左右脑分工训练”？</p>\n<ul>\n<li>✅真相：大脑是协作工作的整体，不存在左脑右脑分开练。</li>\n</ul>\n</li>\n<li>\n<p>❌“关键期错过就完了”？</p>\n<ul>\n<li>✅其实，科学说的是“敏感期”，而且时间跨度比你想的长得多。（时间没有那么死板）</li>\n</ul>\n</li>\n</ul>\n<p>总结一句话：<strong>不是你育儿方式不行，而是你参考的内容早就过时了。</strong></p>\n<h2>3. 🛠️那我该怎么办？</h2>\n<p>既然找不到靠谱答案，程序员的直觉告诉我：不如程序员的方式，自己做一套科学、系统的育儿“方法论”！</p>\n<p>于是，我和一群热爱学习、追求科学的爸妈们开始了一场“家庭教育重构计划”——</p>\n<p>📡用最新的脑科学、认知心理学、儿童发展研究，🧠翻译成每个家长都能听懂、用得上的“人话版本”。</p>\n<h2>4. 📘《悦创的家庭教育宝典》正式上线！</h2>\n<p>这一年，我将与你分享科学育儿的<strong>五大“脑力系统”</strong>：</p>\n<p>| 模块     | 包含能力                     |<br>\n|</p>\n",
      "image": "https://bornforthis.cn/gzh.jpg",
      "date_published": "2025-06-09T16:53:27.000Z",
      "date_modified": "2025-06-21T08:05:22.000Z",
      "authors": [
        {
          "name": "AI悦创"
        }
      ],
      "tags": []
    },
    {
      "title": "01-🐍 使用 Python 调用 Ollama 本地大模型 API 完整教程",
      "url": "https://bornforthis.cn/column/Python-Programming-Course/P05-AI-large-model/docs/01-ollama-api.html",
      "id": "https://bornforthis.cn/column/Python-Programming-Course/P05-AI-large-model/docs/01-ollama-api.html",
      "summary": "你好，我是悦创。 以下是完整的 Python 使用 Ollama API 教程文档，涵盖了所有主要接口，包括调用示例、参数解释、可选项设置、结构化输出、模型管理等内容，不做任何省略，方便你后续整理、出版或集成使用。 本文详细介绍如何使用 Python 通过 HTTP 请求方式调用 Ollama 的本地大语言模型，包括文本生成、对话、嵌入、模型管理等功能...",
      "content_html": "<p>你好，我是悦创。</p>\n<p>以下是<strong>完整的 Python 使用 Ollama API 教程文档</strong>，涵盖了所有主要接口，包括调用示例、参数解释、可选项设置、结构化输出、模型管理等内容，不做任何省略，方便你后续整理、出版或集成使用。</p>\n<blockquote>\n<p>本文详细介绍如何使用 Python 通过 HTTP 请求方式调用 <a href=\"https://ollama.com/\" target=\"_blank\" rel=\"noopener noreferrer\">Ollama</a> 的本地大语言模型，包括文本生成、对话、嵌入、模型管理等功能。</p>\n</blockquote>\n<h2>📦 1. 环境准备</h2>\n<p>确保你已完成以下环境配置：</p>\n<ol>\n<li>\n<p>✅ 安装并运行 Ollama（访问 <a href=\"https://ollama.com/\" target=\"_blank\" rel=\"noopener noreferrer\">ollama.com</a>）</p>\n</li>\n<li>\n<p>✅ 拉取至少一个模型（如 llama3）：</p>\n<div class=\"language-bash line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"bash\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-bash\"><span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">ollama</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> pull</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> llama3</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div></div></div></li>\n<li>\n<p>✅ 安装 Python 库：</p>\n<div class=\"language-bash line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"bash\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-bash\"><span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">pip</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> install</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> requests</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div></div></div></li>\n</ol>\n<h2>📘 2. 文本生成接口：<code>/api/generate</code></h2>\n<p>用于传入 prompt，生成文本回答，可流式或一次性返回。</p>\n<h3>✅ 2.1 基本调用（非流式）</h3>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">import</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> requests</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">url </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> \"http://localhost:11434/api/generate\"</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">payload </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    \"model\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"llama3\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    \"prompt\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"Why is the sky blue?\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    \"stream\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">False</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">}</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">res </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> requests.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">post</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(url, </span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">json</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">payload)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(res.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">json</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()[</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"response\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">])</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><h3>⚙️ 2.2 可选参数说明</h3>\n<p>| 参数名    | 类型       | 描述                                |<br>\n|</p>\n",
      "image": "https://bornforthis.cn/gzh.jpg",
      "date_published": "2025-06-01T14:13:30.000Z",
      "date_modified": "2025-06-05T07:30:47.000Z",
      "authors": [
        {
          "name": "AI悦创"
        }
      ],
      "tags": []
    },
    {
      "title": "《炉石传说》",
      "url": "https://bornforthis.cn/blog/2025/5month/LisaPiza.html",
      "id": "https://bornforthis.cn/blog/2025/5month/LisaPiza.html",
      "summary": "IntroductionHearthstone is a strategy card game developed by Blizzard Entertainment. In this assignment, you will be implementing a text based game (very) loosely based on this ...",
      "content_html": "<p>Introduction<a href=\"https://hearthstone.blizzard.com/en-us\" target=\"_blank\" rel=\"noopener noreferrer\">Hearthstone</a> is a strategy card game developed by Blizzard Entertainment. In this assignment, you will be implementing a text based game (very) loosely based on this title. Note that where the behaviour of the original game differs from this specification, this specification takes precedence, and you should implement the assignment as per it. In our version of Hearthstone, the player is a Hero tasked with defeating an enemy computer controlled Hero. Heroes battle by casting spells represented by cards which they draw from their personal card decks. These spells can summon minions to fight for their summoner, or directly attack (or defend) a Hero or minion.Getting StartedDownload <code>a2.zip</code> from Blackboard. This archive contains the necessary files to start your assignment. Once extracted, the <code>a2.zip</code> archive will provide the following files:* <code>a2.py</code>: <em>This is the only file you will submit</em> and is where you write your code. <em>Do not</em> make changes to any other files.</p>\n<ul>\n<li><code>support.py</code>: <em>Do not modify or submit this file</em>, it contains pre-defined constants to use in your assignment. In addition to these, you are encouraged to create your own constants in <code>a2.py</code> where possible.</li>\n<li><code>display.py</code>: <em>Do not modify or submit this file</em>, it contains view classes to display your assignment in a visually appealing manner.</li>\n<li><code>gameplay/</code>: This folder contains a number of example outputs generated by playing the game using a fully-functional completed solution to this assignment. The purpose of the files in this folder is to help you understand how the game works, and how output should be formatted.</li>\n<li><code>levels/</code>: This folder contains a small collection of files used to initialize games of HearthStone. In addition to these, you are encouraged to create your own files to help test your implementation where possible.</li>\n</ul>\n<p>GameplayThis section provides a high-level overview of gameplay, and is intended to provide you with an idea of the behaviour of a fully completed assignment. Where interactions are not explicitly mentioned in this section, please see the <a href=\"https://csse1001.github.io/2025s1/a2#implementaion\" target=\"_blank\" rel=\"noopener noreferrer\">Implementation section</a>.ImportantDo not simply implement the behaviour described here using your own structure; you <em>must</em> implement the individual functions, classes, and methods described in the <a href=\"https://csse1001.github.io/2025s1/a2#implementaion\" target=\"_blank\" rel=\"noopener noreferrer\">Implementation section</a>. Inputs and outputs must match <em>exactly</em> what is expected. Refer to the Implementation section, the given examples, and the provided <a href=\"https://csse1001.github.io/2025s1/a2#assignment-submission\" target=\"_blank\" rel=\"noopener noreferrer\">Gradescope tests</a> for clarification on required prompts and outputs.The game focusses on conflict between Two <em>heroes</em>, one controlled by the player, and one controlled by the computer. Heroes are a type of <em>entity</em>. All entities have a health and shield value. These values can be depleted by receiving <em>damage</em>. If an entity has a positive shield value, then its health cannot be depleted in this way. An entity is <em>alive</em> while its health value is above zero; it is <em>defeated</em> when its health drops to zero.Heroes also possess an <em>energy</em> level. Energy is a currency used to perform actions. A hero’s energy cannot exceed that hero’s <em>energy capacity</em>. Which is a value that gradually increases as the game progresses. Actions in Hearthstone are represented by <em>cards</em>. Heroes possess a <em>deck</em> of cards from which they draw into a <em>hand</em>. Cards can then be <em>played</em> from the hero’s hand in order to perform actions. In addition to the regular entity rules, a hero is also defeated if its deck contains zero cards. Heroes take turns playing cards, and at the start of a turn a hero draws from the <em>top</em> of their deck until their hand is <em>full</em> (that is contains the maximum number of cards). A hero can hold a maximum of 5 cards in their hand. Each hero can play any number of cards on their <a href=\"http://turn.In\" target=\"_blank\" rel=\"noopener noreferrer\">turn.In</a> addition to a name and description, all cards have a <em>cost</em> and an <em>effect</em>. A cards cost is the energy that a hero must spend in order to play it. If a hero does not have enough energy to spend, it cannot play a given card. Instead of playing a card normally, a hero can choose to discard a given card. This moves the card from their hand to the <em>bottom</em> of their deck. A cards effect is what happens when that card is played. The types of effect are given in <a href=\"https://csse1001.github.io/2025s1/a2#tbl-effects\" target=\"_blank\" rel=\"noopener noreferrer\">Table 1</a>.Table 1: Types of effect. A card may have zero, one or multiple effect types.</p>\n<p>| Effect | Impact on target entity                                      |<br>\n|</p>\n",
      "image": "https://bornforthis.cn/gzh.jpg",
      "date_published": "2025-05-28T19:10:07.000Z",
      "date_modified": "2025-05-31T01:21:56.000Z",
      "authors": [
        {
          "name": "AI悦创"
        }
      ],
      "tags": []
    },
    {
      "title": "12-炒海带丝",
      "url": "https://bornforthis.cn/column/cookdinner/P02-%E5%87%89%E8%8F%9C%E5%B0%8F%E7%82%92/12-%E7%82%92%E6%B5%B7%E5%B8%A6%E4%B8%9D.html",
      "id": "https://bornforthis.cn/column/cookdinner/P02-%E5%87%89%E8%8F%9C%E5%B0%8F%E7%82%92/12-%E7%82%92%E6%B5%B7%E5%B8%A6%E4%B8%9D.html",
      "summary": "㊙️海带丝这样做香辣过瘾，干完3碗米饭😹 🌟嗨，今天看到菜场的海带丝感觉新鲜不错，两块💰买了一小袋，回到家随便一烧，没想到我家人都快哭了😭，太下饭了，这个夏天已经好久没这么开胃过了🤣，迫不及待的赶紧要分享给你们，收好咯～ ❣️食材：海带丝一把，大蒜4瓣，小米辣2个，小葱2颗，豆瓣酱1勺 1⃣️：锅里倒半锅水放海带丝煮开，喜欢软一点可以再煮两分...",
      "content_html": "<div style=\"text-align:center\">\n<p>㊙️海带丝这样做香辣过瘾，干完3碗米饭😹</p>\n</div>\n<p>🌟嗨，今天看到菜场的海带丝感觉新鲜不错，两块💰买了一小袋，回到家随便一烧，没想到我家人都快哭了😭，太下饭了，这个夏天已经好久没这么开胃过了🤣，迫不及待的赶紧要分享给你们，收好咯～</p>\n<p>❣️食材：海带丝一把，大蒜4瓣，小米辣2个，小葱2颗，豆瓣酱1勺</p>\n<p>1⃣️：锅里倒半锅水放海带丝煮开，喜欢软一点可以再煮两分钟，然后捞出。</p>\n<p>2⃣️：大蒜切成蒜末，小米辣也切碎。</p>\n<p>3⃣️：锅里倒适量油，放蒜末和辣椒碎翻炒出香味，再加入一勺豆瓣酱翻炒出红油，加入两勺生抽，一小勺食盐，一小勺白糖，一勺蚝油翻炒均匀。</p>\n<p>4⃣️：放入海带丝，加葱花翻拌均匀就可以了。</p>\n<p>🌈巨巨巨香，最后的汤汁拌米饭巨好吃，不好吃来找我😹</p>\n",
      "image": "https://bornforthis.cn/gzh.jpg",
      "date_published": "2025-05-27T17:28:00.000Z",
      "date_modified": "2025-05-27T09:33:42.000Z",
      "authors": [
        {
          "name": "AI悦创"
        }
      ],
      "tags": []
    },
    {
      "title": "06-虎皮凤爪",
      "url": "https://bornforthis.cn/column/cookdinner/P01-%E8%8D%A4%E8%8F%9C%E7%B1%BB/04-%E9%85%B1%E9%A6%99%E7%94%9C%E5%8F%A3%E7%B1%BB/06-%E8%99%8E%E7%9A%AE%E5%87%A4%E7%88%AA.html",
      "id": "https://bornforthis.cn/column/cookdinner/P01-%E8%8D%A4%E8%8F%9C%E7%B1%BB/04-%E9%85%B1%E9%A6%99%E7%94%9C%E5%8F%A3%E7%B1%BB/06-%E8%99%8E%E7%9A%AE%E5%87%A4%E7%88%AA.html",
      "summary": "公众号：AI悦创【二维码】 AI悦创·编程一对一 AI悦创·推出辅导班啦，包括「Python 语言辅导班、C++ 辅导班、java 辅导班、算法/数据结构辅导班、少儿编程、pygame 游戏开发、Web、Linux」，招收学员面向国内外，国外占 80%。全部都是一对一教学：一对一辅导 + 一对一答疑 + 布置作业 + 项目实践等。当然，还有线下线上摄影...",
      "content_html": "\n",
      "image": "https://bornforthis.cn/gzh.jpg",
      "date_published": "2025-05-26T21:12:21.000Z",
      "date_modified": "2025-06-06T00:38:34.000Z",
      "authors": [
        {
          "name": "AI悦创"
        }
      ],
      "tags": []
    },
    {
      "title": "03-如何快速识别一段 Python 代码是不是 AI 写的？",
      "url": "https://bornforthis.cn/blog/%E5%85%AC%E4%BC%97%E5%8F%B7%E7%B3%BB%E5%88%97%E6%96%87%E7%AB%A0/2025%E5%B9%B4/03-simple-ways-to-tell-if-python-code-was-written-by-an-llm.html",
      "id": "https://bornforthis.cn/blog/%E5%85%AC%E4%BC%97%E5%8F%B7%E7%B3%BB%E5%88%97%E6%96%87%E7%AB%A0/2025%E5%B9%B4/03-simple-ways-to-tell-if-python-code-was-written-by-an-llm.html",
      "summary": "你好，我是悦创。 作为一名数据科学和数学的教学者，其实我并不介意学生使用 ChatGPT 这样的 LLM（大语言模型），前提是他们把它当作学习过程中的辅助工具，而不是学习的替代品。加州理工学院（Caltech）对申请者撰写入学文书时的 AI 使用指南，启发了我为自己的编程和机器学习课程制定了一套 AI 使用规范： 哪些是 Caltech 所认为的不道德...",
      "content_html": "<figure><figcaption></figcaption></figure>\n<p>你好，我是悦创。</p>\n<p>作为一名数据科学和数学的教学者，其实我并不介意学生使用 ChatGPT 这样的 LLM（大语言模型），前提是他们把它当作学习过程中的辅助工具，而不是学习的替代品。<a href=\"https://www.admissions.caltech.edu/apply/first-year-applicants/supplemental-application-essays/ethical-use-of-ai-guidelines-for-fall-2025-applicants\" target=\"_blank\" rel=\"noopener noreferrer\">加州理工学院（Caltech）</a>对申请者撰写入学文书时的 AI 使用指南，启发了我为自己的编程和机器学习课程制定了一套 AI 使用规范：</p>\n<blockquote>\n<p><strong>哪些是 Caltech 所认为的不道德的 AI 使用方式？</strong></p>\n<ul>\n<li>直接复制粘贴 AI 生成的内容；</li>\n<li>依赖 AI 来构思或草拟整篇文章；</li>\n<li>用 AI 内容取代你原本独特的语气和风格；</li>\n<li><s>翻译一篇你用其他语言写好的文章</s> 翻译用另一种语言写的文章；</li>\n</ul>\n<p><strong>哪些是合理且道德的 AI 使用方式？</strong></p>\n<ul>\n<li>使用 Grammarly 或 Microsoft Editor 等 AI 工具检查语法与拼写</li>\n<li>用 AI 提问或生成练习题以启动头脑风暴过程</li>\n<li>利用 AI 研究大学申请流程</li>\n</ul>\n<p><strong>如果你还不确定你的 AI 使用是否合适，不妨这样问自己：你会请一个值得信任的成年人帮你完成这件事吗？换句话说：你会让 ChatGPT 做的事情，同样让一个成年人帮你做吗？如果你觉得不妥，那就是不合适的！</strong></p>\n<p>比如，请老师帮你检查语法和拼写？完全没问题。</p>\n<p>可如果是让老师帮你写好草稿，你稍作修改就提交？那就不合适了。</p>\n</blockquote>\n<p>话虽如此，最近我收到了一些学生提交的代码，实在是太明显、太彻底地“AI 味”十足了。因此，我整理了一份“AI 代码征的清单”，列出了一些容易识别出 AI 生成代码的特征。当然，辨别人写的代码和 AI 写的代码每天都在变得更困难。但目前还是能找到一些共同点，尤其是出现在 ChatGPT、Claude、DeepSeek 生成的代码中——这些共同点是立即需要警惕的危险信号。</p>\n<h2>一、注释风格</h2>\n<p>我当然希望所有学生都能像 ChatGPT 一样写出详尽的注释——但现实是，他们做不到。</p>\n<p>🚩 <strong>过度详细的注释</strong>，或<strong>风格怪异的注释</strong>，可能意味着是 AI 写的。</p>\n<p>比如，DeepSeek 很喜欢用三引号 <code>\"\"\"</code> 写多行注释，即使那根本不是真正的 docstring，也没有标明参数或返回值：</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> find_squares_adding_to_zero</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">mod</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    \"\"\"Find two non-zero numbers a and b such that a^2 + b^2 ≡ 0 mod n.\"\"\"</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> a </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> range</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, mod):  </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># Start from 1 to exclude a = 0</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> b </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> range</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(a, mod):  </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># Start from a to avoid redundant pairs</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">            if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> (a</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">**</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> +</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> b</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">**</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">) </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">%</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> mod </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">==</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">                return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> (a, b)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    return</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> None</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>这种注释方式我觉得非常不自然，因为在我的课堂上我们讲的是用 <code>#</code> 来做单行注释，而 <code>\"\"\"</code> 是专门用于 docstring 的。</p>\n<p>另外，如果在注释中出现像“<code>≡</code>”这样的特殊字符，也可能是 AI 写的。除非我打算让很多人看到这段代码，不然我自己写代码时几乎不会特地去找这些符号——我相信学生们也一样。</p>\n<h2>二、Lambda 表达式</h2>\n<p>别误会，我本人很喜欢 lambda 表达式，也认为它们是 Python 的一项精巧设计。不过，lambda 的本意是写一些临时、一次性的小函数，比如传入 <code>map()</code>、<code>filter()</code>、<code>sorted()</code> 这种函数中。</p>\n<p>🚩 <strong>如果 lambda 被用错了、滥用了（缺乏周到的设计），或出现在学习进度尚未涉及的时候，就很可能是 AI 写的。</strong></p>\n<p>比如，如果在我们还没系统学习 lambda 的时候，学生交上这样一段代码，我很容易就能闻出 ChatGPT 的味道：</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">from</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> functools </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">import</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> lru_cache</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">fib </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> (</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">lambda</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> f</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: (</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">lambda</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> x</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: </span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">f</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(f, x)))(</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">lambda</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">n</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: </span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    n </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> n </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&lt;</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 2</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> else</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\"> self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, n</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">) </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\"> self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, n</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">))</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># Generate the first 10 Fibonacci numbers</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">fib_sequence </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> [</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">fib</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(n) </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> n </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> range</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">10</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(fib_sequence)</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>这段代码太复杂、太“反自然”，不像一个初学者能自然写出来的，特别是把<strong>递归逻辑硬塞进 lambda 表达式中</strong>，明显是 AI 的风格。</p>\n<h2>三、库的使用方式</h2>\n<p><strong>库导入的位置问题</strong></p>\n<p>🚩 如果库的 <code>import</code> 没写在文件开头，而是“散落”在代码中某处，这可能是 AI 写的。</p>\n<p>虽然这种情况我只遇到过几次，但如果你课堂上强调过“所有导入要放在文件开头”，那看到这种代码就要警觉。</p>\n<p><strong>使用的库本身</strong></p>\n<p>🚩 使用一个没有必要的库，尤其是还没在课堂中讲到的库，也可能是 AI 参与的痕迹。</p>\n<p>还是看之前那段 lambda 代码：</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">from</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> functools </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">import</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> lru_cache</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div></div></div><p>如果你还没讲过 <code>functools</code> 模块，那学生可能是用 ChatGPT 或谷歌找到的。使用这些工具发现库本身并没有错，但确实提示了我们：“AI 介入”的可能性。</p>\n<h2>四、命名与格式不一致「具有争议的标准」</h2>\n<p>这个问题就比较直观了，如果你布置作业时明确写了某个变量或字段的名字，但学生交上来的代码却用了一堆“规范但不符合你的要求”的变量名——那很可能是 AI 写的。</p>\n<p>比如这段代码是求小于 n 的所有素数，变量命名都非常标准：</p>\n<div class=\"language-python line-numbers-mode has-collapsed-lines collapsed\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--vp-collapsed-lines:15;--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> sieve_of_eratosthenes</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">limit</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    \"\"\"Return a list of all prime numbers less than the given limit.\"\"\"</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> limit </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&lt;=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> []</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">    # Initialize a boolean array to track prime numbers</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    is_prime </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">True</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">] </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">*</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> limit</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    is_prime[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">] </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> is_prime[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">] </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> False</span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">  # 0 and 1 are not primes</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> num </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> range</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">int</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(limit</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">**</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0.5</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">) </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> is_prime[num]:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">            # Mark multiples of num as non-prime</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">            for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> multiple </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> range</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(num </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">*</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> num, limit, num):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">                is_prime[multiple] </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> False</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">    # Collect all prime numbers</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    primes </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> [num </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> num, prime </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> enumerate</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(is_prime) </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> prime]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> primes</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># Example usage</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">limit </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 50</span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">  # Change this value to find primes less than a different number</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">primes </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> sieve_of_eratosthenes</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(limit)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">f</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"Primes less than </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">{</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">limit</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">}</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">: </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">{</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">primes</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">}</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div><div class=\"collapsed-lines\"></div></div><p>普通学生可能会使用描述性较差的变量名和函数名，而我自己的写法可能会直接用 <code>n</code> 代替 <code>limit</code>，函数名也会用 <code>prime_finder()</code> 而不是 <code>sieve_of_eratosthenes()</code> 这么长。虽然不能完全凭这点就断定是 AI 写的，但如果结合其他“特征”，就更有可能了。</p>\n<p>注意：这里是针对初学者，如果是老手的程序员或者想要精进，这种命名方法是推荐的。</p>\n<h2>五、逻辑错误</h2>\n<p>最明显的信号，当然是逻辑错误。但要区分是学生的水平不够，还是 AI 理解出了问题，其实很难。</p>\n<p>LLM 本质上是基于概率建模的系统，它们根据上下文生成“可能合理”的下一个词或代码块，而不是“真正理解”问题。这导致它们在处理需要严密推理或逻辑严谨的问题时，经常会出现错误。比如：索引出错、不处理边界情况、算错结果等等。</p>\n<p>🚩 <strong>如果代码中存在不符合逻辑的错误，尤其是算法推导出错，那就很可能是 AI 写的。</strong></p>\n<p>理想情况下，认真负责任的学生会在交作业前检查并修复这些问题。但现实是，很多学生交上来的代码根本跑不通，甚至直接报错。</p>\n<h2>六、最后一点建议</h2>\n<p>我们很难用一套“绝对规则”来判断一段代码是不是 AI 写的，所以我建议大家在教学时以“探索式”的态度去沟通，而不是质疑或指责。如果我怀疑某位学生对 AI 依赖过度，我可能会请他在白板上现场讲讲解决思路，或者让他解释自己写的代码是怎么来的。</p>\n<p>只要给予适当的引导和信任，我们是可以培养出能善用 AI 的未来专业人才的 —— 把 AI 当作工具，而不是拐杖。</p>\n<p>你有没有发现过类似的“AI痕迹”？欢迎一起交流。</p>\n<p>哦对，还可以让学生使用 github 进行开发跟踪！</p>\n\n<details class=\"hint-container details\"><summary>详情</summary>\n<h2>Ethics and AI at Caltech</h2>\n<h5><a class=\"header-anchor\" href=\"#all-fall-2025-applicants-will-be-asked-to-review-caltech-s-guidelines-on-the-ethical-use-of-ai-before-submitting-their-supplemental-essays\"><span><em>All Fall 2025 applicants will be asked to review Caltech's guidelines on the ethical use of AI before submitting their</em> </span></a><a href=\"https://www.admissions.caltech.edu/apply/first-year-applicants/supplemental-application-essays\" target=\"_blank\" rel=\"noopener noreferrer\"><em>supplemental essays</em></a><em>.</em></h5>\n<p><a href=\"https://scienceexchange.caltech.edu/topics/artificial-intelligence-research\" target=\"_blank\" rel=\"noopener noreferrer\">Artificial Intelligence</a> (AI) research at Caltech is groundbreaking, and Caltech students will encounter AI in a wide range of interdisciplinary applications.</p>\n<p>Since 2018, Caltech's <a href=\"https://www.ai4science.caltech.edu/\" target=\"_blank\" rel=\"noopener noreferrer\">AI4Science</a> (or <em>Artificial Intelligence for Science</em>) Initiative has provided training and access to modern AI tools so researchers across a wide range of disciplines, from economics to astrophysics, can harness the power of AI. In 2023, Caltech established the <a href=\"https://lindeinstitute.caltech.edu/research/csspp\" target=\"_blank\" rel=\"noopener noreferrer\">Center for Science, Society, and Public Policy</a> to examine the intersection of science and society, facilitate discussion of scientific ethics, and help shape public science policy.</p>\n<p>The Caltech community cares deeply about the ethical and social implications of AI technology, and this starts with the ethical use of AI by our applicants to Caltech undergraduate and graduate degree programs.</p>\n<p>The Undergraduate Faculty Admissions and Graduate Studies committees convened and have approved of the following ethical guidelines for the use of AI in the Fall 2025 application cycle. As access to AI continues to grow and the technology evolves, so will our recommendations and expectations for future application cycles.</p>\n<h3>Ethical Use of AI: Guidelines for Fall 2025 Applicants</h3>\n<p>Your essays are where we hear <strong>your voice.</strong> Relying on AI, specifically large language models such as ChatGPT or Bard, to craft your essay will dilute your unique expression and perspective. While we know AI tools have become readily accessible over recent months, overuse of AI will diminish your individual, bold, creative identity as a prospective Techer.</p>\n<p>What are some examples of <strong>unethical</strong> uses of AI for Caltech admissions essays?</p>\n<ul>\n<li>Copying and pasting directly from an AI generator</li>\n<li>Relying on AI generated content to outline or draft an essay</li>\n<li>Replacing your unique voice and tone with AI generated content</li>\n<li>Translating an essay written in another language</li>\n</ul>\n<p>What are some examples of <strong>ethical</strong> uses of AI for Caltech admissions essays?</p>\n<ul>\n<li>Using AI tools, like Grammarly or Microsoft Editor, to review grammar and spelling of your completed essays</li>\n<li>Generating questions or exercises to help kick start the brainstorming process</li>\n<li>Using AI to research the college application process</li>\n</ul>\n<p><strong>If you are still wondering whether your use of AI in crafting your application is ethical, ask yourself whether it would be ethical to have a trusted adult perform the same task you are asking of ChatGPT.</strong> Would a teacher be able to review your essay for grammatical and spelling errors? Of course! Would that same teacher write a draft of an essay for you to tweak and then submit? Definitely not.</p>\n<p>Above all else, remember to be <strong>authentic to yourself</strong> when writing your essays. Our Caltech supplemental questions are designed to spark your curiosity, to make you think deeply about whether you see yourself as a Techer, and to jumpstart your creativity – don't let a reliance on AI tools take that opportunity from you!</p>\n<p><em>Caltech students, faculty, and staff are guided by the</em> <a href=\"https://www.admissions.caltech.edu/why-caltech/student-life/honor-code\" target=\"_blank\" rel=\"noopener noreferrer\"><em>Honor Code</em></a> <em>and policies of AI use as an academic tool by students will be determined by individual departments and/or individual faculty.</em></p>\n<h3>We are curious, just like you! Which is why we are asking the following question to Fall 2025 applicants.</h3>\n<p>Did you receive any AI generated assistance in the preparation of your application materials?</p>\n<p><em>Please note, this information is confidential and will not be used in our review of your application. Answers to this question will</em> <em>never</em> <em>be used against a student. Caltech admissions readers will never have access to this information at any point in our review; in fact, we will not access this information until May 2025, after all admissions decisions have been made and the class of 2029 is finalized. We are simply curious about the use of AI in the admissions process.</em></p>\n</details>\n<details class=\"hint-container details\"><summary>公众号：AI悦创【二维码】</summary>\n<figure><img src=\"/gzh.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n</details>\n<div class=\"hint-container info\">\n<p class=\"hint-container-title\">AI悦创·编程一对一</p>\n<p>AI悦创·推出辅导班啦，包括「Python 语言辅导班、C++ 辅导班、java 辅导班、算法/数据结构辅导班、少儿编程、pygame 游戏开发、Web、Linux」，招收学员面向国内外，国外占 80%。全部都是一对一教学：一对一辅导 + 一对一答疑 + 布置作业 + 项目实践等。当然，还有线下线上摄影课程、Photoshop、Premiere 一对一教学、QQ、微信在线，随时响应！微信：Jiabcdefh</p>\n<p>C++ 信息奥赛题解，长期更新！长期招收一对一中小学信息奥赛集训，莆田、厦门地区有机会线下上门，其他地区线上。微信：Jiabcdefh</p>\n<p>方法一：<a href=\"http://wpa.qq.com/msgrd?v=3&amp;uin=1432803776&amp;site=qq&amp;menu=yes\" target=\"_blank\" rel=\"noopener noreferrer\">QQ</a></p>\n<p>方法二：微信：Jiabcdefh</p>\n</div>\n<figure><img src=\"/zsxq.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n",
      "date_published": "2025-05-25T22:45:34.000Z",
      "date_modified": "2025-05-31T00:56:38.000Z",
      "authors": [
        {
          "name": "AI悦创"
        }
      ],
      "tags": []
    },
    {
      "title": "Simple Ways to Tell if Python Code Was Written by an LLM",
      "url": "https://bornforthis.cn/blog/2025/Other/24-simple-ways-to-tell-if-python-code-was-written-by-an-llm.html",
      "id": "https://bornforthis.cn/blog/2025/Other/24-simple-ways-to-tell-if-python-code-was-written-by-an-llm.html",
      "summary": "As a data science and math instructor, I actually don’t mind if my students use LLMs like ChatGPT, as long as it’s supplementing their learning process and not detracting from i...",
      "content_html": "<figure><figcaption></figcaption></figure>\n<p>As a data science and math instructor, I actually don’t mind if my students use LLMs like ChatGPT, as long as it’s supplementing their learning process and not detracting from it. The <a href=\"https://www.admissions.caltech.edu/apply/first-year-applicants/supplemental-application-essays/ethical-use-of-ai-guidelines-for-fall-2025-applicants\" target=\"_blank\" rel=\"noopener noreferrer\">Caltech admissions essay guidelines</a> inspired my AI policy for my programming and machine learning classes:</p>\n<blockquote>\n<p>What are some examples of <strong>unethical</strong> uses of AI for Caltech admissions essays?</p>\n<ul>\n<li>\n<p>Copying and pasting directly from an AI generator</p>\n</li>\n<li>\n<p>Relying on AI generated content to outline or draft an essay</p>\n</li>\n<li>\n<p>Replacing your unique voice and tone with AI generated content</p>\n</li>\n<li>\n<p>Translating an essay written in another language</p>\n</li>\n</ul>\n<p>What are some examples of <strong>ethical</strong> uses of AI for Caltech admissions essays?</p>\n<ul>\n<li>\n<p>Using AI tools, like Grammarly or Microsoft Editor, to review grammar and spelling of your completed essays</p>\n</li>\n<li>\n<p>Generating questions or exercises to help kick start the brainstorming process</p>\n</li>\n<li>\n<p>Using AI to research the college application process</p>\n</li>\n</ul>\n<p><strong>If you are still wondering whether your use of AI […] is ethical, ask yourself whether it would be ethical to have a trusted adult perform the same task you are asking of ChatGPT.</strong> Would a teacher be able to review your essay for grammatical and spelling errors? Of course! Would that same teacher write a draft of an essay for you to tweak and then submit? Definitely not.</p>\n</blockquote>\n<p>That said, I’ve been getting some code submissions lately that are so obviously and completely AI-generated that I’ve had to put together my own compilation of AI omens. Of course, differentiating between human-generated and AI-generated code is getting more difficult every day. Still, there are some commonalities between ChatGPT/Claude/DeepSeek AI-generated code that are immediate red flags.</p>\n<h2>Comments</h2>\n<p>Do I wish that all my students commented as thoroughly as ChatGPT does? Absolutely. Do they? Definitely not.</p>\n<p>🚩 Overly detailed commenting or odd commenting styles can indicate AI use.</p>\n<p>For instance, when using DeepSeek, you’ll see a docstring with three quotation marks as a instead of a comment using the standard pound (<code>#</code>), even though the docstring does not specify the arguments or the return values:</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> find_squares_adding_to_zero</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">mod</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    \"\"\"Find two non-zero numbers a and b such that a^2 + b^2 ≡ 0 mod n.\"\"\"</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> a </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> range</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, mod):  </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># Start from 1 to exclude a = 0</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> b </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> range</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(a, mod):  </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># Start from a to avoid redundant pairs</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">            if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> (a</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">**</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> +</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> b</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">**</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">) </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">%</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> mod </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">==</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">                return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> (a, b)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    return</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> None</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>I find this to be an unnatural and odd way of commenting a single line, particularly given the context that I teach single-line comments in Python using #, and this is not proper docstring formatting.</p>\n<p>Special characters in comments can also be an indicator of AI-generated code. Unless I’m writing something I know will be seen by many people, I probably wouldn’t put the effort into finding characters like “<code>≡</code>” just for a comment. I’d wager my students feel the same way.</p>\n<h2>Lambda Expressions</h2>\n<p>Don’t get me wrong — I love lambda expressions and consider them a unique and valuable feature of Python. I see them as compact, throwaway functions meant to be created and passed directly as arguments to other functions. When used properly, they shine in situations where you need to pass a simple, one-off function to another function, like in <code>map()</code>, <code>filter()</code>, or <code>sorted()</code>. That said, lambda expressions can be a red flag when overused, applied incorrectly, or introduced prematurely.</p>\n<p>🚩 The misuse of lambda expressions demonstrates a lack of thoughtful design or an overreliance on AI.</p>\n<p>For instance, if I got the following code submission before we’ve gone in depth on lambda expressions, and for a task such as this, I’d sniff out the ChatGPT use immediately:</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">from</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> functools </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">import</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> lru_cache</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">fib </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> (</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">lambda</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> f</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: (</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">lambda</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> x</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: </span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">f</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(f, x)))(</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">lambda</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">n</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: </span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    n </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> n </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&lt;</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 2</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> else</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\"> self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, n</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">) </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\"> self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, n</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">))</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># Generate the first 10 Fibonacci numbers</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">fib_sequence </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> [</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">fib</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(n) </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> n </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> range</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">10</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(fib_sequence)</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>This is clearly a problem not well-suited to a lambda expression and is too complex for students to get to naturally and on their own in a first Python course.</p>\n<h2>Libraries</h2>\n<p><strong>Placement of Library Imports</strong></p>\n<p>🚩 On occasion, LLMs will place library imports in weird places (places other than the top of the file).</p>\n<p>I’ve only seen this happen a few times, but particularly if you’ve emphasized to students that library imports should go at the beginning or in one place all together, this should seem fishy.</p>\n<p><strong>What Libraries Are In-Use:</strong></p>\n<p>🚩 Using a library to execute a task that doesn’t necessarily require it can indicate AI use, particularly if it’s a library that isn’t common or hasn’t yet been introduced.</p>\n<p>Let’s revisit the lambda expression code from above:</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">from</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> functools </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">import</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> lru_cache</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">fib </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> (</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">lambda</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> f</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: (</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">lambda</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> x</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: </span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">f</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(f, x)))(</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">lambda</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">n</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: </span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    n </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> n </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&lt;</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 2</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> else</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\"> self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, n</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">) </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\"> self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, n</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">))</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># Generate the first 10 Fibonacci numbers</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">fib_sequence </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> [</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">fib</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(n) </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> n </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> range</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">10</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(fib_sequence)</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>If you haven’t introduced the functools library, a student very likely could have found out about it by using either Google or an LLM. There’s nothing wrong with discovering libraries using these tools, but it could tip you off to their specific implementation being AI-generated as well.</p>\n<h2>Naming and Formatting Inconsistencies</h2>\n<p>This one speaks for itself. If you have an assignment where a field or variable name is something specific, AI-generated code will generalize it to a variable name that feels more explanatory but less natural. For instance, in the following code to find all primes less than a given number n, the average student would likely have less descriptive variable and function names:</p>\n<div class=\"language-python line-numbers-mode has-collapsed-lines collapsed\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--vp-collapsed-lines:15;--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> sieve_of_eratosthenes</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">limit</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    \"\"\"Return a list of all prime numbers less than the given limit.\"\"\"</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> limit </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&lt;=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> []</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">    # Initialize a boolean array to track prime numbers</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    is_prime </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">True</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">] </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">*</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> limit</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    is_prime[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">] </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> is_prime[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">] </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> False</span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">  # 0 and 1 are not primes</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> num </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> range</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">int</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(limit</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">**</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0.5</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">) </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> is_prime[num]:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">            # Mark multiples of num as non-prime</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">            for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> multiple </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> range</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(num </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">*</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> num, limit, num):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">                is_prime[multiple] </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> False</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">    # Collect all prime numbers</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    primes </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> [num </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> num, prime </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> enumerate</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(is_prime) </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> prime]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> primes</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># Example usage</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">limit </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 50</span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">  # Change this value to find primes less than a different number</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">primes </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> sieve_of_eratosthenes</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(limit)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">f</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"Primes less than </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">{</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">limit</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">}</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">: </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">{</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">primes</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">}</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div><div class=\"collapsed-lines\"></div></div><p>I would likely use “n” instead of “limit” or just “prime_finder” instead of “sieve_of_eratosthenes”. That said, particularly detail-oriented students might be wrongly accused of AI use under this rule, so I mainly consider this AI-generated code when combined with some of the other red flags provided in this article.</p>\n<h2>Incorrect Logic</h2>\n<p>Logical errors are the most obvious red flag of all, on paper. In practice, it’s more difficult to tell — how can you determine if a language model made a logical mistake or if a student just didn’t quite get it?</p>\n<p>At their core, LLMs are statistical models designed to predict the likelihood of the next token (such as a word, letter, or subword unit) based on patterns learned from their training data. While they excel at generating coherent and contextually relevant text, they lack true understanding, reasoning, or algorithmic thinking. This limitation often leads to errors in tasks requiring precise logic, like solving math problems or generating code. An LLM might produce plausible-sounding but incorrect solutions or fail to follow complex logical sequences. For example, I’ve seen LLMs struggle with indexing in mathematical applications, not address edge cases, and provide outright incorrect results.</p>\n<p>🚩 If the code contains errors in logic or errors in reasoning, it could be AI-generated.</p>\n<p>Ideally, a diligent student would carefully review and correct such errors before submission. However, in practice, this step is often overlooked; I’ve gotten code submissions that produce incorrect outputs or don’t even run in the first place.</p>\n<p>As a disclaimer, it’s difficult to create hard and fast rules for telling if code is AI-generated, so I’d recommend approaching students with curiosity instead of accusation. If I believe a student is using AI to an unhealthy extent, I may ask them to have a whiteboard coding session on a related problem or ask about their intuition behind their solution. With the right support and attention to detail, I hope we can build up future professionals who use AI as a tool and not a crutch.</p>\n<p>What are some LLM red flags you’ve noticed?</p>\n<details class=\"hint-container details\"><summary>公众号：AI悦创【二维码】</summary>\n<figure><img src=\"/gzh.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n</details>\n<div class=\"hint-container info\">\n<p class=\"hint-container-title\">AI悦创·编程一对一</p>\n<p>AI悦创·推出辅导班啦，包括「Python 语言辅导班、C++ 辅导班、java 辅导班、算法/数据结构辅导班、少儿编程、pygame 游戏开发、Web、Linux」，招收学员面向国内外，国外占 80%。全部都是一对一教学：一对一辅导 + 一对一答疑 + 布置作业 + 项目实践等。当然，还有线下线上摄影课程、Photoshop、Premiere 一对一教学、QQ、微信在线，随时响应！微信：Jiabcdefh</p>\n<p>C++ 信息奥赛题解，长期更新！长期招收一对一中小学信息奥赛集训，莆田、厦门地区有机会线下上门，其他地区线上。微信：Jiabcdefh</p>\n<p>方法一：<a href=\"http://wpa.qq.com/msgrd?v=3&amp;uin=1432803776&amp;site=qq&amp;menu=yes\" target=\"_blank\" rel=\"noopener noreferrer\">QQ</a></p>\n<p>方法二：微信：Jiabcdefh</p>\n</div>\n<figure><img src=\"/zsxq.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n<p><a href=\"https://medium.com/science-spectrum/simple-ways-to-tell-if-python-code-was-written-by-an-llm-ce51f16a78cd\" target=\"_blank\" rel=\"noopener noreferrer\">.</a></p>\n",
      "date_published": "2025-05-23T22:26:42.000Z",
      "date_modified": "2025-05-25T02:28:09.000Z",
      "authors": [
        {
          "name": "AI悦创"
        }
      ],
      "tags": []
    },
    {
      "title": "豌豆射手",
      "url": "https://bornforthis.cn/blog/2025/5month/java-exam.html",
      "id": "https://bornforthis.cn/blog/2025/5month/java-exam.html",
      "summary": "云计算学院专业一《Java基础》 第三周周考技能试卷 考试须知 考试须知： 试卷满分 100分; 理论及技能试卷考试时间共计3小时30分钟，请合理安排考试时间; 开考前2分钟，开始录屏，同时开启录音，摄像头窗口放在屏幕的左上角，录屏需要清晰看到面部表情 无录屏者一律按0分处理，必须是完整的考试录屏(只有单独录效果录屏按0分处理)，录屏过程中不允许有暂停...",
      "content_html": "<div style=\"text-align:center\">\n<h3>云计算学院专业一《Java基础》</h3>\n<p><strong>第三周周考技能试卷</strong></p>\n</div>\n<details class=\"hint-container details\"><summary>考试须知</summary>\n<p>考试须知：</p>\n<ol>\n<li>试卷满分 100分;</li>\n<li>理论及技能试卷考试时间共计3小时30分钟，请合理安排考试时间;</li>\n<li>开考前2分钟，开始录屏，同时开启录音，摄像头窗口放在屏幕的左上角，录屏需要清晰看到面部表情</li>\n<li>无录屏者一律按0分处理，必须是完整的考试录屏(只有单独录效果录屏按0分处理)，录屏过程中不允许有暂停行为，否则按考试作弊处理</li>\n<li>桌面必须有自己的学院、班级、姓名</li>\n<li>试卷收发完毕，关闭与考试无关软件，不允许使用编辑器，否则按作弊处理</li>\n<li>技能题目必须新建项目，不允许在旧项目上实现 (违反者一律0分)</li>\n<li>考试过程中，认真审题，按时答题，严禁作弊，请独立答题，有任何问题请举手示意</li>\n<li>考试完成后将笔试与机试文档存入U 盘一并上交，U 盘中只允许有自己考试的项目，否则按零分处理;</li>\n<li>不可百度搜索代码，不可查看资料、源代码;</li>\n<li>保存试卷和视频文件均为:学院+班级+姓名+周考/月考。</li>\n</ol>\n</details>\n<h2>1. 技能题(100分)</h2>\n<ol>\n<li>\n<p>模拟植物大战僵尸角色完成下列功能；</p>\n</li>\n<li>\n<p>完成循环菜单效果，并且可以对存放角色的数组进行增删改查；</p>\n<div class=\"language-bash line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"bash\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-bash\"><span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">1:添加，2:查询，3:删除，4:退出</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div></div></div></li>\n<li></li>\n</ol>\n<details class=\"hint-container details\"><summary>公众号：AI悦创【二维码】</summary>\n<figure><img src=\"/gzh.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n</details>\n<div class=\"hint-container info\">\n<p class=\"hint-container-title\">AI悦创·编程一对一</p>\n<p>AI悦创·推出辅导班啦，包括「Python 语言辅导班、C++ 辅导班、java 辅导班、算法/数据结构辅导班、少儿编程、pygame 游戏开发、Web、Linux」，招收学员面向国内外，国外占 80%。全部都是一对一教学：一对一辅导 + 一对一答疑 + 布置作业 + 项目实践等。当然，还有线下线上摄影课程、Photoshop、Premiere 一对一教学、QQ、微信在线，随时响应！微信：Jiabcdefh</p>\n<p>C++ 信息奥赛题解，长期更新！长期招收一对一中小学信息奥赛集训，莆田、厦门地区有机会线下上门，其他地区线上。微信：Jiabcdefh</p>\n<p>方法一：<a href=\"http://wpa.qq.com/msgrd?v=3&amp;uin=1432803776&amp;site=qq&amp;menu=yes\" target=\"_blank\" rel=\"noopener noreferrer\">QQ</a></p>\n<p>方法二：微信：Jiabcdefh</p>\n</div>\n<figure><img src=\"/zsxq.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n",
      "image": "https://bornforthis.cn/gzh.jpg",
      "date_published": "2025-05-22T17:21:10.000Z",
      "date_modified": "2025-05-22T10:42:07.000Z",
      "authors": [
        {
          "name": "AI悦创"
        }
      ],
      "tags": []
    },
    {
      "title": "AI is exposing the many flaws of the broken education system",
      "url": "https://bornforthis.cn/blog/2025/Other/23-ai-exposed-education-system-flaws.html",
      "id": "https://bornforthis.cn/blog/2025/Other/23-ai-exposed-education-system-flaws.html",
      "summary": "AI tools are showing us just how broken the education system really is. There was an article I saw recently talking about the damning AI double standard in education… Teachers a...",
      "content_html": "<figure><figcaption></figcaption></figure>\n<p>AI tools are showing us just how broken the education system really is.</p>\n<p>There was an article I saw recently talking about the damning AI double standard in education…</p>\n<p>Teachers are using AI to grade school papers and prepare learning plans — yet they’re banning students from using it.</p>\n<p>ChatGPT getting banned in schools and universities tells you everything you need to know about the education system.</p>\n<p><strong>School doesn’t prepare anyone for the real world.</strong></p>\n<p>If they did then none of these tools clearly used in the real-world would be banned.</p>\n<p>All most schools do is feed you with unnecessary or esoteric knowledge you wouldn’t need to use in the vast majority of cases.</p>\n<p>In university they box you into a cage of specialization to meet the requirements for a job.</p>\n<p>And for most of the jobs, you didn’t even need to know half of the things they made you learn to get the certificate.</p>\n<p>Assignments and exams for the most part only test how much you can recall information.</p>\n<figure><figcaption></figcaption></figure>\n<p>They test your memory retrieval ability. They don’t test your thinking process.</p>\n<p>They don’t test how sharp your mental models for solving problems are.</p>\n<p>So of course if they allowed AI tools like ChatGPT, everyone would get a perfect score in every exam.</p>\n<p>Because all the knowledge is already out there.</p>\n<p>Actually, AI is making it pretty clear that <strong>assignments and exams shouldn’t even really exist</strong>.</p>\n<p>If school was really about learning, then the focus would be on personalized, hands-on, interactive practice.</p>\n<p>It wouldn’t be about knowing the “right” answers and getting a terrible grade if you don’t.</p>\n<p>Grades wouldn’t even be a thing, at least in their current form.</p>\n<p>School wouldn’t be about getting the correct solution if you want to “pass”, it would be about <strong>becoming someone</strong> who can solve problems — especially big picture problems that really matter in life — or at least <strong>should</strong> really matter.</p>\n<p>And using powerful tools to help us solve the problems even easier and faster.</p>\n<p>And what if AI could eventually solve the problem entirely without us even having to think about it?</p>\n<p>Would it be so wrong to have AI “think” for us, especially for irrelevant problems we’d rather not handle ourselves?</p>\n<p>Relatively boring, repetitive problems?</p>\n<p>Problems that already have well-established and predictable methods for solving them that today’s AI’s could easily internalize and replicate.</p>\n<p>Problems like coding, for the most part.</p>\n<p>But sadly most schools mainly exist to take your money and produce certified knowledge warehouses.</p>\n<p>They’re not about big-picture, original thinking or the pursuit of happiness.</p>\n<p>Too idealistic, right?</p>\n<details class=\"hint-container details\"><summary>公众号：AI悦创【二维码】</summary>\n<figure><img src=\"/gzh.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n</details>\n<div class=\"hint-container info\">\n<p class=\"hint-container-title\">AI悦创·编程一对一</p>\n<p>AI悦创·推出辅导班啦，包括「Python 语言辅导班、C++ 辅导班、java 辅导班、算法/数据结构辅导班、少儿编程、pygame 游戏开发、Web、Linux」，招收学员面向国内外，国外占 80%。全部都是一对一教学：一对一辅导 + 一对一答疑 + 布置作业 + 项目实践等。当然，还有线下线上摄影课程、Photoshop、Premiere 一对一教学、QQ、微信在线，随时响应！微信：Jiabcdefh</p>\n<p>C++ 信息奥赛题解，长期更新！长期招收一对一中小学信息奥赛集训，莆田、厦门地区有机会线下上门，其他地区线上。微信：Jiabcdefh</p>\n<p>方法一：<a href=\"http://wpa.qq.com/msgrd?v=3&amp;uin=1432803776&amp;site=qq&amp;menu=yes\" target=\"_blank\" rel=\"noopener noreferrer\">QQ</a></p>\n<p>方法二：微信：Jiabcdefh</p>\n</div>\n<figure><img src=\"/zsxq.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n<p><a href=\"https://medium.com/coding-beauty/ai-exposed-education-system-flaws-7fa5e5934bb5\" target=\"_blank\" rel=\"noopener noreferrer\">.</a></p>\n",
      "date_published": "2025-05-22T13:20:27.000Z",
      "date_modified": "2025-05-22T05:38:36.000Z",
      "authors": [
        {
          "name": "AI悦创"
        }
      ],
      "tags": []
    },
    {
      "title": "02-人工智能暴露了教育体系的诸多缺陷",
      "url": "https://bornforthis.cn/blog/%E5%85%AC%E4%BC%97%E5%8F%B7%E7%B3%BB%E5%88%97%E6%96%87%E7%AB%A0/2025%E5%B9%B4/02-ai-exposed-education-system-flaws.html",
      "id": "https://bornforthis.cn/blog/%E5%85%AC%E4%BC%97%E5%8F%B7%E7%B3%BB%E5%88%97%E6%96%87%E7%AB%A0/2025%E5%B9%B4/02-ai-exposed-education-system-flaws.html",
      "summary": "人工智能工具向我们展示了教育系统的真正缺陷。 我最近看到一篇文章，讨论了教育领域中令人发指的人工智能双重标准…… 教师们正在使用人工智能来批改试卷和制定学习计划——但他们却禁止学生使用它。 学校和大学封杀 ChatGPT，这就已经足够说明当前教育体系的问题。 学校并不能帮助任何人做好面对现实世界的准备。 如果他们这样做了，那么现实世界中明显使用的这些工...",
      "content_html": "<figure><figcaption></figcaption></figure>\n<p><strong>人工智能工具向我们展示了教育系统的真正缺陷。</strong></p>\n<p>我最近看到一篇文章，讨论了教育领域中令人发指的人工智能双重标准……</p>\n<p><s>老师们在用 AI 批改作业、制定教学计划 —— 可与此同时，他们却禁止学生使用它。</s></p>\n<p>教师们正在使用人工智能来批改试卷和制定学习计划——但他们却禁止学生使用它。</p>\n<p>学校和大学封杀 ChatGPT，这就已经足够说明当前教育体系的问题。</p>\n<p><s>学校根本没有为现实世界做好准备。</s></p>\n<p><strong>学校并不能帮助任何人做好面对现实世界的准备。</strong></p>\n<p>如果他们这样做了，那么现实世界中明显使用的这些工具就不会被禁止。</p>\n<p>大多数学校所做的就是向你灌输大多数情况下你不需要使用的不必要或深奥的知识。</p>\n<p>大学更是把你框进一座“专业化”的牢笼，只为了满足某份工作的学历门槛。</p>\n<p>而实际上，那些工作根本不需要用到你学过的一半知识，就足已胜任。</p>\n<p>作业和考试大部分只是测试你能回忆多少信息。（也就是在考你能记住多少东西）</p>\n<figure><figcaption></figcaption></figure>\n<p><strong>它们只是在测试你的记忆提取能力，而不是你的思维过程</strong>。换句话说：检查你的记忆力，以及你对于记忆力中数据的检索能力，并不是真正考察你的思考过程！</p>\n<p>他们不会考察你解决问题的思维模型是否足够敏锐。</p>\n<p>所以，如果允许使用 ChatGPT 这样的 AI 工具，每个人的考试分数当然都会满分。</p>\n<p>他们不会考察你解决问题的思维模型是否足够敏锐。</p>\n<p>因此，如果他们允许使用 ChatGPT 等人工智能工具，那么每个人在每次作业、考试中都会获得满分。</p>\n<p>因为所需的知识早已唾手可得，获取答案的成本在 AI 时代下，逐步降低！</p>\n<p>实际上，AI 已经让我们看清：<strong>作业和考试可能根本就不应该存在。</strong></p>\n<p>如果学校真的以“学习”为本，那重点就该放在个性化、实践性强、交互式的学习上。</p>\n<p>而不是去追求所谓的“标准答案”，然后因为错了一道题就被打个很差的分数。</p>\n<p>成绩，至少以现在这种形式，是不应该存在的。或者委婉的说：在目前的形势下成绩根本不算什么。</p>\n<p>“通过考试”不该意味着你要得出“标准答案”，而应该是：你要成为一个能真正解决问题的人 —— 特别是那些在生活中真正重要的大问题，或者<strong>本该</strong>重要的问题。</p>\n<p>并且善于运用强大的工具，使我们更高效、更容易的解决问题。</p>\n<p>如果有一天 AI 可以彻底替我们解决这些问题 —— 甚至无需我们亲自动脑，那又怎样？</p>\n<p><s>让 AI 为我们“思考”那些我们本来就不想自己动脑的问题，真的有错吗？</s></p>\n<p>让人工智能为我们“思考”难道有什么错吗，尤其是对于我们自己不愿意处理的无关问题？比如，那些重复、无聊、机械的问题呢？</p>\n<p>那些已经有成熟解决方案、AI 完全可以掌握和复现的问题呢？</p>\n<p>大多数情况下，问题类似于编码。不过注意，这里还是要强调：<strong>AI 工具本身就是一个双刃剑，还要学习的！学习，你才拥有判断 AI 回答的正确与否。不过，这个学习和以往不同～</strong></p>\n<p><s>比如说编程 —— 在很大程度上就是这样的问题。</s></p>\n<p>但遗憾的是，大多数学校的存在目的，只是为了从你身上赚钱，并生产一批又一批“持证的知识仓库”。</p>\n<p>它们根本不关心你是否具备<strong>大局观</strong>、是否具备<strong>原创性思维</strong>，甚至<strong>不关心你是否快乐</strong>。</p>\n<p>太理想主义了吗？</p>\n<p><strong>这只猫（人工智能）永远不会再回到袋子里，我们需要懂得如何善用它的人。</strong></p>\n<p>要有自己的思想，自己的批判性思维，一切都可以解决！</p>\n<details class=\"hint-container details\"><summary>公众号：AI悦创【二维码】</summary>\n<figure><img src=\"/gzh.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n</details>\n<div class=\"hint-container info\">\n<p class=\"hint-container-title\">AI悦创·编程一对一</p>\n<p>AI悦创·推出辅导班啦，包括「Python 语言辅导班、C++ 辅导班、java 辅导班、算法/数据结构辅导班、少儿编程、pygame 游戏开发、Web、Linux」，招收学员面向国内外，国外占 80%。全部都是一对一教学：一对一辅导 + 一对一答疑 + 布置作业 + 项目实践等。当然，还有线下线上摄影课程、Photoshop、Premiere 一对一教学、QQ、微信在线，随时响应！微信：Jiabcdefh</p>\n<p>C++ 信息奥赛题解，长期更新！长期招收一对一中小学信息奥赛集训，莆田、厦门地区有机会线下上门，其他地区线上。微信：Jiabcdefh</p>\n<p>方法一：<a href=\"http://wpa.qq.com/msgrd?v=3&amp;uin=1432803776&amp;site=qq&amp;menu=yes\" target=\"_blank\" rel=\"noopener noreferrer\">QQ</a></p>\n<p>方法二：微信：Jiabcdefh</p>\n</div>\n<figure><img src=\"/zsxq.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n",
      "date_published": "2025-05-22T13:28:08.000Z",
      "date_modified": "2025-05-22T12:59:47.000Z",
      "authors": [
        {
          "name": "AI悦创"
        }
      ],
      "tags": []
    },
    {
      "title": "01-谷歌刚刚确认了许多程序员拼命否认的 AI 现实",
      "url": "https://bornforthis.cn/blog/%E5%85%AC%E4%BC%97%E5%8F%B7%E7%B3%BB%E5%88%97%E6%96%87%E7%AB%A0/2025%E5%B9%B4/01-ai-writes-google-codebase.html",
      "id": "https://bornforthis.cn/blog/%E5%85%AC%E4%BC%97%E5%8F%B7%E7%B3%BB%E5%88%97%E6%96%87%E7%AB%A0/2025%E5%B9%B4/01-ai-writes-google-codebase.html",
      "summary": "你好，我是悦创。 AI 正在悄悄接管编程工作，但许多程序员仍然对即将到来的变化视而不见…… 现在，谷歌的首席科学家透露了一个令人深思的事实：AI 现在已经生成了他们至少 25% 的代码。 AI 现在已经生成了谷歌 25% 的代码AI 现在已经生成了谷歌 25% 的代码 你能看见吗？这正在全球最顶尖的软件公司中发生，而这些公司拥有数十亿行活跃代码。 然而...",
      "content_html": "<figure><figcaption></figcaption></figure>\n<p>你好，我是悦创。</p>\n<p>AI 正在悄悄接管编程工作，但许多程序员仍然对即将到来的变化视而不见……</p>\n<p>现在，谷歌的首席科学家透露了一个令人深思的事实：<strong>AI 现在已经生成了他们至少 25% 的代码</strong>。</p>\n<figure><figcaption>AI 现在已经生成了谷歌 25% 的代码</figcaption></figure>\n<p>你能看见吗？这正在全球最顶尖的软件公司中发生，而这些公司拥有数十亿行活跃代码。</p>\n<p>然而，还有那么多人仍然把 AI 辅助编程当作噱头，认为：<strong>没人真正用它来开发正式产品</strong>。</p>\n<p>甚至有人在我评论区留言说，使用 AI 工具并不会提高效率……</p>\n<p>拜托，我们不是早就一致认为 GitHub Copilot 是个爆款了吗？去年这个时候他们就已经有超过 <strong>130 万付费用户</strong>，这难道还不够说明问题吗？甚至当下火爆的 ChatGPT、DeepSeek，也可以间接的说明一些问题。</p>\n<p>你要知道：<strong>软件开发者本来就是最难变现的群体之一</strong>——如果你能让 130 万开发者付费，那你的工具肯定不简单。</p>\n<p>即使这些用户大部分来自企业端，我也不相信每个 B2B 开发者工具都能达到这个体量。</p>\n<p>我还记得我第一次使用 Copilot 的时候：嗯，不错的工具，建议还可以，不赖……</p>\n<p>可没过几天，当网络出问题我不得不用手码时——我才意识到，我其实已经开始<strong>依赖这个工具</strong>了。我已经习惯了更高质量的开发体验，但自己居然都没发觉。</p>\n<p>那个用于接受补全的 Tab 键 —— 我那几天敲得最多的是 Tab，还是按回车键多？</p>\n<p><strong>以前：</strong></p>\n<ul>\n<li>输入 48 个字符 — 回车</li>\n<li>输入 60 个字符 — 回车</li>\n<li>输入 55 个字符 — 回车</li>\n</ul>\n<p><strong>现在：</strong></p>\n<ul>\n<li>输入 9 个字符 — Tab — 回车</li>\n<li>输入 2 个字符 — Tab — 回车</li>\n<li>直接 Tab — 回车</li>\n</ul>\n<p><strong>生活质量的差距不言而喻，生产力的差距也同样如此。</strong></p>\n<p>这也提醒我们一件事：<strong>编程从来都是“思考”的行为，而不是“打字”的行为</strong>。</p>\n<p>真正耗时间的，始终是<strong>思考</strong>：高层的系统设计，底层的算法和模式设计。打字，只是最后那一小步，其实很机械，很重复。</p>\n<p>所以 Copilot 远不只是个代码补全工具，它是一个<strong>思维预测工具</strong>。</p>\n<p>它不只是帮你更快编码，它是在理解你的想法，然后<strong>消除从思维到实现之间的阻碍</strong>。你只需要按下 Tab，而不用敲几十个字。</p>\n<p>这已经非常实用了，而这还只是<strong>逐行级别</strong>的智能：预测你每一行的想法。</p>\n<p>而现在我们有了更先进的工具，比如 <strong>Supercomplete</strong>，能预测你对<strong>整个文件</strong>的意图，开发体验再次跃升。</p>\n<figure><figcaption></figcaption></figure>\n<p>还有像 <strong>Cursor Compose</strong> 和 <strong>Windsurf Cascade</strong> 这样的工具，能将你的想法扩展到<strong>多个文件</strong>中自动实现。</p>\n<p>它们不断在放大你的想法带来的价值和影响力。</p>\n<p>比如你想为一个 Web 应用添加搜索功能：</p>\n<ul>\n<li><strong>Copilot</strong> 可以为你逐行补全 UI 组件、事件处理器和搜索算法或库的相关代码。</li>\n<li><strong>Supercomplete</strong> 甚至可以为你生成一个空的事件处理函数，等待你定义。</li>\n<li>但更智能的 AI 代理工具，只需你说一句：“给应用添加搜索功能”，它就能处理<strong>上述所有事情</strong>，甚至包括安装 NPM 库。</li>\n</ul>\n<p>那距离你直接说一句“构建并部署一个电商网站”，然后一切自动完成，还会有多远？</p>\n<p>想象一下，你只给出一个模糊的描述，AI 就能主动向你提问，收集详细需求，避免歧义。</p>\n<p>这已经越来越像是“<strong>迟早的事</strong>”，而不是“是否会发生”。</p>\n<p>但如果你还在假装 AI 工具不会彻底改变软件开发的游戏规则 —— 那你很可能会被时代彻底抛下。</p>\n<p>甚至，当下还有 ChatGPT、DeepSeek 作为辅助。如果只是简单的了解，不加以重视很有可能被被时代抛弃。</p>\n<p>请持续关注 AI悦创，会一直带你解锁前沿的思想与技术！</p>\n<details class=\"hint-container details\"><summary>公众号：AI悦创【二维码】</summary>\n<figure><img src=\"/gzh.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n</details>\n<div class=\"hint-container info\">\n<p class=\"hint-container-title\">AI悦创·编程一对一</p>\n<p>AI悦创·推出辅导班啦，包括「Python 语言辅导班、C++ 辅导班、java 辅导班、算法/数据结构辅导班、少儿编程、pygame 游戏开发、Web、Linux」，招收学员面向国内外，国外占 80%。全部都是一对一教学：一对一辅导 + 一对一答疑 + 布置作业 + 项目实践等。当然，还有线下线上摄影课程、Photoshop、Premiere 一对一教学、QQ、微信在线，随时响应！微信：Jiabcdefh</p>\n<p>C++ 信息奥赛题解，长期更新！长期招收一对一中小学信息奥赛集训，莆田、厦门地区有机会线下上门，其他地区线上。微信：Jiabcdefh</p>\n<p>方法一：<a href=\"http://wpa.qq.com/msgrd?v=3&amp;uin=1432803776&amp;site=qq&amp;menu=yes\" target=\"_blank\" rel=\"noopener noreferrer\">QQ</a></p>\n<p>方法二：微信：Jiabcdefh</p>\n</div>\n<figure><img src=\"/zsxq.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n",
      "date_published": "2025-05-21T07:01:29.000Z",
      "date_modified": "2025-05-21T09:56:01.000Z",
      "authors": [
        {
          "name": "AI悦创"
        }
      ],
      "tags": []
    },
    {
      "title": "P03-每日英语单词记忆卡片工具",
      "url": "https://bornforthis.cn/column/Python-Programming-Course/P04-Projects/P03-english-word-memory-tool.html",
      "id": "https://bornforthis.cn/column/Python-Programming-Course/P04-Projects/P03-english-word-memory-tool.html",
      "summary": "1. 作业项目说明：每日英语单词记忆卡片工具 1.1 项目目标 制作一个英语学习小工具，能够每天抽取若干个单词，展示其中英文，支持标记是否掌握，并将未掌握单词记录下来，以便后续复习。 1.2 任务要求 1.2.1 基础功能（必做） 从本地词库文件 word_list.txt 读取若干单词； 随机抽取 5 个单词作为当天学习内容； 每个单词按以下流程交互...",
      "content_html": "<h2>1. 作业项目说明：每日英语单词记忆卡片工具</h2>\n<h3>1.1 项目目标</h3>\n<p>制作一个英语学习小工具，能够每天抽取若干个单词，展示其中英文，支持标记是否掌握，并将未掌握单词记录下来，以便后续复习。</p>\n<h3>1.2 任务要求</h3>\n<h4>1.2.1 基础功能（必做）</h4>\n<ul>\n<li>从本地词库文件 <code>word_list.txt</code> 读取若干单词；</li>\n<li>随机抽取 5 个单词作为当天学习内容；</li>\n<li>每个单词按以下流程交互：\n<ul>\n<li>显示英文；</li>\n<li>用户按下 Enter 查看中文意思；</li>\n<li>提问：“是否记住了？” 记录用户输入；</li>\n</ul>\n</li>\n<li>将“未记住”的单词写入 <code>review_list.txt</code></li>\n</ul>\n<h4>1.2.2 进阶功能（选做）</h4>\n<ul>\n<li>加一个选项：<code>“是否复习未掌握单词？”</code>（读取 <code>review_list.txt</code> 中的词汇）</li>\n<li>显示学习进度（如“今日记住 3 / 5 个单词”）</li>\n<li>使用 <code>datetime</code> 模块记录学习日期</li>\n<li>使用 <code>json</code> 或 <code>csv</code> 存储学习记录（带日期）</li>\n</ul>\n<h3>1.3 文件说明</h3>\n<h4>1.3.1 <code>word_list.txt</code> 示例格式（英文:中文，每行一个）</h4>\n<div class=\"language-text line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"text\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-text\"><span class=\"line\"><span>apple:苹果</span></span>\n<span class=\"line\"><span>book:书</span></span>\n<span class=\"line\"><span>computer:电脑</span></span>\n<span class=\"line\"><span>run:跑</span></span>\n<span class=\"line\"><span>happy:开心</span></span>\n<span class=\"line\"><span>sun:太阳</span></span>\n<span class=\"line\"><span>dog:狗</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><h4>1.3.2 <code>review_list.txt</code> 示例格式</h4>\n<div class=\"language-text line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"text\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-text\"><span class=\"line\"><span>book:书</span></span>\n<span class=\"line\"><span>sun:太阳</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><h3>1.4 参考代码结构建议</h3>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> load_words</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">file_path</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">    ...</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> study_session</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">words</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> count</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">5</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">    ...</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> save_to_review</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">to_review</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> file_path</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">    ...</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> review_words</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">file_path</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">    ...</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> main</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">():</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#D19A66\">    ...</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><h3>1.5 作业提交要求</h3>\n<ol>\n<li>提交 <code>.py</code> 程序源代码（含完整注释）；</li>\n<li>代码提交到为你分配的 Github 仓库并使用 Github 跟踪开发进程；<a href=\"https://github.com/Code1v1\" target=\"_blank\" rel=\"noopener noreferrer\">https://github.com/Code1v1</a></li>\n<li>git 提交 message 需要编写好合适的记录，不能乱编写；</li>\n<li>提交测试截图（运行过程）；</li>\n<li>附带自制的 <code>word_list.txt</code> 词库（不少于 20 个单词）；</li>\n<li>附加功能或界面美化可酌情加分；</li>\n<li>为你的项目编写合适的 <code>README.md</code> 文件，并创建 <code>log.md</code> 文件实时记录自己每次的开发，还需要创建一个 <code>Thinking.md</code> 编写你脑海中随机浮现的想法💡（包括疑惑，不过需要注意结构。）</li>\n<li>如果参考了网络文章、人工智能，记得留下对应的参考链接，说明使用了什么知识；（Tips：ChatGPT 可以生成分享链接）</li>\n<li>切勿直接通过 AI 生成代码！</li>\n</ol>\n<h3>1.6 扩展挑战（鼓励但不强制）</h3>\n<ul>\n<li>添加 <strong>中文猜英文</strong> 的测试模式；</li>\n<li>支持 <strong>错题本</strong> 机制，记录曾经记错过的单词；</li>\n<li>使用 <code>tkinter</code> 实现图形界面；</li>\n<li>每天自动弹出学习提醒（可结合 <code>schedule</code> 或 <code>crontab</code>）；</li>\n<li>融合 AI 答疑助教；</li>\n</ul>\n<h3>1.7 项目评分标准：每日英语单词记忆卡片工具</h3>\n<p>| 评分项                         | 说明                                                  | 分值  |<br>\n|</p>\n",
      "image": "https://bornforthis.cn/gzh.jpg",
      "date_published": "2025-05-18T21:22:48.000Z",
      "date_modified": "2025-10-14T08:04:59.000Z",
      "authors": [
        {
          "name": "AI悦创"
        }
      ],
      "tags": []
    },
    {
      "title": "02-蓉宝“第一次”母亲节",
      "url": "https://bornforthis.cn/column/cookdinner/P00-Plan/2025-year/02-2025%E5%B9%B45%E6%9C%8811%E6%97%A5%E6%AF%8D%E4%BA%B2%E8%8A%82.html",
      "id": "https://bornforthis.cn/column/cookdinner/P00-Plan/2025-year/02-2025%E5%B9%B45%E6%9C%8811%E6%97%A5%E6%AF%8D%E4%BA%B2%E8%8A%82.html",
      "summary": "1. 菜单 水煮肉片（加一些肥牛测试）； 懒人焖饭； 葱烧肥牛； 煎饺； 2. 配菜",
      "content_html": "<h2>1. 菜单</h2>\n<ol>\n<li>水煮肉片（加一些肥牛测试）；</li>\n<li>懒人焖饭；</li>\n<li>葱烧肥牛；</li>\n<li>煎饺；</li>\n</ol>\n<h2>2. 配菜</h2>\n",
      "date_published": "2025-05-11T14:33:56.000Z",
      "date_modified": "2025-09-19T14:35:01.000Z",
      "authors": [],
      "tags": []
    },
    {
      "title": "06-for 循环内容补充",
      "url": "https://bornforthis.cn/Books/02-SupplementaryArticles/Python/06-for-loop.html",
      "id": "https://bornforthis.cn/Books/02-SupplementaryArticles/Python/06-for-loop.html",
      "summary": "1. for 循环嵌套 点击展开阅读 在 Python 中，嵌套的 for 循环是指在一个 for 循环内部再包含一个或多个 for 循环。这种结构在处理多维数据（例如二维、三维的列表或数组）以及需要多层次迭代的场景中非常常见，可以大幅提高编程的灵活性与效率。 1. 嵌套 for 循环的基本结构 1.1 基本定义 一个嵌套的 for 循环通常的书写形式...",
      "content_html": "<h2>1. for 循环嵌套</h2>\n<details class=\"hint-container details\"><summary>点击展开阅读</summary>\n<p>在 Python 中，<strong>嵌套的 <code>for</code> 循环</strong>是指在一个 <code>for</code> 循环内部再包含一个或多个 <code>for</code> 循环。这种结构在处理多维数据（例如二维、三维的列表或数组）以及需要多层次迭代的场景中非常常见，可以大幅提高编程的灵活性与效率。</p>\n<h3>1. 嵌套 for 循环的基本结构</h3>\n<h4>1.1 基本定义</h4>\n<p><s>嵌套的 <code>for</code> 循环的基本结构如下：</s></p>\n<p>一个嵌套的 <code>for</code> 循环通常的书写形式如下：</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> 变量1 </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> 可迭代对象1:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> 变量2 </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> 可迭代对象2:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">        # 执行代码块</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>每个 <code>for</code> 循环工作原理如下：</p>\n<ul>\n<li>外层循环从<code>可迭代对象1</code>中取出一个元素赋值给<code>变量1</code>。</li>\n<li>然后，内层循环开始执行，从<code>可迭代对象2</code>中逐一取出元素赋值给<code>变量2</code>。</li>\n<li>特别注意：对于外层循环的每一个（次）单独的迭代，内层循环都会完整地循环一遍（举个例子：假如外层循环2次，内层循环3次。当程序开始运行时：外层循环执行第一次，内层循环会完整的执行完 3次。然后外层循环才会再执行下一次循环，内层循环接着重复执行完整的3次。如此反复～）</li>\n</ul>\n<h4>1.2 代码示例</h4>\n<p>查看下面的代码示例，助于理解：</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> i </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> range</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">    print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">f</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"外层循环执行了第 </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">{</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">i </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 1}</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> 次\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> j </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> range</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">        print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">f</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">\\t</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">内层循环执行了第 </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">{</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">j </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 1}</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> 次\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>运行结果如下：</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">外层循环执行了第 </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> 次</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">\t内层循环执行了第 </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> 次</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">\t内层循环执行了第 </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> 次</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">\t内层循环执行了第 </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> 次</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">外层循环执行了第 </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> 次</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">\t内层循环执行了第 </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> 次</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">\t内层循环执行了第 </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> 次</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">\t内层循环执行了第 </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> 次</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>看了上面的输出，你会对 for 循环嵌套有更好的理解。我接下来还有写一个生活中的例子来辅助理解嵌套循环，学代码不要脱离现实！一切都来源于生活～</p>\n<h4>1.3 生活中的例子</h4>\n<p>让我们用一个贴近生活的场景来解释嵌套 for 循环的思想。想象你是餐厅的经理，负责统计一晚上的销售收入。</p>\n<p><strong>场景描述：</strong></p>\n<p>在一家繁忙的餐厅中，每张桌子都有几位顾客，每位顾客可能会点多道菜。为了统计当晚的总收入，你会采取以下步骤：</p>\n<ol>\n<li><strong>逐桌检查</strong>：你首先走遍整个餐厅，对每一张桌子进行查看。这一步相当于第一层“循环”——每张桌子都要统计。</li>\n<li><strong>逐人点单</strong>：对于每张桌子，你会询问每位顾客点了哪些菜，并记录每道菜的价格。这就相当于在每张桌子内部，你又需要逐一处理桌子上的所有订单，也就是第二层“循环”。</li>\n<li><strong>汇总统计</strong>：当你收集完每桌的所有订单后，将每张桌子的总金额加起来，就可以得出餐厅的总收入。</li>\n</ol>\n<p><strong>这个过程可以形象地理解为：</strong></p>\n<ul>\n<li><strong>外层循环（第一层）：</strong> 遍历餐厅的每张桌子。</li>\n<li><strong>内层循环（第二层）：</strong> 对每张桌子上的每位顾客及其订单进行统计。</li>\n</ul>\n<p>这种分步走的做法正是嵌套循环的思想：先处理大范围的分组（桌子），再在每个分组内部逐个处理细节（顾客订单）。这种方法不仅让你更有条理地完成任务，还能防止遗漏细节。</p>\n<p>通过这种方式，你就能准确地统计出餐厅一整晚的销售额，同时也能发现某一桌的消费是否特别高、哪种菜品更受欢迎等信息。这正是嵌套 for 循环在现实生活中的一个直观应用。</p>\n<h3>2. 示例：处理二维列表</h3>\n<h4>2.1 基本遍历输出</h4>\n<p><s>假设我们有一个二维列表（即列表的列表），我们可以使用嵌套的 <code>for</code> 循环来遍历每一个元素。</s></p>\n<p>假设我们有一个二维列表（列表中存放列表），现在需要依次遍历并访问里面的每个元素。示例代码如下：</p>\n<p><s>假设我们有一个二维列表（即列表的列表），比如一个 3x3 的矩阵。我们希望依次访问矩阵中的每个元素。下面的示例代码展示了如何使用嵌套循环来完成这个任务：</s></p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">matrix </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> [</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">],</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">4</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">5</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">6</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">],</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">7</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">8</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">9</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> row </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> matrix:       </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 外层循环：遍历每一行</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> item </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> row:     </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 内层循环：遍历当前行中的每个元素</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">        print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(item)</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p><s>这段代码首先遍历 <code>matrix</code> 中的每一行（外层循环），然后遍历该行中的每个元素（内层循环），并打印出来。</s></p>\n<p><s>运行结果将依次打印 <code>1 2 3 4 5 6 7 8 9</code>。这里的 <code>row</code> 是外层循环的元素（即矩阵中的一行），<code>item</code> 则代表当前行中的某个具体元素。</s></p>\n<p><strong>逐步解析：</strong></p>\n<ol>\n<li><strong>外层循环</strong>：<code>for row in matrix:</code> 这一行代码会依次取出 <code>matrix</code> 中的每一行（每一行本身也是一个列表），并将它赋值给变量 <code>row</code>。</li>\n<li><strong>内层循环</strong>：<code>for item in row:</code> 每当外层循环取得一行数据后，内层循环会遍历该行中的所有元素，依次将元素赋值给 <code>item</code>，并执行 <code>print(item)</code>。</li>\n</ol>\n<p><strong>小实验</strong>：尝试在代码中添加注释或打印调试信息，观察内外层循环的执行顺序，加深理解。</p>\n<h4>2.2 小试牛刀 5：遍历二维列表</h4>\n<p><s><strong>小试牛刀：</strong> 用 for 循环嵌套求 matrix 数据总和。</s></p>\n<p>用 for 循环嵌套对二维列表求和，二维列表数据如下：</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">matrix </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> [</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">],</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">4</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">5</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">6</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">],</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">7</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">8</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">9</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><ol>\n<li>\n<p><strong>第一步</strong>：先思考如何实现，我们要计算出列表 matrix 中的总和，前提是什么？前提是先得到每个数字！</p>\n</li>\n<li>\n<p><strong>第二步</strong>：得到列表中的每个数字，前面已经讲解过：</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">matrix </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> [</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">],</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">4</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">5</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">6</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">],</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">7</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">8</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">9</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> row </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> matrix:       </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 外层循环：遍历每一行</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> item </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> row:     </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 内层循环：遍历当前行中的每个元素</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">        print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(item)</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div></li>\n<li>\n<p><strong>第三步</strong>：得到每一个数字后，我们需要实现累加。现实生活中，我们加一个数时会怎么计算？</p>\n<ol>\n<li>例如计算一组：<code>[1, 2, 3]</code>；</li>\n<li>首先计算 1 + 2 得到 3，我们记下来；</li>\n<li>接着用前面记着的 3，加上下一个待相加的 3 得到：<code>3 + 3 = 6</code>。</li>\n<li>我记下来是怎么记的？——无非是记在草稿子上或者是记在脑子的某个位置；</li>\n<li>那在代码中如何实现？——找一个类似草稿子或者脑子的某个位置来记，在 Python 中我们就可以创建一个变量来存储待求的总和，我们就把变量叫 <code>total</code> 吧。</li>\n<li>下一个问题来了，直接就在代码里面写 <code>total</code> 吗？——肯定不行，语法也不允许。肯定是需要给 total 赋一个值，因为我们是要求和，赋什么值不会影响最终的计算结果呢？——零（0），零加上任何数都等于本身！</li>\n</ol>\n<p>最终代码如下：</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 我们先初始化一个变量 total 用于累加每个元素的值。</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">total </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 0</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div></li>\n<li>\n<p><strong>第四步</strong>：直接进行累加即可</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">matrix </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> [</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">],</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">4</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">5</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">6</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">],</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">7</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">8</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">9</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">total </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 0</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> row </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> matrix:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> item </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> row:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">        total </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> item  </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 外层循环遍历每一行，内层循环遍历每一行中的每个数字，并不断将数字加到 total 上。</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(total)</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>这段代码会将所有数字相加并打印出结果 <code>45</code>，如果可以：试着在内层循环中添加 <code>print(item)</code>，观察程序是如何逐步累加的。</p>\n</li>\n</ol>\n<p><s>上面成功实现求和，但 for 循环嵌套并不是必须的，我们如何实现只用一个 for 循环实现呢？</s></p>\n<p><strong>并非所有情形都必须使用嵌套循环</strong>，我们学会跳出思维惯性，开阔自己的思维。有时解决问题的方法不止一种，如同上面的求和任务。若仅仅是想把所有数字相加，还可以用下面的写法，一个 <code>for</code> 循环就足够了。</p>\n<p>这里我们可以利用 Python 内置的 <code>sum()</code> 函数对每一行列表求和，然后再累加。例如：</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">matrix </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> [</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">],</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">4</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">5</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">6</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">],</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">7</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">8</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">9</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">total </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 0</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> row </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> matrix:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    total </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+=</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> sum</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(row)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(total)</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>这种方式代码更简洁，但理解嵌套循环的工作原理对于你日后面对更复杂问题时非常重要。如果说推荐，我肯定推荐现在的第二种方法。这里用到 for 嵌套，纯粹是为了教你用而用。</p>\n<h4>2.3 难度升级：二维数组竖列求和</h4>\n<h5>2.3.1 任务描述</h5>\n<p>在更复杂的情形下，我们可能需要按“列”来计算和。</p>\n<p>现在让我们挑战一下：是我们的“老熟人”二维数组 <code>matrix</code>，要求计算每一列的元素之和，并将结果存储在一个一维数组中。该任务不仅锻炼你对嵌套循环的理解，同时也会让你更熟悉如何操作数组索引。</p>\n<p><strong>对于下面的矩阵：</strong></p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">matrix </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> [</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">],</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">4</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">5</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">6</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">],</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">7</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">8</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">9</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>对于上述 <code>matrix</code>，你的程序应该输出：</p>\n<div class=\"language- line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-\"><span class=\"line\"><span>每列的和: [12, 15, 18]</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div></div></div><p><strong>说明：</strong></p>\n<ol>\n<li>\n<p>第一列（第 0 列）的和：<code>1 + 4 + 7 = 12</code></p>\n</li>\n<li>\n<p>第二列（第 1 列）的和：<code>2 + 5 + 8 = 15</code></p>\n</li>\n<li>\n<p>第三列（第 2 列）的和：<code>3 + 6 + 9 = 18</code></p>\n</li>\n</ol>\n<p><strong>要求</strong>：你必须使用 <code>for</code> 循环来遍历二维数组并计算每列的和。</p>\n<p><strong>提示</strong>：你可以通过初始化一个长度为 <code>n</code> 的数组来存储每列的和，并在遍历每行时将每列的值加到相应的数组位置上。</p>\n<p>好好思考一下，看看上面如何实现。接下来，我会一步步带你实现。</p>\n<h5>2.3.2 <strong>第一步：从现实生活角度理解如何按列求和</strong></h5>\n<p>想象一下，你有一个由多行数字组成的表格，每一列都排列着一组数字。假如你要计算每一列的总和，首先你会在心中设定一个记录器，每一列都有一个“计数器”。</p>\n<p>当你逐行查看这张表格时，每读到一行，就会把这一行中每一列的数字分别加到对应的计数器上。</p>\n<p>比如，第一行的三个数字分别加到第一、第二、第三个计数器上；接着第二行同样处理……直到所有行都看完。</p>\n<p>最终，每个计数器中的数值就是对应列的总和。</p>\n<p>接下来，我举个具体的例子，来让你更好的理解。文字表达终归有局限性，但是我会尽可能表达完全且清楚。</p>\n<p>假设你面前有一个表格，表格中的数字排列如下：</p>\n<div class=\"language-diff line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"diff\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-diff\"><span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">+</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div></div></div></details>\n",
      "date_published": "2025-05-05T16:49:17.000Z",
      "date_modified": "2025-05-07T11:20:58.000Z",
      "authors": [
        {
          "name": "AI悦创"
        }
      ],
      "tags": []
    },
    {
      "title": "07-类内容补充",
      "url": "https://bornforthis.cn/Books/02-SupplementaryArticles/Python/07-class.html",
      "id": "https://bornforthis.cn/Books/02-SupplementaryArticles/Python/07-class.html",
      "summary": "1. 从生活中的类比说起 将程序任务涉及到的事物抽象为一个个的对象，以这些对象为中心来写程序。是不是很抽象，很难理解？不用慌，我们从头开始讲！ 很多朋友最开始学编程的时候，是从 C++ 或者 JAVA 语言入手的。甚至现在国内外 Python 课程开设，不用要求学生提前掌握其它编程语言。读者们好不容易磕磕绊绊地搞懂了最基本的数据类型、赋值判断和循环，却...",
      "content_html": "<h2>1. 从生活中的类比说起</h2>\n<p>将程序任务涉及到的事物抽象为一个个的对象，以这些对象为中心来写程序。是不是很抽象，很难理解？不用慌，我们从头开始讲！</p>\n<p>很多朋友最开始学编程的时候，是从 C++ 或者 JAVA 语言入手的。甚至现在国内外 Python 课程开设，不用要求学生提前掌握其它编程语言。读者们好不容易磕磕绊绊地搞懂了最基本的数据类型、赋值判断和循环，却又迎面撞上了 OOP (object oriented programming) 的大墙，一头扎进公有私有保护、多重继承、多态派生、纯函数、抽象类、友元函数等一堆专有名词的汪洋大海中找不到彼岸，于是就放弃了进阶之路。</p>\n<p>相比之下，Python 是一门相对友好的语言，它在创立之初就鼓励命令交互式的轻量级编程。理论上，Python 的命令式语言是图灵完备的, 也就是说命令式语言，理论上可以做到其他任何语言能够做到的所有的事情，甚至进一步，仅仅依靠汇编语言的 MOV 指令，就能实现图灵完备编程。</p>\n<p>那么为什么不这样做呢？其实，“上古时代”的程序员就是这么做的，可是随着程序功能复杂性的逐步提升，以及需求的不断迭代，很多老旧的代码修改起来麻烦无比，牵一发而动全身，根本无法迭代和维护，甚至只能推倒重来，这也是很多古老的代码被称为“屎山”的原因。</p>\n<p>传统的命令式语言有无数重复性代码，虽然函数的诞生减缓了许多重复性，但随着计算机的发展，只有函数依然不够，需要把更加抽象的概念引入计算机才能缓解（而不是解决）这个问题，于是 OOP 应运而生。</p>\n<p>Python 在 1989 年被一位程序员打发时间创立之后，一步步攻城掠地飞速发展，从最基础的脚本程序，到后来可以编写系统程序、大型工程、数据科学运算、人工智能，早已脱离了当初的设计，因此一些其他语言的优秀设计之处依然需要引入。我们必须花费一定的代价掌握面向对象编程，才能跨越学习道路中的瓶颈期，走向下一步。</p>\n<p>接下来，我将用上万字来讲解面向对象编程，从基础到实战。我将带你快速但清晰地疏通最基础的知识，确保你能够迅速领略面向对象的基本思想。接着我们从零开始写一个文字对话游戏，将前面所学知识融会贯通。</p>\n<p>这些内容可能和你以往看到的所有教程都不太一样，我会尽可能从一个初学者的角度来审视这些难点。同时我们面向实战、面向工程，不求大而全，但是对最核心的思想会有足够的勾勒。我可以保证内容清晰易懂，但想要真正掌握，仍要求你能用心去阅读和思考。真正的提高，永远要靠自己才能做到。</p>\n<h3>1.1 什么是类？什么是实例？</h3>\n<p>学习编程时，我们常常会听到“类”和“实例”这两个概念。要想真正理解它们，可以先从生活中的例子说起。</p>\n<ol>\n<li>\n<p>什么是类？狗是某一类动物，它们具有相同、相似的属性。如同我们平时说人：物以类聚，人以群分。</p>\n</li>\n<li>\n<p>狗这一类里面有具体地：我家有一只狗，叫旺财。你家有一只狗，叫大黄。</p>\n</li>\n<li>\n<p>因为属于同一狗类，所以它们有共同点：旺财、大黄都有四条腿，一条尾巴，都会狗叫。</p>\n</li>\n<li>\n<p>虽然都属于同一类，但它们互相独立：旺财和大黄被生出来后，互相不会影响。旺财吃胖了，体重增加了不会影响大黄。（一千只狗，就会有一千只哈姆雷特狗。「开玩笑的」）</p>\n</li>\n<li>\n<p>同属一类，当类被影响（修改）时，它们命运相同：如果某一天上帝决定给狗这个种类的生物都增加一条尾巴，那么旺财和大黄会同时变成两条尾巴。</p>\n</li>\n</ol>\n<p>上面用来具体例子在描述类和具体的旺财和大黄，接下来我们快速总结一下：</p>\n<ol>\n<li>狗这一类动物，就是我们所说的：类。就像人类：也是有相同相似的属性，例如：两只腿、两只手、一个鼻子这样；</li>\n<li>旺财：狗这个类的一个实例；</li>\n<li>大黄：狗这个类的一个实例；</li>\n<li>修改类会影响所有的实例，如同上帝让狗都变成了两条尾巴。</li>\n<li>修改某个实例里的属性不会影响其他类，就像人类中：某个人掉头发，但是不会影响其他人。（每个人都是人类这个类别中的实例）</li>\n</ol>\n<h3>1.2 对象，你找到了吗？</h3>\n<p>我们接下来学习，面向对象编程中最基本的概念。前面是比较接地气的解释，下面算是比较正经的解释。虽然有循环论证之嫌（lol），但是我不关心，反复强调之中我还是希望你能对面向对象的最基础的思想，有更真实的了解。</p>\n<p>为了方便你理解其中的抽象概念，我先打个比方带你感受一下。生物课上，我们学过“界门纲目科属种”的概念，核心思想是科学家们根据各种动植物、微生物的相似之处，将其分化为不同的类型方便研究。生活中我们也是如此，习惯对身边的事物进行分类：</p>\n<ol>\n<li>猫和狗都是动物；</li>\n<li>直线和圆都是平面几何的图形；</li>\n<li>《哈利波特》和《冰与火之歌》（即《权力的游戏》）都是小说。</li>\n</ol>\n<p>自然，同一类事物便会有着相似的特性：</p>\n<ol>\n<li>动物会动；</li>\n<li>平面图形有面积和周长；</li>\n<li>小说也都有相应的作者和大致情节等各种元素。</li>\n</ol>\n<h2>2. 一个例子：现在的方法</h2>\n<p><strong>任务</strong>：我们有一只猫和一只狗，他们在听到指令后要向前跑 10 米。</p>\n<p>我们来编写这两个函数：</p>\n<div class=\"language-python line-numbers-mode has-collapsed-lines collapsed\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--vp-collapsed-lines:15;--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">dog_x </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 0</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">cat_x </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 0</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> dog_move</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">():</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    global</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> dog_x  </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 为什么要加上 global？因为 dog_x 是全局变量，如果不加上 global，函数内的 dog_x 会被视为局部变量，也无法修改全局变量的值</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    dog_x </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> dog_x </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 10</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> cat_move</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">():</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    global</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> cat_x</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    cat_x </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> cat_x </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 10</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">user_input </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> input</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'输入指令:'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> user_input </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">==</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> 'move'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">    print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'dog:</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">{}</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">, cat:</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">{}</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">format</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(dog_x, cat_x))</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">    dog_move</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">    cat_move</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">    print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'dog:</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">{}</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">, cat:</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">{}</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">format</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(dog_x, cat_x))</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div><div class=\"collapsed-lines\"></div></div><p><strong>注意</strong>：在阅读的过程当中，你要按我的指导来并且思路也要跟着来。</p>\n<p>现在，把上面的代码敲一遍。敲完之后，也先别急着往下阅读。先思考和阅读一下上面的代码，看看功能、语法都能理解吗。能理解，则继续。</p>\n<p>相必你已经理解了上面的代码，接下来请你再添加一只动物：大象，也是听到指令后要向前跑 10 米。</p>\n<div class=\"language-python line-numbers-mode has-collapsed-lines collapsed\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--vp-collapsed-lines:15;--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">dog_x </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 0</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">cat_x </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 0</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">elephant </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 0</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> dog_move</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">():</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    global</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> dog_x  </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 为什么要加上 global？因为 dog_x 是全局变量，如果不加上 global，函数内的 dog_x 会被视为局部变量，也无法修改全局变量的值</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    dog_x </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> dog_x </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 10</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> cat_move</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">():</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    global</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> cat_x</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    cat_x </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> cat_x </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 10</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> elephant_move</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">():</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    global</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> elephant</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    elephant </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> elephant </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 10</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">user_input </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> input</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'输入指令:'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> user_input </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">==</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> 'move'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">    print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'dog:</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">{}</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">, cat:</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">{}</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">, elephant:</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">{}</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">format</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(dog_x, cat_x, elephant))</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">    dog_move</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">    cat_move</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">    elephant_move</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">    print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'dog:</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">{}</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">, cat:</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">{}</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">, elephant:</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">{}</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">format</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(dog_x, cat_x, elephant))</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div><div class=\"collapsed-lines\"></div></div><p>敲完大象的代码后，你有没有感觉什么？如果你有什么感觉或者感受，马上拿支笔或者用电脑写注释，把感受写下来！</p>\n<p>我们上面定义了三个相似的函数，功能一样，只有什么不一样？——变量名称不一样。</p>\n<p>是不是感觉太多重复了，你有可能此时觉得没必要创建这么多函数。但是我举个例子你就明白了，比如我们开发了一个围棋对弈的程序，支持用户注册，每个用户注册都要填写用户名、手机号、密码。那是不是意味着我们都要为每个用户创建一个函数来存储呢？</p>\n<div class=\"language-python line-numbers-mode has-collapsed-lines collapsed\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--vp-collapsed-lines:15;--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 我们现在有三个用户要注册，每个用户都要填写用户名、手机号、密码</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 如果我们不优化代码，那可能会像下面这样写：</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> register_user1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">():</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    username1 </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> input</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"请输入用户1的用户名：\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    phone1 </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> input</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"请输入用户1的手机号：\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    password1 </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> input</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"请输入用户1的密码：\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">    print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"用户1注册成功！用户名：</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">{}</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">，手机号：</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">{}</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">format</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(username1, phone1))</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> register_user2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">():</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    username2 </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> input</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"请输入用户2的用户名：\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    phone2 </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> input</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"请输入用户2的手机号：\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    password2 </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> input</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"请输入用户2的密码：\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">    print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"用户2注册成功！用户名：</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">{}</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">，手机号：</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">{}</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">format</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(username2, phone2))</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> register_user3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">():</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    username3 </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> input</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"请输入用户3的用户名：\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    phone3 </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> input</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"请输入用户3的手机号：\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    password3 </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> input</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"请输入用户3的密码：\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">    print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"用户3注册成功！用户名：</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">{}</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">，手机号：</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">{}</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">format</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(username3, phone3))</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 现在我们要依次注册这三个用户</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">register_user1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">register_user2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">register_user3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div><div class=\"collapsed-lines\"></div></div><p>所以，要是为每个用户都来一个类似的行数。那代码是不是会变成“屎”一样的山呢？——答案想必你聊熟于心（肯定会变成屎山的）</p>\n<p>我们接着回到一开始的动物向前移动的例子，我们一共写了三只动物的移动函数：<code>dog_move()</code>、<code>cat_move()</code>、<code>elephant_move()</code>。并且每个函数都做着几乎一样的事情，只是变量名不同。虽然目前动物不多，但如果我们要添加更多动物，比如兔子、老虎、熊猫……你会发现代码会迅速变得臃肿、重复，维护起来很麻烦。</p>\n<p><strong>思考一下</strong>：有没有更优雅的方式来管理动物的位置？</p>\n<p>我们可以把这些“重复”的结构统一管理起来，例如：我们把所有动物的位置，放进一个<strong>统一的容器</strong>里，比如用一个字典来表示。一起来看看下面的代码。</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">positions </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    \"dog\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    \"cat\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    \"elephant\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">}</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>那么至少，这样的代码会比原本的简洁一些。看看下面的代码效果：</p>\n<div class=\"language-python line-numbers-mode has-collapsed-lines collapsed\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--vp-collapsed-lines:15;--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">positions </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    \"dog\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    \"cat\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    \"elephant\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">}</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> dog_move</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">():</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    global</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> positions</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    positions[</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'dog'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">] </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> positions[</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'dog'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">] </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 10</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> cat_move</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">():</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    global</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> positions</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    positions[</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'cat'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">] </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> positions[</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'cat'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">] </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 10</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> elephant_move</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">():</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    global</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> positions</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    positions[</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'elephant'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">] </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> positions[</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'elephant'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">] </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 10</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">user_input </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> input</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'输入指令:'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> user_input </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">==</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> 'move'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">    print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'dog:</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">{}</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">, cat:</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">{}</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">, elephant:</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">{}</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">format</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(positions[</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'dog'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">], positions[</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'cat'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">], positions[</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'elephant'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]))</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">    dog_move</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">    cat_move</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">    elephant_move</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">    print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'dog:</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">{}</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">, cat:</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">{}</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">, elephant:</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">{}</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">format</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(positions[</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'dog'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">], positions[</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'cat'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">], positions[</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'elephant'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]))</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div><div class=\"collapsed-lines\"></div></div><p>运行之后，输出如下：</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">输入指令:move</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">dog:</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, cat:</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, elephant:</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">dog:</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">10</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, cat:</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">10</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, elephant:</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">10</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>函数还是一如既往的更“屎”一样，但是动物的数据结构化了。</p>\n<p>到此，我们来稍微总结一下：</p>\n<ol>\n<li>相同点：每个函数都是相同的功能，结构都是一样的；</li>\n<li>不同点：只有变量名不一样；</li>\n</ol>\n<p>那么对于相同功能和相同的结构，是不是就可以说是：相同相似的属性，那么就可以把上面写的多个函数（<code>dog_move()</code>、<code>cat_move()</code>、<code>elephant_move()</code>）都是视为同一个类。可以叫动物类（Animal），只要属于这个动物类都可以接收指令往前跑。</p>\n<h2>3. 一个例子：面向对象的方法</h2>\n<h3>3.1 面向对象代码基础</h3>\n<p>接下来，我们就要使用面向对象的方法来实现前面动物听到指令就往前跑的功能。</p>\n<p>编写如下代码：</p>\n<div class=\"language-python line-numbers-mode has-collapsed-lines collapsed\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--vp-collapsed-lines:15;--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">class</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> Animal</span><span style=\"--shiki-light:#C18401;--shiki-dark:#ABB2BF\">()</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    def</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> __init__</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E5C07B;--shiki-dark-font-style:italic\">self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">        self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.x </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 0</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> move</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E5C07B;--shiki-dark-font-style:italic\">self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">        self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.x </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\"> self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.x </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 10</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">dog </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> Animal</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">cat </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> Animal</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">user_input </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> input</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'输入指令:'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> user_input </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">==</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> 'move'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    dog.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">move</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    cat.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">move</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">    print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'Dog position:'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, dog.x)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">    print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'Cat position:'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, cat.x)</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div><div class=\"collapsed-lines\"></div></div><p>参照着这段代码，我先来简单解释几个概念。</p>\n<ol>\n<li>类：一群有着相似性的事物的集合，这里对应 Python 的 class。</li>\n<li>对象：集合中的一个事物，这里对应由 class 生成的某一个 object，比如代码中的 dog 或 cat。（其实就是实例）</li>\n<li>属性：对象的某个静态特征，比如上述代码中的 x。</li>\n<li>函数：对象（实例）的某个动态能力，比如上述代码中的 <code>move()</code> 函数。</li>\n</ol>\n<p>接下来，看下面的图比较直观一点，能看到每个部分代表什么：</p>\n<figure><figcaption></figcaption></figure>\n<p>当然，这样的说法既不严谨，也不充分，但如果你对面向对象编程完全不了解，它们可以让你迅速有一个直观的了解。</p>\n<p>这里我想多说两句。回想起当年参加数学竞赛时，我曾和一个大佬交流数学的学习，我清楚记得我们对数学有着相似的观点：很多数学概念非常抽象，如果纯粹从数理逻辑而不是更高的角度去解题，很容易陷入僵局；而具体、直观的想象和类比，才是迅速打开数学大门的钥匙。虽然这些想象和类比不严谨也不充分，很多时候甚至是错误或者异想天开的，但它们确实能帮我们快速找到正确的大门。</p>\n<p>就像很多人都有过的一个疑惑，“学霸是怎样想到这个答案的？”。德国数学家克莱因曾说过，“推进数学的，主要是那些有卓越直觉的人，而不是以严格的证明方法见长的人。”编程世界同样如此，如果你不满足于只做一个 CRUD“码农”，而是想成为一个优秀的工程师，那就一定要积极锻炼直觉思考和快速类比的能力，尤其是在找不到 bug 的时候。这才是编程学习中能给人最快进步的方法和路径。</p>\n<p>言归正传，继续回到我们的主题，还是通过刚刚那段代码，我想再给类下一个更为严谨的定义。</p>\n<p><strong>类，一群有着相同属性和函数的对象的集合。</strong></p>\n<h3>3.2 <code>__init__(self)</code> 函数</h3>\n<p>接下来，我们来具体解读刚刚这段代码。为了方便你的阅读学习，我把它重新放在了这段文字下方。</p>\n<div class=\"language-python line-numbers-mode has-collapsed-lines collapsed\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--vp-collapsed-lines:15;--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">class</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> Animal</span><span style=\"--shiki-light:#C18401;--shiki-dark:#ABB2BF\">()</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    def</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> __init__</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E5C07B;--shiki-dark-font-style:italic\">self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">        self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.x </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 0</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> move</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E5C07B;--shiki-dark-font-style:italic\">self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">        self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.x </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\"> self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.x </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 10</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">dog </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> Animal</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">cat </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> Animal</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">user_input </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> input</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'输入指令:'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> user_input </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">==</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> 'move'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    dog.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">move</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    cat.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">move</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">    print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'Dog position:'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, dog.x)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">    print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'Cat position:'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, cat.x)</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div><div class=\"collapsed-lines\"></div></div><p>可以看到，<code>class Animal</code> 定义了 Animal 类，再往下能看到它有两个函数，这连个函数即为 Animal 类的两个函数。</p>\n<p>其中，<strong>init</strong> 表示构造函数，含义则是：<strong>在一个对象生成时会被自动调用的函数</strong>。这么讲比较抽象，我们来结合下面的代码来实现：</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">class</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> Animal</span><span style=\"--shiki-light:#C18401;--shiki-dark:#ABB2BF\">()</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    def</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> __init__</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E5C07B;--shiki-dark-font-style:italic\">self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">        print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'init function called'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">dog </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> Animal</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>运行上面代码后会自动输出：</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">Nice to meet you!</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div></div></div><p>我们能看到， <code>dog = Animal()</code> 这一行代码被执行的时候，<code>'init function called'</code> 字符串会被打印出来。</p>\n<p>你有没有发现，我们从始至终都没有调用 <code>init</code> 函数！在类 Animal 被实例化为 dog 时，会自动被调用。</p>\n<p><strong>注意</strong>：你需要做到自己编写代码和运行一下，这样才能理解！</p>\n<p>再举一些现实的例子，因为不确定你会因为哪个例子理解，我这里就多列几个：</p>\n<ol>\n<li>\n<p><strong>例子一</strong>：我们创建了一个游戏角色，每个角色一出生（也就是被创建的时候），就会自动拥有一些“天赋技能”。这些技能不是你手动添加的，而是角色一出生系统就帮你准备好了。</p>\n<p>在 Python 中，<code>__init__</code> 函数就像这个“天赋赋予系统”，当你创建一个对象（实例化）的时候，它会自动帮你设置好对象该有的初始状态。</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">class</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> GameCharacter</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    def</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> __init__</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E5C07B;--shiki-dark-font-style:italic\">self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">        print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"角色已创建，天赋技能已激活！\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">hero </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> GameCharacter</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>运行这段代码，控制台会自动输出：</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">角色已创建，天赋技能已激活！</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div></div></div><p>我们没有显式地调用 <code>__init__()</code>，但它还是被执行了。这就是 <code>__init__</code> 函数自动调用的效果。</p>\n<p>这个机制非常重要——它可以让我们在对象被创建时，自动执行一些初始化操作，比如设置默认值、加载数据、建立连接等。</p>\n</li>\n<li>\n<p><s>例子二：我们人类在一诞生的时候，没人教我们怎么呼吸、心跳，这些都是会自动拥有且自动执行（开始的）。</s></p>\n</li>\n<li>\n<p><strong>例子二</strong>：就像我们人类在一诞生的时候，没人教我们怎么呼吸、怎么让心脏跳动——这些能力是与生俱来的，是“出生那一刻就自动开始执行”的。</p>\n<p>Python 中的 <code>__init__</code> 方法（函数），就像“呼吸”和“心跳”一样。当我们创建一个新的对象（生命、实例化）时，它会自动执行，不需要我们手动去调用。</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">class</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> Human</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    def</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> __init__</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E5C07B;--shiki-dark-font-style:italic\">self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">        print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"一个新生命诞生了，正在自动启动呼吸和心跳系统。\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">baby </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> Human</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>输出结果是：</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">一个新生命诞生了，正在自动启动呼吸和心跳系统。</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div></div></div><p>你有没有注意？我们并没有调用 <code>__init__()</code>，但它还是被执行了。为什么？因为我们创建了一个新的 <code>Human()</code> 对象（实例化）baby，Python 就会自动调用 <code>__init__()</code>，帮我们把“出生后应该启动的机制”都安排好。</p>\n<p>所以你可以把 <code>__init__</code> 想象成“对象出生时的大脑指令中心”——只要对象（实例化）一被创建，它就会第一时间执行你写好的初始化内容，比如设定初始状态、创建属性，或者像我们上面例子一样，打印一句欢迎词。</p>\n</li>\n</ol>\n<p>讲完初始化函数 <code>__init__</code> ，我们接下来来讲 <code>move()</code> 函数，<code>move()</code> 则为类的普通函数，我们调用它们来对对象的属性做一些事情。</p>\n<h3>3.3 <code>move(self)</code> 函数</h3>\n<p><code>move(self)</code> 函数就是和我们前面讲的基本函数意思、功能是一样的，只不过这里是属于类里面的功能函数。没有什么要讲的，重点去看前一篇的。</p>\n<h3>3.4 类当中的 self</h3>\n<p>在上面的代码中，你如果仔细观察的话会发现：在类内的每个函数中，都有写 self 参数。这个地方的知识点比较抽象，一定要细细思考和阅读。就算我不慎重复论述，你也不要疑惑，一切的一切都是为了让你学会。</p>\n<p>我把代码贴出来，方便阅读学习：</p>\n<div class=\"language-python line-numbers-mode has-collapsed-lines collapsed\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--vp-collapsed-lines:15;--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">class</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> Animal</span><span style=\"--shiki-light:#C18401;--shiki-dark:#ABB2BF\">()</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    def</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> __init__</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E5C07B;--shiki-dark-font-style:italic\">self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">        self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.x </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 0</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> move</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E5C07B;--shiki-dark-font-style:italic\">self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">        self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.x </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\"> self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.x </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 10</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">dog </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> Animal</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">cat </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> Animal</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">user_input </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> input</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'输入指令:'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> user_input </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">==</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> 'move'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    dog.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">move</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    cat.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">move</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">    print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'Dog position:'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, dog.x)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">    print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'Cat position:'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, cat.x)</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div><div class=\"collapsed-lines\"></div></div><p>我一步步带你理解，然后再用专业的角度来解释。（不专业的才是你学会的契机）</p>\n<h4>3.4.1 非正式讲解1</h4>\n<p>self 就是代表 <code>Animal()</code>，而当 <code>Animal()</code> 实例化了 dog（也就是 <code>Animal()</code> 赋值给变量 dog：<code>dog = Animal()</code>），则可以得到 dog 就是代表 <code>Animal()</code>，最终：self 就代表 dog。故而可以得到：</p>\n<ol>\n<li><strong>结论1</strong>：<code>self.x ==&gt; Animal().x ==&gt; dog.x </code>；</li>\n<li><strong>结论2</strong>：<code>Animal()</code> 中的函数可以写成：<code>Animal().move()</code> ，那么实例化之后 dog 就代表 <code>Animal()</code>，可以得到：<code>dog.move()</code> 调用函数。</li>\n<li><strong>结论3</strong>：类里面每个函数都要加上 self 代表都属于类的一员。就如同家族族徽，代表都属于家族的一员。</li>\n<li><strong>结论4</strong>：有了 self 这个族徽，意味着家族的资源都可以互相使用。例如：家族的百万围棋棋盘，所有家族成员都可以直接使用。如果不是同一家族的，就得看情况了。所以，当类里面存在的变量，（包括各个函数的变量）如果在变量前面添加 self（<code>self.x</code>），则在类中，所有函数都可以随时调用变量 <code>self.x</code>。（后续会有代码演示）</li>\n</ol>\n<h4>3.4.2 非正式讲解2</h4>\n<ol>\n<li>换句话说，self 中文代表“自己”的意思，而 self 又存在于类 <code>Animal()</code> 当中。所以 “self 自己”就代表 <code>Animal()</code> 。</li>\n<li>又因为：<code>Animal()</code> 赋值给变量 dog（实例化），所以 dog 代表 <code>Animal()</code> 这个类。</li>\n<li>接着我们就可以推出：<code>self == Animal() == dog</code>，故而 <code>self.x</code> 等价于 <code>Animal().x</code> 接着等价于 <code>dog.x</code>。</li>\n<li>我们说 <code>Animal()</code> 的函数 <code>move()</code>，就可以写成 <code>Animal().move()</code> （中间的点“.”可以理解成“的”），有因为类 <code>Animal()</code> 赋值给 dog，所以可以得出：<code>dog.move()</code>。</li>\n</ol>\n<p>通过上面两个非正式讲解，如果你全部理解的话，那么后续讲解 self 部分你不用细究和强迫读懂，直接速读即可。毕竟正式的表达不好理解，不过我还是得稍微写一下。</p>\n<h4>3.4.3 注意</h4>\n<p>在类里面的函数，第一个参数都必须写 self！</p>\n<figure><figcaption></figcaption></figure>\n<h4>3.4.4 正式讲解：什么是 self？（细读）</h4>\n<p>在 Python 中，当我们定义一个类的方法时，第一个参数通常命名为 <strong>self</strong>。这并不是 Python 的关键字，而是一种编程约定，用来表示当前实例对象。每当我们调用一个对象的方法时，Python 会自动将这个对象传递给方法中的第一个参数，这样我们就可以在方法内部访问该对象的属性和其他方法。</p>\n<h4>3.4.5 为什么需要 self？（速度）</h4>\n<ol>\n<li><strong>明确指定对象实例</strong>：在其他面向对象的语言（例如 Java 或 C++）中，通常会有一个隐式的 <code>this</code> 指针来代表当前对象。但在 Python 中，没有隐式传递对象引用的机制，而是需要程序员显式地声明并使用 <strong>self</strong>。这种方式让代码更加直观，所有对当前对象的引用都清晰可见。</li>\n<li><strong>提高代码的可读性</strong>：显式地使用 <strong>self</strong> 可以帮助初学者更好地理解：在调用方法时，方法内部究竟操作的是哪个对象。它提醒我们：方法内部所有对属性或其他方法的调用，实际上都是在操作当前实例的数据。</li>\n<li><strong>方便方法调用</strong>：因为 <strong>self</strong> 是显式的参数，Python 可以灵活地处理方法调用。你可以将方法绑定到不同的对象上，而不需要额外的内部机制来隐式传递对象引用，这在设计复杂程序时提供了更高的灵活性。</li>\n</ol>\n<h4>3.4.6 生活中的例子：班级中的学生（选读）</h4>\n<p>想象一下，一个班级中有许多学生。每个学生都有自己的姓名、年龄和特点。如果老师想了解某个学生的信息，他会直接问那位学生：“你叫什么名字？”</p>\n<ul>\n<li><strong>学生的自我介绍：</strong> 每个学生在回答问题时都会说“我叫李华”或者“我叫小明”。这里的“我”就相当于这个学生自己。</li>\n<li><strong>学生的独立性：</strong> 即使班上有许多学生，每个学生都是独立的个体，他们各自有自己的名字和特性。在询问时，老师需要明确知道在说哪个学生的信息。</li>\n</ul>\n<p>在 Python 中，<strong>self</strong> 就起到类似“我”的作用。当我们调用某个对象的方法时，self 会自动指向那个具体的对象实例，就像当你问某个学生“你叫什么名字？”时，他会用“我”来代表自己，从而给出正确的回答。</p>\n<h4>3.4.7 self 的本质：方法的第一个参数（细读）</h4>\n<div class=\"language-python line-numbers-mode has-collapsed-lines collapsed\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--vp-collapsed-lines:15;--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">class</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> Animal</span><span style=\"--shiki-light:#C18401;--shiki-dark:#ABB2BF\">()</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    def</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> __init__</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E5C07B;--shiki-dark-font-style:italic\">self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">        self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.x </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 0</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> move</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E5C07B;--shiki-dark-font-style:italic\">self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">        self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.x </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\"> self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.x </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 10</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">dog </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> Animal</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">cat </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> Animal</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">user_input </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> input</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'输入指令:'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> user_input </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">==</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> 'move'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    dog.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">move</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    cat.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">move</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">    print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'Dog position:'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, dog.x)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">    print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'Cat position:'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, cat.x)</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div><div class=\"collapsed-lines\"></div></div><p>当你调用 <code>dog.move()</code> 时，Python 实际上会自动将 <code>dog</code> 这个对象作为第一个参数传递给 <code>move</code> 方法，所以在方法内部，<strong>self</strong> 就代表 <code>dog</code>。这也是为什么我们总是能在方法内部通过 <strong>self</strong> 来访问和修改对象的属性。</p>\n<p><strong>提示</strong>：尝试在方法内部打印一下 <code>self</code>，你会看到它输出的是该对象的内存地址或其它标识信息，这可以帮助你更直观地理解 <strong>self</strong> 代表的是当前实例对象。代码如下：</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">class</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> Animal</span><span style=\"--shiki-light:#C18401;--shiki-dark:#ABB2BF\">()</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    def</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> __init__</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E5C07B;--shiki-dark-font-style:italic\">self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">        self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.x </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 0</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">        print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">f</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"self address: </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">{</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">self</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">}</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">dog </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> Animal</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">f</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"dog address: </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">{</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">dog</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">}</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>运行后输出如下：</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> address: </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&lt;</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">__main__.Animal </span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">object</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> at </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">0x</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1097e0dd0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&gt;</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">dog address: </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&lt;</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">__main__.Animal </span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">object</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> at </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">0x</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1097e0dd0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&gt;</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>从上面的输出可知，最终两个输出的地址是相同的，代表 <strong>self 就是代表当前的实例化对象</strong>。</p>\n<h2>4. <code>__init__</code> 初始化参数</h2>\n<h3>4.1 背景</h3>\n<p>现实生活中，小孩在出生之前。大人们都会做一件什么事情？</p>\n<p>取名字！取名字这件事，是在宝宝出生之前就要提前准备好的。当小孩一出生，就要及时办理出生证。办理出生证就需要想好的名字，而一个人的名字很重要。这时有奇思妙想的学生就会说：老师，你怎么知道性别？咦，我当然不知道了。但是我可以提前想好男宝和女宝的姓名不就行了。</p>\n<p>言归正传，有时候我们在类的初始化时，我们就想给实例化对象取一个名称（昵称）。就比如上面所说的取名字或者你玩游戏之前都要去一个昵称才能开始游戏吧。</p>\n<p>再比如：你注册微信也要一个微信号、微信昵称注册 QQ 就要设置 QQ 昵称、头像吧。这些都是在一开始初始化（实例化）的时候就要填写的。</p>\n<h3>4.2 设置单个参数</h3>\n<p>那么在面向对象中，我们如何达到呢？看看如下代码：</p>\n<div class=\"language-python line-numbers-mode has-collapsed-lines collapsed\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--vp-collapsed-lines:15;--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 在现实生活中，当宝宝出生之前，大人们就会为宝宝取名字，</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 并且准备好出生证明等信息。</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 在面向对象中，我们通过 __init__ 方法初始化实例时，就相当于在出生之前</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 为小孩准备好了“名字”（以及其他必要的信息）。</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">class</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> Baby</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    def</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> __init__</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E5C07B;--shiki-dark-font-style:italic\">self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> name</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">        \"\"\"</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">        初始化宝宝对象时，必须提供名字，</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">        这就像是大人提前为宝宝取好名字，并在必要时办理出生证明。</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">        \"\"\"</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">        self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.name </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> name      </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 宝宝的名字，相当于出生证明中的名字</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> introduce</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E5C07B;--shiki-dark-font-style:italic\">self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">        \"\"\"</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">        宝宝的自我介绍方法，展示初始化时设置的属性。</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">        \"\"\"</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">        print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">f</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"大家好，我叫 </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">{</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.name</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">}</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">。\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 宝宝出生前，大人已经为他取好了名字</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">baby1 </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> Baby</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">name</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"棠棠\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)  </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 实例化</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">baby1.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">introduce</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()  </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 输出: 大家好，我叫 棠棠。</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div><div class=\"collapsed-lines\"></div></div><p>从上面的代码就可以知道，我们如果想要在实例化对象的时，想要添加参数，只需要 <code>__init__</code> 函数的 self 后面添加参数即可。</p>\n<p>接着，我们讲一下为什么要把用户传入的参数进行添加 self 赋值操作：<code>self.name = name</code>。</p>\n<h3>4.4 我们为什么要写 <code>self.xxx = xxx</code>？背后到底发生了什么？</h3>\n<p><strong>小提示</strong>：白话讲解为了让你理解，总结性讲解为了让你专业。</p>\n<h4>4.4.1 白话讲解</h4>\n<p>我先打白话讲解一下，然后再总结性的讲解一下。下面的讲解中，我们都使用 <code>self.name = name</code> 为例来讲解。</p>\n<p>在 <code>__init__</code> 方法（函数）中，你会从上面的代码中发现一个疑问点：为什么用户传入的参数不直接使用，还要创建一个 <code>self.变量名 = 参数</code> 的操作。</p>\n<p>就例如以下几个问题：</p>\n<ol>\n<li><strong>问题一</strong>：为什么传进参数 name，还要把 name 赋值给 <code>self.name</code>？</li>\n<li><strong>问题二</strong>：为什么不直接 <code>name = name</code> 还要用 self？</li>\n<li><strong>问题三</strong>：为什么“点”后面的变量名称和参数同名，不同名可以吗？</li>\n</ol>\n<p>上面三个问题，到底意欲何为呢。我们来一一解答这三个问题。</p>\n<ol>\n<li>\n<p><strong>问题一解答</strong>：通过初始化函数传进来的参数，是不是得找地方存放？就像你准备开设围棋大师班，在正式开设之前。从外地引入了围棋棋具，是不是需要在开班之前要找地方存放。我们类通过实例化（初始化）传入的参数也需要找地方存放，所以需要使用 <code>self.name = name</code> 来存放，至于为什么加 self 下一个问题会解答。</p>\n</li>\n<li>\n<p><strong>问题二解答</strong>：直接使用 <code>name = name</code> 可以，但是就仅限于初始化函数 <code>__init__</code> 自己使用，不仅仅其它函数无法使用，类的实例化对象也无法调用该参数变量（属性值）。看下面的代码，我们没有使用 self 来赋值：</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">class</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> Baby</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    def</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> __init__</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E5C07B;--shiki-dark-font-style:italic\">self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> name</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">        name </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> name</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">        print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">f</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"init name: </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">{</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">name</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">}</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> introduce</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E5C07B;--shiki-dark-font-style:italic\">self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">        print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">f</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"大家好，我叫 </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">{</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">name</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">}</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">。\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">baby1 </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> Baby</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">name</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"棠棠\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)  </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 实例化</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(baby1.name)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">baby1.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">introduce</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>上面的代码运行之后，是会报错的。有两个报错点，有一个报错还没来的及出来。报错如下：</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">init name: 棠棠</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">Traceback</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> (most recent call last):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">  File </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"/Users/huangjiabao/bornforthis.cn/demo.py\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, line </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">15</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> &lt;</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">module</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&gt;</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">    print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(baby1.name)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">          ^^^^^^^^^^</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#ABB2BF\">AttributeError</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'Baby'</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> object</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> has no attribute </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'name'</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>报错点1：代码 <code>baby1.name</code> 无法调用 name 属性值；</p>\n<p>报错点2：除 init 函数外，其它函数（introduce）无法使用用户传入的初始化参数。（init 初始化 <code>print(f\"init name: {name}\")</code> 正常输出）</p>\n<p>所以，使用 self 可以解决上面的两个报错点。</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">class</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> Baby</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    def</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> __init__</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E5C07B;--shiki-dark-font-style:italic\">self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> name</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">        self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.name </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> name</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">        print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">f</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"init name: </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">{</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.name</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">}</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> introduce</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E5C07B;--shiki-dark-font-style:italic\">self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">        print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">f</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"大家好，我叫 </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">{</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.name</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">}</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">。\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">baby1 </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> Baby</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">name</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"棠棠\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)  </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 实例化</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(baby1.name)  </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 输出: 棠棠</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">baby1.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">introduce</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()  </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 输出: 大家好，我叫 棠棠。</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div></li>\n<li>\n<p><strong>问题三解答</strong>：至于为什么要使用同名这个很简单，因为：懒。你叫其它变量名可以，但是你还得思考其它有没有合适的变量名，毕竟我们需要的变量名是：见名知意。故而：既然参数名是想好的，索性直接基于参数名加上 self 就可以了。代码示例：</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">class</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> Baby</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    def</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> __init__</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E5C07B;--shiki-dark-font-style:italic\">self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> name</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">        self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.name </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> name</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">        self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.username </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> name</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">        print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">f</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"init name: </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">{</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.name</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">}</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">, username: </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">{</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.username</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">}</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">baby1 </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> Baby</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">name</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"棠棠\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div></li>\n</ol>\n<h4>4.4.2 总结性讲解</h4>\n<p>在 <code>__init__</code> 方法中，我们通常会把用户传入的参数赋值给对象的属性，例如 <code>self.name = name</code>。这样做有几个主要原因：</p>\n<ol>\n<li><strong>保存信息以便后续使用</strong>：传入的参数 <code>name</code> 在 <code>__init__</code> 方法内仅是一个局部变量，作用域仅限于这个方法内部。如果不将其赋值给 <code>self.name</code>，当 <code>__init__</code> 执行完毕后，这个值就会丢失。而通过 <code>self.name = name</code>，我们将这个值保存到了对象的属性中，这样对象的其他方法就可以随时访问和使用这个信息，就像现实中宝宝的名字会被一直记录在出生证明上一样。</li>\n<li><strong>实现对象独立性</strong>：每个对象都有自己的状态和数据。当我们用 <code>self.name = name</code> 时，每个实例都会拥有自己的 <code>name</code> 属性，这样不同对象之间的数据互不干扰。比如两个宝宝虽然可能取相同的名字，但它们是两个独立的个体，彼此之间不会混淆。</li>\n<li><strong>提高代码的清晰性和可维护性</strong>：显式地将参数赋值给实例属性可以让代码更直观，读者一眼就能看出这个对象有哪些属性，并且这些属性是在创建对象时被初始化的。这种写法也符合 Python 的编程习惯，使代码更具可读性。</li>\n</ol>\n<p>下面通过一个代码示例来说明这一点：</p>\n<div class=\"language-python line-numbers-mode has-collapsed-lines collapsed\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--vp-collapsed-lines:15;--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 模拟现实中为宝宝取名字和准备出生证明的过程</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">class</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> Baby</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    def</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> __init__</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E5C07B;--shiki-dark-font-style:italic\">self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> name</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">        \"\"\"</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">        当宝宝出生之前，大人们已经为他取好了名字。</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">        这里的 __init__ 方法相当于在宝宝出生前给他准备好所有必要的信息，</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">        而 self.name = name 就像是把这个名字写入了宝宝的出生证明中。</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">        \"\"\"</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">        # 将传入的 name 参数赋值给当前对象的属性 self.name</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">        self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.name </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> name</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> introduce</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E5C07B;--shiki-dark-font-style:italic\">self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">        \"\"\"</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">        宝宝的自我介绍方法，用来展示初始化时设置的信息。</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">        这里使用 self.name 来引用对象保存的名字信息。</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">        \"\"\"</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">        print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">f</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"大家好，我叫 </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">{</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.name</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">}</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">。\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 实例化对象时传入参数</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">baby1 </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> Baby</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"小明\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">baby2 </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> Baby</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"小红\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 分别调用 introduce 方法，展示对象中保存的信息</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">baby1.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">introduce</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()  </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 输出: 大家好，我叫 小明。</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">baby2.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">introduce</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()  </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 输出: 大家好，我叫 小红。</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div><div class=\"collapsed-lines\"></div></div><p><strong>总结：</strong></p>\n<ul>\n<li><strong>局部变量与实例属性的区别：</strong> 在 <code>__init__</code> 方法中，<code>name</code> 是一个局部变量，而 <code>self.name</code> 是实例的属性。只有将 <code>name</code> 赋值给 <code>self.name</code>，我们才能在对象的其他方法中使用这个值。</li>\n<li><strong>对象的持久状态：</strong> <code>self.name = name</code> 确保了对象在其生命周期内能够持续保留这个信息，就像宝宝的名字一直伴随着他成长一样。</li>\n<li><strong>提高代码清晰度：</strong> 显式赋值让代码更加易于理解，明确标识出每个对象所拥有的属性和状态。</li>\n</ul>\n<p>这种做法不仅符合 Python 的面向对象编程习惯，还能帮助初学者更好地理解对象的概念和数据的持久化存储。</p>\n<h3>4.5 设定参数后，实例化时不给会怎么样？</h3>\n<p>如果在类的初始化函数 <code>__init__</code>中设定了参数，则必须在类的实例化时给出参数的值，否则代码会报错。一起看看下面的代码示例：</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">baby1 </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> Baby</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div></div></div><p>没有给出具体的参数，运行后会报错：</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">Traceback</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> (most recent call last):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">  File </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"/Users/huangjiabao/bornforthis.cn/demo.py\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, line </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">21</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> &lt;</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">module</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&gt;</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    baby1 </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> Baby</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">            ^^^^^^</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#ABB2BF\">TypeError</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: Baby.</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">__init__</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">() missing </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> required positional argument: </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'name'</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>所以，如果给初始化函数设置了参数，就必须在实例化时给参数赋值。除非我们给参数设置了默认值，后续会讲解到。</p>\n<h3>4.6 设置多个参数</h3>\n<p>上面的类还不完善，还需要考虑宝宝的性别。那么在类当中如果有多个初始化参数，和普通函数设置参数一样：直接用逗号分隔多个参数。看看下面的代码示例：</p>\n<div class=\"language-python line-numbers-mode has-collapsed-lines collapsed\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--vp-collapsed-lines:15;--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">class</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> Baby</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    def</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> __init__</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E5C07B;--shiki-dark-font-style:italic\">self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> name</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> gender</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">        \"\"\"</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">        初始化宝宝对象时，必须提供名字，性别。</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">        这就像是大人提前为宝宝取好名字，并在必要时办理出生证明。</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">        \"\"\"</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">        self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.name </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> name      </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 宝宝的名字，相当于出生证明中的名字</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">        self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.gender </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> gender  </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 宝宝的性别，可能提前确定</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> introduce</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E5C07B;--shiki-dark-font-style:italic\">self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">        \"\"\"</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">        宝宝的自我介绍方法，展示初始化时设置的属性。</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">        \"\"\"</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">        print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">f</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"大家好，我叫 </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">{</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.name</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">}</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">，我是一个 </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">{</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.gender</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">}</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> 宝宝。\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 模拟场景1：宝宝出生前，大人已经为他取好了名字和性别信息</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">baby1 </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> Baby</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">name</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"棠棠\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">gender</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"女\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">baby1.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">introduce</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()  </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 输出: 大家好，我叫 棠棠，我是一个 女 宝宝。</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 模拟场景2：宝宝出生前，大人已经为她取好了名字和性别信息</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">baby2 </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> Baby</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">name</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"锦奕\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">gender</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"男\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">baby2.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">introduce</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()  </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 输出: 大家好，我叫 锦奕，我是一个 男 宝宝。</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div><div class=\"collapsed-lines\"></div></div><h3>4.7 设置默认值</h3>\n<p>上面的类有个地方设计的不好，想想是什么地方？</p>\n<p>性别，我们怎么可能可以自己设定和提前知道呢。（提前知道是违法的呢）有时候性别不知道，所以类初始化时 gender 应该是一个可选项。也就是：类需要支持用户不填性别可以正常使用。</p>\n<p>这时，我们就需要设置默认值。不过这里设置默认值和函数设置默认值是一致的：</p>\n<ol>\n<li>\n<p>我们如果一开始设置了默认值，那么该参数后面的参数。都要设置默认值，否则会报错。</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">class</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> Baby</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    def</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> __init__</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E5C07B;--shiki-dark-font-style:italic\">self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> name</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">=</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'小悦'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> gender</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">=</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'男'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">        print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">f</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"大家好，我叫 </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">{</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">name</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">}</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">，我是一个 </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">{</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">gender</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">}</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> 宝宝。\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">baby1 </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> Baby</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>运行后输出：</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">大家好，我叫 小悦，我是一个 男 宝宝。</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div></div></div><p>我们来试试前面设置默认值，后面不设默认值：</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">class</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> Baby</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    def</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> __init__</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E5C07B;--shiki-dark-font-style:italic\">self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> name</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">=</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'小悦'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> gender</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">        print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">f</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"大家好，我叫 </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">{</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">name</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">}</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">，我是一个 </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">{</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">gender</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">}</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> 宝宝。\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">baby1 </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> Baby</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'小明'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'男'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)  </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 就算你实例化传入数据，也无济于事！</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>运行后会报错：</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">  File </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"/Users/huangjiabao/bornforthis.cn/demo.py\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, line </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    def</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> __init__</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E5C07B;--shiki-dark-font-style:italic\">self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> name</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">=</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'小悦'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> gender</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">                                  ^^^^^^</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#ABB2BF\">SyntaxError</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: non</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">default argument follows default argument</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div></li>\n<li>\n<p>如果一开始没有设置默认值，但是后续开始设置，那么后续设置的默认值都要一直设置。不能省略，否则会报错。</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">class</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> Baby</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    def</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> __init__</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E5C07B;--shiki-dark-font-style:italic\">self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> name</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> gender</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">None</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> age</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">None</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> weight</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">None</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">        self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.name </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> name</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">        self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.gender </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> gender</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">        self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.age </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> age</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">        self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.weight </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> weight</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">baby1 </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> Baby</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>运行后一切正常，不会有任何报错。如果此时把参数 age 之后的参数不设置默认值，则会报错：</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">class</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> Baby</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    def</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> __init__</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E5C07B;--shiki-dark-font-style:italic\">self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> name</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> gender</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">None</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> age</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">None</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> weight</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">        self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.name </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> name</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">        self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.gender </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> gender</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">        self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.age </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> age</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">        self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.weight </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> weight</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">baby1 </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> Baby</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>此时运行代码会直接报错：</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">  File </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"/Users/huangjiabao/bornforthis.cn/demo.py\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, line </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    def</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> __init__</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E5C07B;--shiki-dark-font-style:italic\">self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> name</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> gender</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">None</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> age</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">None</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> weight</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">                                                    ^^^^^^</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#ABB2BF\">SyntaxError</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: non</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">default argument follows default argument</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div></li>\n</ol>\n<p>所以，我们最终的 Baby 类可以编写成这样就会比较合适。性别是可选的：</p>\n<div class=\"language-python line-numbers-mode has-collapsed-lines collapsed\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--vp-collapsed-lines:15;--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">class</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> Baby</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    def</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> __init__</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E5C07B;--shiki-dark-font-style:italic\">self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> name</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> gender</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">None</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">        \"\"\"</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">        初始化宝宝对象时，必须提供名字，</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">        性别可以提前指定，也可以在宝宝出生时再确定。</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">        这就像是大人提前为宝宝取好名字，并在必要时办理出生证明。</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">        \"\"\"</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">        self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.name </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> name      </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 宝宝的名字，相当于出生证明中的名字</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">        self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.gender </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> gender  </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 宝宝的性别，可能提前确定，也可能待定</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> introduce</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E5C07B;--shiki-dark-font-style:italic\">self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">        \"\"\"</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">        宝宝的自我介绍方法，展示初始化时设置的属性。</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">        如果性别已知，则完整介绍；否则提示性别待定。</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">        \"\"\"</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        if</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\"> self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.gender:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">            print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">f</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"大家好，我叫 </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">{</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.name</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">}</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">，我是一个 </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">{</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.gender</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">}</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> 宝宝。\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        else</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">            print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">f</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"大家好，我叫 </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">{</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.name</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">}</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">，性别待定。\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 模拟场景1：宝宝出生前，大人已经为他取好了名字和性别信息</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">baby1 </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> Baby</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">name</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"棠棠\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">gender</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"女\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">baby1.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">introduce</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()  </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 输出: 大家好，我叫 棠棠，我是一个 女 宝宝。</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 模拟场景2：宝宝出生前，大人已经为她取好了名字和性别信息</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">baby2 </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> Baby</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">name</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"锦奕\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">gender</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"男\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">baby2.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">introduce</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()  </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 输出: 大家好，我叫 锦奕，我是一个 男 宝宝。</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 模拟场景3：宝宝出生前，大人只取好了名字，性别待定</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">baby3 </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> Baby</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">name</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"宝宝\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">baby3.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">introduce</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()  </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 输出: 大家好，我叫 宝宝，性别待定。</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div><div class=\"collapsed-lines\"></div></div><h2>5. 类实例化时：指定传参数和位置传参</h2>\n<p>其实，在前面的代码中已经演示过了。不过我还是单独讲解一下，类的传入参数的三种原则。</p>\n<ol>\n<li>\n<p>全部不指定参数</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">baby1 </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> Baby</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'小红'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'女'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">7.8</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div></div></div></li>\n<li>\n<p>全部指定参数</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">baby1 </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> Baby</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">name</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'小红'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">gender</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'女'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">age</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">weight</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">7.8</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div></div></div></li>\n<li>\n<p>部分指定参数，只能从前面不指定。后面一旦开始指定，后续都要指定。否则会报错，一起看看代码示例：</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">baby1 </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> Baby</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'小红'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'女'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">age</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">weight</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">7.8</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div></div></div><p>如果 age 后面不继续指定就会报错：</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">baby1 </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> Baby</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'小红'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'女'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">age</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">7.8</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)  </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 报错如下：SyntaxError: positional argument follows keyword argument</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div></div></div></li>\n</ol>\n<p>最后，我来补充一个。我没讲不代表不存在或不支持，类实例化参数可以通过变量传递进去：</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">name </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> input</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"Enter your name: \"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">gender </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> input</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"Enter your gender: \"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">age </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> input</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"Enter your age: \"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">weight </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> float</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">input</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"Enter your weight: \"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">))</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">baby1 </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> Baby</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(name, gender, age, weight)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">baby2 </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> Baby</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">name</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">name, </span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">gender</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">gender, </span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">age</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">age, </span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">weight</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">weight)</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><h2>6. 类内部函数设置参数</h2>\n<h3>6.1 设置单个函数</h3>\n<p><s>对于类内部的函数设置参数和初始化函数（init）语法一致：要在 self 之后添加参数即可，代码如下：</s></p>\n<p>对于类内部的函数，设置参数的语法和初始化函数 <code>__init__</code> 是一致的：只需在 <code>self</code> 后面添加你需要的参数即可。下面是一个示例：</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">class</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> Dog</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    def</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> __init__</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E5C07B;--shiki-dark-font-style:italic\">self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> name</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">        self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.name </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> name</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> bark</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E5C07B;--shiki-dark-font-style:italic\">self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> times</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">        print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">f</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">{</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.name</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">}</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> 汪\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> *</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> times)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 创建一个 Dog 实例</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">my_dog </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> Dog</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"小黑\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 调用类内部的函数并传入参数</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">my_dog.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">bark</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>运行结果：</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">小黑 汪小黑 汪小黑 汪</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div></div></div><p>在这个例子中：</p>\n<ul>\n<li><code>__init__</code> 方法用于初始化对象，并接收一个参数 <code>name</code>。</li>\n<li><code>bark</code> 是类中的另一个函数（也叫方法），它接受一个参数 <code>times</code>，用于指定狗叫的次数。</li>\n<li>无论是 <code>__init__</code> 还是 <code>bark</code>，参数的定义方式都是：在 <code>self</code> 后面继续添加即可。</li>\n</ul>\n<h3>6.2 设置第二个参数</h3>\n<p>我们可以对 bark 函数再添加一个参数 newline，一起来看看：</p>\n<div class=\"language-python line-numbers-mode has-collapsed-lines collapsed\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--vp-collapsed-lines:15;--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">class</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> Dog</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    def</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> __init__</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E5C07B;--shiki-dark-font-style:italic\">self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> name</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">        self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.name </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> name</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> bark</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E5C07B;--shiki-dark-font-style:italic\">self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> times</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> newline</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> _ </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> range</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(times):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">            if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> newline:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">                print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">f</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">{</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.name</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">}</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> 汪\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">            else</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">                print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">f</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">{</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.name</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">}</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> 汪\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">end</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\" \"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 创建一个 Dog 实例</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">my_dog </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> Dog</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"小黑\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 调用 bark 函数，传入两个参数：叫3次，并每次换行</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"每次换行：\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">my_dog.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">bark</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">True</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 调用 bark 函数，传入两个参数：叫3次，但不换行</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">\\n</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">不换行：\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">my_dog.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">bark</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">False</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div><div class=\"collapsed-lines\"></div></div><p>运行结果如下：</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">每次换行：</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">小黑 汪</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">小黑 汪</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">小黑 汪</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">不换行：</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">小黑 汪 小黑 汪 小黑 汪</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>如果想要更多参数，就以此类推即可。但是需要注意：如果设置了参数，在用户调用时，必须传入参数，否则会报错！除非设置默认值，接下来会讲。</p>\n<h3>6.3 默认参数</h3>\n<p>其实类里面的函数设置默认参数，和基本函数设置是一样的。给参数设置默认值，这样在调用函数时可以选择性传入。设置默认值后，用户在调用函数时，可以选择性传入参数。</p>\n<div class=\"language-python line-numbers-mode has-collapsed-lines collapsed\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--vp-collapsed-lines:15;--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">class</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> Dog</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    def</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> __init__</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E5C07B;--shiki-dark-font-style:italic\">self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> name</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">        self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.name </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> name</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> bark</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E5C07B;--shiki-dark-font-style:italic\">self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> times</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> newline</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">True</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> _ </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> range</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(times):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">            if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> newline:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">                print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">f</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">{</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.name</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">}</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> 汪\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">            else</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">                print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">f</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">{</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.name</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">}</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> 汪\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">end</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\" \"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 默认参数调用</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"默认只叫一次，并换行：\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">my_dog </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> Dog</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"小白\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">my_dog.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">bark</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">\\n</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">叫两次但不换行：\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">my_dog.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">bark</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">False</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div><div class=\"collapsed-lines\"></div></div><h3>6.4 小贴士</h3>\n<ol>\n<li>\n<p>类内部的函数（方法）可以定义多个参数，只需要按顺序写在 <code>self</code> 后面即可。</p>\n</li>\n<li>\n<p>调用方法时，也要按顺序传入对应的值。</p>\n</li>\n<li>\n<p>参数可以用来控制方法行为，使代码更灵活。</p>\n</li>\n<li>\n<p>类内部可以设置默认值，使参数变成可选。</p>\n</li>\n</ol>\n<h2>7. 通过实例化对象，修改类的属性值</h2>\n<p>我们可以通过实例化对象，不仅仅可以快速查询对应的属性值。我们还可以通过此方法，修改属性值。我们一起来看看代码，下面的代码是常规的实例化调用：</p>\n<div class=\"language-python line-numbers-mode has-collapsed-lines collapsed\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--vp-collapsed-lines:15;--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">class</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> Person</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    def</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> __init__</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E5C07B;--shiki-dark-font-style:italic\">self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> name</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> gender</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">None</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> age</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">None</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> weight</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">None</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">        self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.name </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> name</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">        self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.gender </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> gender</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">        self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.age </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> age</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">        self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.weight </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> weight</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> introduce</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E5C07B;--shiki-dark-font-style:italic\">self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">        intro </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> f</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"大家好，我叫 </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">{</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.name</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">}</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">。\"</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        if</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\"> self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.gender:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">            if</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\"> self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.gender </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">==</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> '男'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">                intro </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+=</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> \" 我是一个男孩。\"</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">            else</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">                intro </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+=</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> \" 我是一个女孩。\"</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        else</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">            intro </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+=</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> \" 我的性别暂时保密哦～\"</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        if</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\"> self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.age:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">            intro </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+=</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> f</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\" 我今年 </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">{</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.age</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">}</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> 岁了。\"</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        else</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">            intro </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+=</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> \" 我的年龄保密～\"</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        if</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\"> self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.weight:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">            intro </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+=</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> f</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\" 我的体重是 </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">{</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.weight</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">}</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> 千克。\"</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        else</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">            intro </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+=</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> \" 我的体重目前未知。\"</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">        print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(intro)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">person1 </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> Person</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">name</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'Bornforthis'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">gender</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'男'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">age</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">28</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">weight</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">75</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">person1.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">introduce</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div><div class=\"collapsed-lines\"></div></div><p>运行后会输出：</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">大家好，我叫 Bornforthis。 我是一个男孩。 我今年 </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">28</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> 岁了。 我的体重是 </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">75</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> 千克。</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div></div></div><p>接下来，我们来通过实例化对象 person1 来读取内部属性值：</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(person1.name, person1.gender, person1.age, person1.weight)</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div></div></div><p>运行后输出：</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">Bornforthis 男 </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">28</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 75</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div></div></div><p>我们接着通过实例化对象 person1 修改内部属性，并通过调用 <code>introduce()</code> 函数来输出验证：</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">class</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> Person</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    def</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> __init__</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E5C07B;--shiki-dark-font-style:italic\">self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> name</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> gender</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">None</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> age</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">None</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> weight</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">None</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">        self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.name </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> name</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">        self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.gender </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> gender</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">        self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.age </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> age</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">        self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.weight </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> weight</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> introduce</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E5C07B;--shiki-dark-font-style:italic\">self</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">        #</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div>",
      "date_published": "2025-05-04T19:55:33.000Z",
      "date_modified": "2025-05-07T14:30:07.000Z",
      "authors": [
        {
          "name": "AI悦创"
        }
      ],
      "tags": []
    },
    {
      "title": "03-元组内容补充",
      "url": "https://bornforthis.cn/Books/02-SupplementaryArticles/Python/03-Tuple.html",
      "id": "https://bornforthis.cn/Books/02-SupplementaryArticles/Python/03-Tuple.html",
      "summary": "1. 元组常见的内置函数 点击展开阅读 1. count() 统计元素在元组中出现的次数。 语法： 示例： 2. index() 返回元素首次出现的索引位置。 语法： 示例： 3. 内置函数 len() 返回元组元素数量。 语法： 示例： 4. 内置函数 max() 和 min() 返回元组中最大和最小元素。 语法： 示例： 5. 内置函数 sum()...",
      "content_html": "<h2>1. 元组常见的内置函数</h2>\n<details class=\"hint-container details\"><summary>点击展开阅读</summary>\n<h3>1. count()</h3>\n<ul>\n<li>统计元素在元组中出现的次数。</li>\n</ul>\n<p>语法：</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">tuple</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">count</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(item)</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div></div></div><p>示例：</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">t </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> (</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(t.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">count</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">))  </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 输出: 3</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><h3>2. index()</h3>\n<ul>\n<li>返回元素首次出现的索引位置。</li>\n</ul>\n<p>语法：</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">tuple</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">index</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(item[, start[, end]])</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div></div></div><p>示例：</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">t </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> (</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'a'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'b'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'c'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'b'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'d'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(t.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">index</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'b'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">))      </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 输出: 1</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(t.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">index</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'b'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">))   </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 输出: 3，从索引2开始查找</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><h3>3. 内置函数 len()</h3>\n<ul>\n<li>返回元组元素数量。</li>\n</ul>\n<p>语法：</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">tuple</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div></div></div><p>示例：</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">t </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> (</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">4</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(t))  </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 输出: 4</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><h3>4. 内置函数 max() 和 min()</h3>\n<ul>\n<li>返回元组中最大和最小元素。</li>\n</ul>\n<p>语法：</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">max</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">tuple</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">min</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">tuple</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>示例：</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">t </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> (</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">10</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">20</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">5</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">15</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">max</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(t))  </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 输出: 20</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">min</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(t))  </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 输出: 5</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><h3>5. 内置函数 sum()</h3>\n<ul>\n<li>返回元组中元素之和。</li>\n</ul>\n<p>语法：</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">sum</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(tuple[, start])</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div></div></div><p>示例：</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">t </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> (</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">4</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">sum</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(t))      </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 输出: 10</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">sum</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(t, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">10</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">))  </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 输出: 20，从10开始累加</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><h3>6. 内置函数 sorted()</h3>\n<ul>\n<li>返回排序后的<strong>列表</strong>（元组本身不可变，不影响原元组）。</li>\n</ul>\n<p>语法：</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">sorted</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(tuple[, key][, reverse])</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div></div></div><p>示例：</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">t </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> (</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">sorted_t </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> sorted</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(t)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(sorted_t)  </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 输出: [1, 2, 3]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(t)         </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 输出: (3, 1, 2)，原元组不变</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><h3>7. 元组连接（<code>+</code>）</h3>\n<ul>\n<li>连接两个元组产生新元组。</li>\n</ul>\n<p>示例：</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">t1 </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> (</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">t2 </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> (</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">4</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">t3 </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> t1 </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> t2</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(t3)  </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 输出: (1, 2, 3, 4)</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><h3>8. 元组重复（<code>*</code>）</h3>\n<ul>\n<li>重复元组中的元素。</li>\n</ul>\n<p>示例：</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">t </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> (</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(t </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">*</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> 3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)  </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 输出: (1, 2, 1, 2, 1, 2)</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><h3>9. 成员检测（<code>in</code> 和 <code>not in</code>）</h3>\n<ul>\n<li>检查元素是否在元组内。</li>\n</ul>\n<p>示例：</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">t </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> (</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'apple'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'banana'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'banana'</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> in</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> t)      </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># True</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'orange'</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> not</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> in</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> t)  </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># True</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><h3>10. 元组切片</h3>\n<ul>\n<li>提取元组的子序列。</li>\n</ul>\n<p>示例：</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">t </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> (</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">4</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(t[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">4</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">])   </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># (1, 2, 3)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(t[::</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">])  </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># (4, 3, 2, 1, 0)</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><h3>11. 元组拆包（unpacking）</h3>\n<ul>\n<li>将元组元素分别赋给多个变量。</li>\n</ul>\n<p>示例：</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">t </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> (</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">10</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">20</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">30</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">a, b, c </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> t</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(a, b, c)  </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 10 20 30</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><h3>12. 嵌套元组</h3>\n<ul>\n<li>元组内嵌套元组。</li>\n</ul>\n<p>示例：</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">t </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> (</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, (</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">), </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">4</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(t[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">][</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">])  </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 2</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><h3>13. any() 和 all()</h3>\n<ul>\n<li>判断元组元素真值。</li>\n</ul>\n<p>示例：</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">t1 </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> (</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">False</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">''</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">t2 </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> (</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">True</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">''</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">any</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(t1))  </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># False</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">any</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(t2))  </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># True</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">all</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">((</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)))  </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># True</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">all</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">((</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)))  </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># False</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><h3>14. tuple() 转换函数</h3>\n<ul>\n<li>将其他可迭代对象转换为元组。</li>\n</ul>\n<p>示例：</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">lst </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> [</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">t </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> tuple</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(lst)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(t)  </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># (1, 2, 3)</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><h3>15. 元组与列表相互转换（常用）</h3>\n<ul>\n<li>元组不可变，若想修改内容，可先转换为列表再改回元组。</li>\n</ul>\n<p>示例：</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">t </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> (</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">lst </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> list</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(t)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">lst.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">append</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">4</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">t </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> tuple</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(lst)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(t)  </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># (1, 2, 3, 4)</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><h3>16. 常见函数和方法速览表</h3>\n<p>| 序号 | 内置函数名称或操作     | 功能说明                 | 使用代码示例              |<br>\n|</p>\n</details>\n",
      "date_published": "2025-05-03T16:49:55.000Z",
      "date_modified": "2025-05-07T11:20:58.000Z",
      "authors": [
        {
          "name": "AI悦创"
        }
      ],
      "tags": []
    },
    {
      "title": "02-列表内容补充",
      "url": "https://bornforthis.cn/Books/02-SupplementaryArticles/Python/02-list.html",
      "id": "https://bornforthis.cn/Books/02-SupplementaryArticles/Python/02-list.html",
      "summary": "1. 列表的深浅拷贝 点击展开阅读 1. y = x 所存在的问题，是真的备份吗？ 阅读下面的代码，思考下面两个问题： 问题1：这段代码的意图是什么？开发者希望实现什么效果？ 问题2：代码的输出结果是什么？是否符合预期？ 注意： 下面的代码我是有意写这么长的字符串，有两个目的： 目的一：为了带你回顾一个字符串格式化、转义的用法！ 目的二：方便我们后续观...",
      "content_html": "<h2>1. 列表的深浅拷贝</h2>\n<details class=\"hint-container details\"><summary>点击展开阅读</summary>\n<h3>1. <code>y = x</code> 所存在的问题，是真的备份吗？</h3>\n<p>阅读下面的代码，思考下面两个问题：</p>\n<ul>\n<li>问题1：这段代码的意图是什么？开发者希望实现什么效果？</li>\n<li>问题2：代码的输出结果是什么？是否符合预期？</li>\n</ul>\n<p><strong>注意：</strong> 下面的代码我是有意写这么长的字符串，有两个目的：</p>\n<ul>\n<li>目的一：为了带你回顾一个字符串格式化、转义的用法！</li>\n<li>目的二：方便我们后续观察找出问题；</li>\n</ul>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">x </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> [</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'毒药'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'感冒药'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'解药'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">y </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> x</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">f</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'Original:</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">\\n\\t</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">x: </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">{</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">x</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">}</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">\\n\\t</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">y: </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">{</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">y</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">}</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">\\n\\t</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">id_x: </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">{</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">id</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(x)</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">}</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">\\t</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">id_y: </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">{</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">id</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(y)</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">}</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)  </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># id() 用来获取变量的物理地址</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">y[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">] </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> '消炎药'</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">f</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'After:</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">\\n\\t</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">x: </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">{</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">x</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">}</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">\\n\\t</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">y: </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">{</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">y</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">}</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">\\n\\t</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">id_x: </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">{</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">id</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(x)</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">}</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">\\t</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">id_y: </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">{</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">id</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(y)</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">}</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>阅读到此，想必你有了你自己的思考。我们现在来看看，我对于上面两个问题的回答。</p>\n<h4>1.1 问题1</h4>\n<p>从代码 <code>y = x</code> 可知，开发者想要复制一个 x 列表的副本给变量 y 并且想要修改列表 y 时不影响原列表 x。换句话说，y 应该是 x 的一个独立备份。</p>\n<p>为什么我们会有这种需求？让我们结合现实场景来思考。</p>\n<p>假设你有一个包含 <strong>100万条数据</strong>的 Excel 文件，<s>为下载这个数据文件</s>获取这个文件的代价极高：</p>\n<ol>\n<li>你需要<strong>花费1000元</strong>；</li>\n<li>下载<strong>耗费3个小时</strong>；</li>\n<li>并且1000元<strong>只能下载一次</strong>，数据丢失想要重新下载需要重新付费；</li>\n</ol>\n<p>注意：这里我是特意这么夸张，请不要想其它的。我只是为了让你尽可能感觉到这个数据是多么昂贵的，并且获取这个数据所要付出的代价是巨大的，因为只有昂贵才会重视，便于我塑造情景。</p>\n<p>这里再次强调：如果再下载一次还是需要 1000元、下载耗费3个小时、并且还是只能下载一次。此时你要操作这个拥有 100万数据且下载成本极高的 Excel 会怎么操作？</p>\n<p>阅读到此时，请停顿一下。思考一下，在这种情况下，你会怎么做？</p>\n<p>毫无疑问，肯定是在操作前做一个<strong>备份</strong>，以便在操作时：如果不小心手贱按错按键，或者破电脑突然卡住导致你操作的数据没有及时保存或关闭等情况，导致数据缺失或损坏。此时就需要使用备份文件来恢复，这样就避免重新获取数据而产生的高额代价。所以在上面的代码中也是这样的意图，列表 x 作为备份数据，以确保对 y 的修改不会影响到原始数据 x，以此保证原数据不被影响。</p>\n<h4>1.2 问题2</h4>\n<p>对于问题2请先观察下面的代码实际输出，看看输出结果中存在什么问题和特点？</p>\n<p><strong>注意</strong>：观察下面的代码时你要具备一个原则：<strong>有时候，不要只看局部。站的高点，站的远点，使我们有全局视角，这样往往更便于我们发现事物中所存在的关联关系或规律。</strong></p>\n<p>意思就是：你在观察下面的输出结果时，不要单纯的一行一行看，或者看完下一行忘记上一行。要把自己从中抽离出来，看整个输出。去及时的观察和对比，这样才能发现其中的规律或者存在的问题。</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">Original:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">\tx: [</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'毒药'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'感冒药'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'解药'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">\ty: [</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'毒药'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'感冒药'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'解药'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">\tid_x: </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">4470743680</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">\tid_y:</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">4470743680</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">After:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">\tx: [</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'消炎药'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'感冒药'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'解药'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">\ty: [</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'消炎药'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'感冒药'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'解药'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">\tid_x: </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">4470743680</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">\tid_y:</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">4470743680</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>我们会发现，当我们修改 y 列表中的第一个元素后，<strong>x 列表的内容也发生了变化</strong>，这显然不符合我们的预期。理论上，我们的目标是 <strong>仅修改 y，不影响 x</strong>，但结果表明 <strong>x 和 y 竟然是同一个列表！</strong></p>\n<p>为什么会产生这个<s>问题</s>情况呢？我们可以从 <code>id()</code> 函数的输出中找到答案。</p>\n<p>从上面的输出结果可知：列表 x 和列表 y 的物理地址是相同的，意味着虽然做了备份（<code>y = x</code>），但没想到列表 x 和 y 是指向同一个列表，故而导致修改列表 y 时，列表 x 的数据也被修改。与我们原本的意图（备份）事与愿违，并且产生了“巨大”代价！明显我们的代码不符合预期。</p>\n<p>从上面的分析后，我们可知 <code>y = x</code> 只是进行了列表地址的赋值（类似引用），x、y 实际上指向的是同一个列表。可以理解成两个列表元素一样，Python 就偷懒不再创建一个新的相同列表，直接创建一个地址引用。</p>\n<p>为了更直观地理解这个问题，我们可以借助一个现实生活中的类比：</p>\n<ul>\n<li>假设你在百度网盘中 <strong>已经上传了一个文件</strong>，然后你又想要“上传”相同的文件。</li>\n<li>但百度网盘发现，这个文件已经存在，它 <strong>不会真正再上传一次</strong>，而是 <strong>直接在你的账户中创建一个链接</strong>，指向已经存在的文件。</li>\n<li>这样，你看到自己网盘中有两个相同的文件，但实际上它们 <strong>指向的是同一个数据</strong>，修改其中一个，另一个也会随之变化。</li>\n</ul>\n<p>Python 在 <code>y = x</code> 赋值时的行为类似于百度网盘的“创建链接”机制：并没有真正复制列表，而只是让 <code>y</code> 指向了 <code>x</code>，所以 <code>x</code> 和 <code>y</code> 变成了 <strong>同一个对象的两个引用</strong>。</p>\n<h4>1.3 归整一下</h4>\n<p>上面分析了一下，接下来我来给你归整归整。我们说列表 x 和列表 y 指向的是同一个变量，我们口说无凭，来看看下面的凭证：</p>\n<ol>\n<li>\n<p><strong>证明一</strong>：Python <code>id()</code> 用来检查变量物理地址（也就是在计算机中，所在的位置）并结合上面的代码结果可知：x、y 指向的是同一个列表，因为 id 相同。（<code>id_x: 4470743680</code>、<code>id_y:4470743680</code>）</p>\n</li>\n<li>\n<p><strong>证明二</strong>：可以直接使用<a href=\"https://pythontutor.bornforthis.cn/visualize.html#mode=edit\" target=\"_blank\" rel=\"noopener noreferrer\">可视化</a>：<a href=\"https://pythontutor.bornforthis.cn/visualize.html#mode=edit\" target=\"_blank\" rel=\"noopener noreferrer\">https://pythontutor.bornforthis.cn/visualize.html#mode=edit</a>查看，毕竟一图胜千言。在可视化界面中（下图），你会发现 <code>x</code> 和 <code>y</code> 其实是 <strong>同一个列表对象的两个名称</strong>，本质上它们没有区别。因此，修改 <code>y</code> 也会影响 <code>x</code>，这就是问题的根本原因。</p>\n</li>\n</ol>\n<figure><figcaption></figcaption></figure>\n<p>有时候，不要只看局部。站的高点，站的远点，使我们有全局视角，这样往往更便于我们发现事物中所存在的关联关系或规律。——AI悦创 2024-01-01 23:17:10</p>\n<h4>1.4 关键问题：如何正确创建副本？</h4>\n<p>既然 <code>y = x</code> 不能满足我们“创建副本”的需求，那么 <strong>如何正确地复制一个列表，而不影响原列表呢？</strong></p>\n<p>别担心，我们接下来就会深入探讨 <strong>Python 中的深拷贝与浅拷贝</strong>，以及 <strong>如何避免此类问题</strong>。</p>\n<h3>2. 使用 <code>copy()</code> 进行浅拷贝</h3>\n<h4>2.1 代码实现</h4>\n<p>在前面的内容中，我们发现 <strong>直接赋值 <code>y = x</code> 并不会创建一个新的列表</strong>，而只是让 <code>y</code> 指向 <code>x</code>，导致修改 <code>y</code> 的同时 <code>x</code> 也会被修改。这显然不符合我们的备份需求。</p>\n<p>那么，如何正确创建一个<strong>新的副本</strong>，确保 <code>y</code> 和 <code>x</code> 互不影响呢？为了解决这个问题，我们可以使用列表自带的 <code>copy()</code> 方法，这会创建一个“浅拷贝”（shallow copy），从而获得一个独立的对象副本。</p>\n<p>让我们看看使用 <code>copy()</code> 进行列表复制的效果：</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">x </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> [</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'毒药'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'感冒药'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'解药'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">y </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> x.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">copy</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">f</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'Original:</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">\\n\\t</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">x: </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">{</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">x</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">}</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">\\n\\t</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">y: </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">{</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">y</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">}</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">\\n\\t</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">id_x: </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">{</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">id</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(x)</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">}</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">\\t</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">id_y:</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">{</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">id</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(y)</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">}</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)  </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># id 用来获取变量的物理地址</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">y[</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">] </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> '消炎药'</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">f</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'After:</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">\\n\\t</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">x: </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">{</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">x</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">}</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">\\n\\t</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">y: </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">{</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">y</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">}</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">\\n\\t</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">id_x: </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">{</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">id</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(x)</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">}</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">\\t</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">id_y:</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">{</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">id</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(y)</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">}</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>代码输出如下：</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">Original:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">\tx: [</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'毒药'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'感冒药'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'解药'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">\ty: [</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'毒药'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'感冒药'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'解药'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">\tid_x: </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">4428223616</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">\tid_y:</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">4428537536</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">After:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">\tx: [</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'毒药'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'感冒药'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'解药'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">\ty: [</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'消炎药'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'感冒药'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'解药'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">\tid_x: </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">4428223616</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">\tid_y:</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">4428537536</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><h4>2.2 结果分析</h4>\n<p>从输出结果来看，我们可以发现两个重要的现象：</p>\n<ol>\n<li><code>id_x</code> 和 <code>id_y</code> 变了：<strong>初始状态</strong>下，<code>x</code> 和 <code>y</code> 的内容完全相同，但物理地址（<code>id_x</code> 和 <code>id_y</code>）已经 <strong>不再相同</strong>，这表示 <code>copy()</code> 方法为 <code>y</code> 创建了一个全新的列表对象。<code>y</code> 和 <code>x</code> 现在是<strong>两个独立的对象</strong>，互不影响。</li>\n<li>修改 <code>y</code> 后，<code>x</code> 没有被影响：之前 <code>y = x</code> 时，修改 <code>y[0]</code> 为 <code>'消炎药'</code> 时会影响 <code>x[0]</code>，但现在 <code>y</code> 已经是 <code>x</code> 的一个独立副本，因此修改 <code>y</code> <strong>不会影响 <code>x</code></strong>，这正是我们想要的备份效果。</li>\n</ol>\n<h4>2.3 为什么说是“浅拷贝”？</h4>\n<p><code>copy()</code> 方法在 Python 中执行的是 <strong>浅拷贝（Shallow Copy）</strong>。它的本质是 <strong>创建一个新的列表对象，并将原列表中的元素引用复制到新列表中</strong>。简单来说：</p>\n<ul>\n<li><code>copy()</code> <strong>复制了列表本身</strong>，即创建了一个新的 <code>y</code>。</li>\n<li>但 <strong>它并不会复制列表中的元素</strong>，而是让 <code>y</code> 里的元素仍然指向 <code>x</code> 里的同样的元素。如果列表中包含可变的嵌套对象（如列表里还有列表、元组、字典等），这些 <strong>子对象依旧是原来对象的引用</strong>。也就是说，对同一层级的数据做了拷贝，但 <strong>更深层次</strong> 的数据结构还会被引用到原对象。</li>\n<li>对于目前这种 <strong>单层列表</strong>，我们可以把 <code>.copy()</code> 当作和“深拷贝”一样使用，但是前提是：列表的元素都是字符串、数字型、布尔型等不可变数据类型，并没有深层的嵌套结构，自然也就不会出现意料之外的相互影响。</li>\n</ul>\n<p>这可能有点绕，我们可以用下面的图示帮助理解：</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">原列表 x:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">x</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div></details>\n",
      "date_published": "2025-05-03T09:46:57.000Z",
      "date_modified": "2025-05-07T11:20:58.000Z",
      "authors": [
        {
          "name": "AI悦创"
        }
      ],
      "tags": []
    },
    {
      "title": "03-ChatGLM3-6B 基础法律大模型微调",
      "url": "https://bornforthis.cn/column/Python-Programming-Course/P05-AI-large-model/04-Model-Fine-tuning-How-to-Build-a-Large-Model-of-Basic-Legal-Knowledge-Based-on-ChatGLM3-6B-Lora.html",
      "id": "https://bornforthis.cn/column/Python-Programming-Course/P05-AI-large-model/04-Model-Fine-tuning-How-to-Build-a-Large-Model-of-Basic-Legal-Knowledge-Based-on-ChatGLM3-6B-Lora.html",
      "summary": "前面我们本地化部署了 ChatGLM3-6B，对于大模型有了进一步的了解。 目前我们接触的无论是千亿大模型，如 130B、ChatGPT，还是小规模的大模型，如 6B、LLaMA2，都是通用大模型，就是说通过通用常识进行预训练的，如果我们在实际使用过程中，需要大模型具备某一特定领域知识的能力，我们就需要对大模型进行能力增强，具体如何做呢？ 1. 如何增...",
      "content_html": "<p>前面我们本地化部署了 ChatGLM3-6B，对于大模型有了进一步的了解。</p>\n<p>目前我们接触的无论是千亿大模型，如 130B、ChatGPT，还是小规模的大模型，如 6B、LLaMA2，都是通用大模型，就是说通过通用常识进行预训练的，如果我们在实际使用过程中，需要大模型具备某一特定领域知识的能力，我们就需要对大模型进行能力增强，具体如何做呢？</p>\n<h2>1. 如何增强模型能力？</h2>\n<p>微调只是众多优化大模型能力的方法之一，除此之外，还有其他方式，比如接入外挂知识库，或者借助 Agent 调用外部 API 数据源。下面我们来具体看看这些方法的不同之处。</p>\n<ul>\n<li>\n<p><strong>微调</strong>指的是在已有预训练模型的基础上，通过特定任务的数据再次训练，使模型更好地适应特定场景。这种方式相对成本较低，模型能够从训练数据中学习特定领域的表达和逻辑，具备一定的语义理解能力。</p>\n</li>\n<li>\n<p><strong>知识库</strong>通过构建向量数据库或其他结构化数据源，为大模型提供一个额外的信息查找渠道，充当“外挂记忆”。</p>\n</li>\n<li>\n<p><strong>API 接入</strong>与知识库类似，也是为模型提供实时信息的外部接口，能够扩展模型的知识边界。</p>\n</li>\n</ul>\n<p>可以这样理解：微调就像是给大模型上了一门新课程，并让它在答题时进行闭卷考试；而知识库和 API 则更像是给模型准备好了教材和工具书，考试时可以随查随用。几种方式并不冲突，我们完全可以将它们结合使用，以提升模型的输出质量和任务处理能力。下面我们就来简要对比这些方式的优劣势。</p>\n<p>| 方法                             | 优点 👍                                                       | 缺点 👎                                                       |<br>\n|</p>\n",
      "date_published": "2025-04-30T12:13:12.000Z",
      "date_modified": "2025-06-01T12:32:57.000Z",
      "authors": [
        {
          "name": "AI悦创"
        }
      ],
      "tags": []
    },
    {
      "title": "01-安装包下载及其资源",
      "url": "https://bornforthis.cn/Books/04-BookResources/01-InstallationPackage.html",
      "id": "https://bornforthis.cn/Books/04-BookResources/01-InstallationPackage.html",
      "summary": "1. 软件及其数据资源下载地址 提示 长期维护更新，随时评论留言！ 百度网盘下载地址：https://pan.baidu.com/s/1tE6dqpvMxCq88N_aOBlRqA?pwd=aiyc 2. 环境安装视频教程 视频安装教程：自己选择对应的系统安装，这部分视频安装还是比文字版好 国内 B 站：https://www.bilibili.com...",
      "content_html": "<h2>1. 软件及其数据资源下载地址</h2>\n<div class=\"hint-container tip\">\n<p class=\"hint-container-title\">提示</p>\n<p>长期维护更新，随时评论留言！</p>\n</div>\n<p>百度网盘下载地址：<a href=\"https://pan.baidu.com/s/1tE6dqpvMxCq88N_aOBlRqA?pwd=aiyc\" target=\"_blank\" rel=\"noopener noreferrer\">https://pan.baidu.com/s/1tE6dqpvMxCq88N_aOBlRqA?pwd=aiyc</a></p>\n<div class=\"language-text line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"text\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-text\"><span class=\"line\"><span>通过网盘分享的文件：出版书籍资源</span></span>\n<span class=\"line\"><span>链接: https://pan.baidu.com/s/1tE6dqpvMxCq88N_aOBlRqA?pwd=aiyc 提取码: aiyc</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><h2>2. 环境安装视频教程</h2>\n<p>视频安装教程：自己选择对应的系统安装，这部分视频安装还是比文字版好</p>\n<ol>\n<li>国内 B 站：<a href=\"https://www.bilibili.com/video/BV1Gu411G7UA/\" target=\"_blank\" rel=\"noopener noreferrer\">https://www.bilibili.com/video/BV1Gu411G7UA/</a></li>\n<li>国外 Youtobe：<a href=\"https://youtube.com/playlist?list=PLv9xf2Yw5poEXCS8rKOGTYWiNu4FtS_Re&amp;si=qKysjmk1JknMC8YY\" target=\"_blank\" rel=\"noopener noreferrer\">https://youtube.com/playlist?list=PLv9xf2Yw5poEXCS8rKOGTYWiNu4FtS_Re&amp;si=qKysjmk1JknMC8YY</a></li>\n</ol>\n<h2>3. Other 评论</h2>\n<p>关于其它的问题，评论区留言即可。</p>\n",
      "date_published": "2025-04-29T11:57:04.000Z",
      "date_modified": "2025-05-11T03:27:57.000Z",
      "authors": [
        {
          "name": "AI悦创"
        }
      ],
      "tags": []
    },
    {
      "title": "01-🍖烧烤系列",
      "url": "https://bornforthis.cn/column/cookdinner/P04-%E7%83%A7%E7%83%A4%E7%B1%BB/01-%E7%83%A7%E7%83%A4%E7%B3%BB%E5%88%97.html",
      "id": "https://bornforthis.cn/column/cookdinner/P04-%E7%83%A7%E7%83%A4%E7%B1%BB/01-%E7%83%A7%E7%83%A4%E7%B3%BB%E5%88%97.html",
      "summary": "1. 小林哥 烤肉，蒜不嫌多！ 食材准备：葱、姜、蒜、洋葱丝、五花肉、牛肉。 2. 夏叔",
      "content_html": "<h2>1. 小林哥</h2>\n<p>烤肉，蒜不嫌多！</p>\n<p>食材准备：葱、姜、蒜、洋葱丝、五花肉、牛肉。</p>\n\n<h2>2. 夏叔</h2>\n\n",
      "date_published": "2025-04-16T13:52:33.000Z",
      "date_modified": "2025-05-10T10:03:21.000Z",
      "authors": [
        {
          "name": "AI悦创"
        }
      ],
      "tags": []
    },
    {
      "title": "Assignment 6： Pawns on the World Stage – Pawns Board, part 2",
      "url": "https://bornforthis.cn/1v1/93-LiquidLeon/Assignment6-Pawns-on-the-World-Stage-Pawns-Board-part2.html",
      "id": "https://bornforthis.cn/1v1/93-LiquidLeon/Assignment6-Pawns-on-the-World-Stage-Pawns-Board-part2.html",
      "summary": "1. Purpose In this portion of the project, you will be building a visual view of your game, and also start building the computer strategies for playing the game. This assignment...",
      "content_html": "<h2>1. Purpose</h2>\n<p>In this portion of the project, you will be building a visual view of your game, and also start building the computer strategies for playing the game. This assignment has several parts. Look over the outline on the left, and skim through the whole assignment, before diving deeply into any one section. The assignment lists requirements in the recommended order you should do them, but future tasks might give you ideas for how to improve earlier ones.</p>\n<h2>2. Preparation: fixing up your models</h2>\n<h3>2.1 Making your models read-only</h3>\n<p>As we discussed in class, views should not have the ability to mutate the models they are viewing: this would bypass the controller, making it impossible to reliably control the model.</p>\n<p>Refactor your model interface, if necessary, into two interfaces: your <code>PawnsBoardModel</code> interface (or whatever you named it) should now extend a <code>ReadonlyPawnsBoardModel</code> interface (again, choose a name that matches your existing model). The read-only interface should contain all the observation methods of your model, while the mutable sub-interface should contain all the mutator methods.</p>\n<h3>2.2 Adding missing functionality</h3>\n<p>The following is a non-exhaustive checklist of functionality that is necessary for Pawns Board to work properly. Your model interface(s) may not yet expose all of these as methods, or might not make it easy to use.</p>\n<ul>\n<li>Model setup:\n<ul>\n<li>The ability to create a game using the configuration files for the decks</li>\n<li>The ability to create a copy of the board (and any mutable contents therein)</li>\n</ul>\n</li>\n<li>Observations:\n<ul>\n<li>How big is the grid?</li>\n<li>What are the contents of a cell at a given coordinate?</li>\n<li>What are the contents of a player’s hand?</li>\n<li>Which player owns the card or pawns in a cell at a given coordinate?</li>\n<li>Is it legal for the current player to play a given card (via an actual card or an index) at a given coordinate?</li>\n<li>Given a row index, what is a player’s row-score in the game for that row?</li>\n<li>What is a player’s current score in the game?</li>\n<li>Is the game over?</li>\n<li>Which player won, if any?</li>\n</ul>\n</li>\n<li>Operations:\n<ul>\n<li>The current player plays a card from their hand to a given coordinate on the board</li>\n<li>The current player passes their turn</li>\n</ul>\n</li>\n</ul>\n<p>Reexamine the design and implementation of your model from the previous assignment, and improve it to include the functionality above. Document whatever changes you made in a <em>new section of your README</em>, entitled “Changes for part 2” — explain what functionality was missing, and why, and how you chose to add it.</p>\n<h2>3. Visualizing the game</h2>\n<p>To implement your view, you will need to use Java Swing. (You are <em>not</em> permitted to use the <code>javalib</code> library we used in Fundies 2, as it conflates the notions of model, view and controller into a single <code>World</code> class. You are also not permitted to use JavaFX, as that has been deprecated and is overly complicated as well.) The code provided with the <a href=\"https://course.ccs.neu.edu/cs3500/lec/gui_basics/code.zip\" target=\"_blank\" rel=\"noopener noreferrer\">MVC code</a> and the <a href=\"https://course.ccs.neu.edu/cs3500/lec/12-turtles-activity/code.zip\" target=\"_blank\" rel=\"noopener noreferrer\">Turtles activity</a> from class give you a basic beginning using Swing, as well as the exercises in <a href=\"https://course.ccs.neu.edu/cs3500/labs_gui_tutorial_lab.html\" target=\"_blank\" rel=\"noopener noreferrer\">Lab 7</a>.</p>\n<p>You have also been provided with an extensive list of different Swing layouts, components, and their uses in the code linked at the start of the assignment. If you need a more visual way of seeing Swing things done, here is a video covering a lot of basic <a href=\"https://youtu.be/Kmgo00avvEw?si=7sJTwb8MuAoDciRl\" target=\"_blank\" rel=\"noopener noreferrer\">Java Swing components and listeners</a>. Note that if you try to write your code in the way shown in the video or in the way shown in the given code above, you will not do well on the assignment. The video does not follow our design rules nor style rules nor separates code properly into the three components. The code given has no helpers at all nor follows any of our design considerations.</p>\n<ul>\n<li>You will likely need to look up documentation on <a href=\"https://docs.oracle.com/javase/tutorial/2d/\" target=\"_blank\" rel=\"noopener noreferrer\"><code>Graphics</code></a> class, and you may need to explicitly cast <code>Graphics</code> objects to <code>Graphics2D</code> objects. Also look at the “transform” methods available in the <code>Graphics2D</code> class to use the rendering canvas appropriately.</li>\n<li>Here are links to documentation on <a href=\"https://docs.oracle.com/javase/tutorial/uiswing/components/panel.html\" target=\"_blank\" rel=\"noopener noreferrer\"><code>Panel</code>s</a> and <a href=\"https://docs.oracle.com/javase/tutorial/uiswing/components/frame.html\" target=\"_blank\" rel=\"noopener noreferrer\"><code>Frame</code>s</a>.</li>\n<li>Swing defines three template methods by which you can customize the size of panels or frames: <code>getMinimumSize</code>, <code>getPreferredSize</code> and <code>getMaximumSize</code>. Of these, the most common to override is <code>getPreferredSize</code>.</li>\n</ul>\n<p>You will likely need to design at least one, and possibly three, interfaces for your view: one should describe what the <em>frame</em> ought to be capable of, and one for each panel might be needed to describe what the <em>panel</em> ought to be capable of. (These may be empty interfaces for now, if you do not see a need for any methods in them yet...but keep reading below for additional ideas.) Note that your textual rendering from the previous assignment does not have to implement this new GUI view interface, and you do not have to force it to do so.</p>\n<h3>3.1 Required appearance</h3>\n<p>Your view should give as much information as the screenshots below, but the physical appearance is up to you. Consider the following screenshot which shows the start of the game. Notice we can see the board and the pawns on each, row-scores, and the hand of the Red player.</p>\n<figure><figcaption></figcaption></figure>\n<p>Here is a view of the game mid-game, also on Red’s turn:</p>\n<figure><figcaption></figcaption></figure>\n<p>Here is a view of the same game mid-game, but on Blue’s turn. Notice that Blue’s cards have their influence grid already mirrored.</p>\n<figure><figcaption></figcaption></figure>\n<p>And reminder that the game can be more than 3 rows with 5 columns. Here is an example with 7 rows and 11 columns with a starting hand size of 10 cards, totaling 77 cells PLUS the 11 cards that must be displayed at once (remember the red player draws one card at the start of their turn).</p>\n<figure><figcaption></figcaption></figure>\n<p>You may decorate the image if you wish, or adjust the color palette, or even change the font, or change how the cards themselves are displayed, but it should still contain the same information as the above. That means a user can easily identify the following:</p>\n<ul>\n<li>which player is playing</li>\n<li>what cards are in their hand along with influence grids of those cards</li>\n<li>where the board is</li>\n<li>what cells belong to the red player, which to the blue player, and which to neither</li>\n<li>how many pawns are on a cell without a card</li>\n<li>the value scores of any card already on the board</li>\n<li>the row-scores for each player</li>\n</ul>\n<p>Here is an example of an alternative view that shows the same information without the same level of polish as the above.</p>\n<figure><figcaption></figcaption></figure>\n<p>You will notice the following</p>\n<ul>\n<li>There is no gap between the hand and the board.</li>\n<li>The pawns are just numbers on the board telling us how many pawns are there. Ownership of the pawns is shown by the color of the text itself.</li>\n<li>The cards on the board look the same as the cards in the hand, just a little squished.</li>\n<li>The influence grids look exactly like the influence grids from the configuration file.</li>\n<li>The cards owned by blue still have their influence mirrored, but in text instead.</li>\n<li>Row-scores are not displayed on their own as the player can calculate that information themselves from the cards owned by each player.</li>\n</ul>\n<p>The point is your view doesn’t need to be <em>exactly</em> the same as the fancier one and do as much drawing. You can get away with drawing much, much less and then add the polishing features as you please.</p>\n<p>Looking through the documentation of the <code>Graphics2D</code> class, you’ll find several useful methods for drawing text, lines, ovals, images, and shapes; and for transforming the coordinate system (scaling, translating and rotating) to affect where drawings are placed. We recommend building a subclass of <code>Path2D.Double</code> that represents “a card” of whatever size makes sense in your view. You can then draw multiple such cards wherever needed to make up your rendering: this will be much easier than attempting to draw all the individual edges of the cards separately.</p>\n<p>The size of drawn strings is controlled by the size of the font used in the <code>Graphics2D</code> object. I suggest reading up on the <code>Font</code> class to find methods to help change the font size to whatever works best as you resize the window. Furthermore, you <em>cannot</em> print newlines with <code>drawString</code>. Instead, take a look at this <a href=\"https://stackoverflow.com/questions/4413132/problems-with-newline-in-graphics2d-drawstring\" target=\"_blank\" rel=\"noopener noreferrer\">Stack Overflow question</a> on how to visualize a newline.</p>\n<h3>3.2 Required behavior</h3>\n<p>Your view should have a constructor that takes in a <code>ReadonlyPawnsBoardModel</code> — <em>not</em> the mutable interface! — to ensure that your view is incapable of modifying the model even accidentally.</p>\n<p>In preparation for the next assignment (where you will build a controller that delegates to the model and view), you should equip your view with the ability to handle mouse clicks and key presses. This means you will need a <em>stub controller</em> to stand in for the real thing and respond to the events. In particular,</p>\n<ul>\n<li>\n<p>a user should be able to click on a card in the hand, and it should highlight that card somehow. In the image below, the highlight is indicated by changing the card to cyan. You may choose another way of highlighting if you wish so long as it is obvious it is selected.</p>\n<figure><figcaption></figcaption></figure>\n<ul>\n<li>Additionally, your stub controller should print a message (using <code>System.out</code>) containing the index of the card that was clicked on as well as which player owns that hand.</li>\n</ul>\n</li>\n<li>\n<p>a user should be able to click on a cell in the grid, and it should highlight that cell somehow. In the image below, the highlight is indicated by changing the cell background to cyan. You may choose another way of highlighting if you wish so long as it is obvious it is selected.</p>\n<figure><figcaption></figcaption></figure>\n<ul>\n<li>Additionally, the stub controller should print a message (using <code>System.out</code>) containing the coordinates of the cell that was clicked on, in whatever coordinate system you used in your model. <strong>Note:</strong> this is not the same thing as the physical <em>mouse</em> coordinates of the mouse event!</li>\n</ul>\n</li>\n<li>\n<p>a user should be able to indicate they want to confirm their move or pass by handling keyboard input. You may choose what keyboard interactions correspond to confirming or passing, but be sure to document them in you README.</p>\n<p>Additionally, the stub controller should print a message (using <code>System.out</code>) printing whether the key press indicated a confirmation or a pass.</p>\n</li>\n</ul>\n<p>Your view should let the user deselect a selected card in hand or cell on the board by</p>\n<ul>\n<li>clicking on it again OR</li>\n<li>clicking on another card (in which case you should select that new card)</li>\n</ul>\n<p>Clicking outside the boundary of the grid or the hand <em>must not</em> cause your view to crash, throw an exception, or otherwise break.</p>\n<p>You may want to revisit the discussion of the observer pattern from <a href=\"https://course.ccs.neu.edu/cs3500/lec_observer_pattern_notes.html\" target=\"_blank\" rel=\"noopener noreferrer\">Lecture 14: The Observer Pattern</a>, and this may influence your view interface designs. This will also help you plan out your true controller ahead of the next assignment.</p>\n<p>Finally, we should be able to resize your window larger and smaller and all of the above functionality should still work correctly. Note you are not responsible for the visual artifacting (read: anything that <em>looks</em> weird) that can occur at extremely small or large sizes.</p>\n<h3>3.3 Running your view</h3>\n<p>Add the following placeholder class to your project:</p>\n<div class=\"language-java line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"java\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-java\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">package</span><span style=\"--shiki-light:#383A42;--shiki-dark:#C678DD\"> cs3500.pawnsboard</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">;</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">public</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> final</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> class</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> PawnsBoardGame</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">  public</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> static</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> void</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> main</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">String</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">[] </span><span style=\"--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">args</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">    YourModel</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\"> model</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> =</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> ...</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">create</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> an example model...</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">    YourView</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\"> view</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> =</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> new</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> YourView</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(model);</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    ...</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">whatever</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> other setup you need...</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">    view</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">setVisible</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">true</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">); </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">//or the equivalent in your system</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">  }</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">}</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>As we’ve done several times, our <code>main()</code> method simply instantiates a model, instantiates a view using that model, instantiates anything else needed, and tells the view to get started. In later assignments we will augment this to create controllers, players, and make the game playable.</p>\n<h3>3.4 Testing your view</h3>\n<p>Testing views can be quite tricky, since you cannot simply use JUnit assertions to check them for “equality”. For this assignment, you do not need to unit-test your visual view, but you should include in your submission at least four screenshots of your view, each screenshot being of a 5 row and 7 column game:</p>\n<ul>\n<li>At the start of the game</li>\n<li>With a card and cell selected from the Red Player’s hand on their turn during the start of the game</li>\n<li>With a card selected from the Blue Player’s hand on their turn during their first turn of the game</li>\n<li>At a non-trivial intermediate point of the game, meaning cards have been played by both players</li>\n</ul>\n<p>Name the screenshots appropriately, so you and graders can easily tell what they represent. Also, make sure the screenshots are reasonably sized (e.g 600 px height is the height used for the screenshots on this page). There is no reason to have a 4K png of your view.</p>\n<h2>4. Strategic computer players</h2>\n<p>Playing Pawns Board for any amount of time quickly leads to noticing two aspects of the strategies required for key play: which card to choose and then where to place the card.</p>\n<ol>\n<li>Fill first: Choose the first card and location that can be played on and play there.</li>\n<li>Maximize row-score: Choose a card and location that will allow the current player to win a particular row by making their row-score higher than the opponent’s row-score. Rows are visited from top-down. If the current player has a lower or equal row-score than their opponent on that row, this strategy chooses the first card and location option that increases their row-score to be greater than <s>or equal to</s> the opponent’s row-score. If there is no play that would make the current player's row-score greater than the opponent's, move on to the next row. If after visitng all rows, there is still no move to make, report there is no move to make (meaning the player should pass).</li>\n<li>Control the board: choose a card and location that will give the current player ownership of the most cells. In a tie between positions, choose the uppermost-leftmost (so uppermost first, then leftmost). In a tie between cards, choose the leftmost (or closest to first) card.</li>\n<li>A fancier approach might choose the move that leaves their opponent in a situation with no good moves. (This approach <em>minimizes</em> the <em>maximum</em> move the opponent can make, and is known as a <em>minimax strategy</em>.) To calculate the \"best\" move an opponent can make, you must make some guess as to what strategy that opponent is using...and it might be any of these strategies we’ve seen so far.</li>\n</ol>\n<p>(There are far more sophisticated strategies than these, but these will do for now!)</p>\n<h3>4.1 Required behavior</h3>\n<p>Implement the first <em>two</em> of these strategies. Note that those two strategies cannot have tied choices. If there are no valid moves, your player should pass.</p>\n<p><em>Hint:</em> Keep in mind that a strategy needs to know which player it’s trying to pick a move for!</p>\n<p>You must test these strategies, and in particular demonstrate that it resolves ties correctly.</p>\n<p><em>Hint:</em> You may have an easier time implementing your strategies if you generalize their signature somewhat: Unlike the Tic Tac Toe strategies, where moves didn’t have a numerical value, moves here do have a potential score. The possibility of ties in <em>some</em> strategies implies that your strategy’s signature should return more than just a single move possibility...</p>\n<h3>4.2 Extra credit</h3>\n<p>As we discussed with <a href=\"https://course.ccs.neu.edu/cs3500/lec_strategies_decorators_notes.html\" target=\"_blank\" rel=\"noopener noreferrer\">Tic Tac Toe</a>, you can <em>chain</em> these strategies to form strategies of varying sophistication. A simplistic strategy would just use option 1; a smarter strategy might stack on options 2 and 3, as well to further break ties in option 1. Some of these strategies may result in multiple, equally-good options: in case of such ties, again choose the move with the uppermost-leftmost location first and then the leftmost card in the hand.</p>\n<p>Some of these strategies may result in no valid moves: you must figure out how to represent such situations and what they should (eventually) do in the model.</p>\n<p><strong>Your task to get extra credit:</strong></p>\n<ul>\n<li>Implement the other two strategies mentioned in the prior subsection.</li>\n<li>Fix your strategy implementations such that they can be recombined in various ways (and not just hard-coded in a fixed combination like our <code>HybridMergeSorter</code> from class.)</li>\n<li>Write tests that show your new strategies work solo and you can recombine strategies to make more complex ones.</li>\n</ul>\n<p>In your README, explain what the extra credit strategies you implemented were and where we can find their implementations and tests. <strong>If your README does not state this, you will get no extra credit.</strong></p>\n<h4>4.3<code> </code>Testing your strategies</h4>\n<p>The elegant feature of strategies is that they are simply function objects, and so they are eminently testable. Build a collection of example games in known configurations, ask each strategy where it would choose to move for a given player, and check that the result is as expected.</p>\n<p>If you’ve implemented multiple strategies, test them thoroughly: in particular, make sure you test scenarios that demonstrate the differences between them.</p>\n<h4>4.3.1 Mocking your model</h4>\n<p>One of the challenges of testing your strategies is that they depend on your model working correctly: the model needs to implement the complicated game logic of legality checking and scoring, and if those are buggy, your strategies may give unexpected results. But obviously, you can’t execute a strategy without <em>some</em> model object to examine!</p>\n<p>In class we discussed <em>mocks</em>, that are stub implementations of interfaces that can give simulated answers and that can record a transcript of what methods were used. Here are two ideas for mocking your model; you should use these (and probably several more) to test your strategies:</p>\n<ul>\n<li>How can you tell if Strategy 2 actually looked at the rows from top to bottom? Or if Strategy 1 actually stopped at the first possible location when looking for potential moves? Mock your model to record a transcript of which coordinates were inspected by your strategy, and then test whether that transcript contains all the necessary coordinates.</li>\n<li>How can you tell if Strategy 2 chose a valid location to get a higher row-score than the opponent? Mock your model to lie about the legality of certain locations or the value of such moves, to force your strategy to think that only only a pre-determined move is valid, and then test that it indeed returns that move.</li>\n</ul>\n<h2>5. What to do</h2>\n<ol>\n<li>Refactor your model to split it into read-only and mutable interfaces.</li>\n<li>Design your view interfaces, and then begin implementing your views.</li>\n<li>Design your strategy interface(s) and implementation(s). Test them, using mocks of your models as necessary.</li>\n<li>Update your README file to include explanations of all the new classes you’ve designed. Be sure to include a “Changes for part 2” section documenting what you changed from your initial design.</li>\n</ol>\n<details class=\"hint-container details\"><summary>公众号：AI悦创【二维码】</summary>\n<figure><img src=\"/gzh.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n</details>\n<div class=\"hint-container info\">\n<p class=\"hint-container-title\">AI悦创·编程一对一</p>\n<p>AI悦创·推出辅导班啦，包括「Python 语言辅导班、C++ 辅导班、java 辅导班、算法/数据结构辅导班、少儿编程、pygame 游戏开发、Web、Linux」，招收学员面向国内外，国外占 80%。全部都是一对一教学：一对一辅导 + 一对一答疑 + 布置作业 + 项目实践等。当然，还有线下线上摄影课程、Photoshop、Premiere 一对一教学、QQ、微信在线，随时响应！微信：Jiabcdefh</p>\n<p>C++ 信息奥赛题解，长期更新！长期招收一对一中小学信息奥赛集训，莆田、厦门地区有机会线下上门，其他地区线上。微信：Jiabcdefh</p>\n<p>方法一：<a href=\"http://wpa.qq.com/msgrd?v=3&amp;uin=1432803776&amp;site=qq&amp;menu=yes\" target=\"_blank\" rel=\"noopener noreferrer\">QQ</a></p>\n<p>方法二：微信：Jiabcdefh</p>\n</div>\n<figure><img src=\"/zsxq.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n",
      "date_published": "2025-03-24T13:03:54.000Z",
      "date_modified": "2025-04-10T23:49:50.000Z",
      "authors": [
        {
          "name": "Bornforthis"
        }
      ],
      "tags": []
    },
    {
      "title": "06｜RAG实战：基于ChatGLM3-6B+LangChain+Faiss搭建企业内部知识库",
      "url": "https://bornforthis.cn/column/AI%E5%A4%A7%E6%A8%A1%E5%9E%8B%E5%AE%9E%E6%88%98%E9%AB%98%E6%89%8B%E8%AF%BE/06-RAG%E5%AE%9E%E6%88%98%EF%BC%9A%E5%9F%BA%E4%BA%8EChatGLM3-6B_LangChain_Faiss%E6%90%AD%E5%BB%BA%E4%BC%81%E4%B8%9A%E5%86%85%E9%83%A8%E7%9F%A5%E8%AF%86%E5%BA%93.html",
      "id": "https://bornforthis.cn/column/AI%E5%A4%A7%E6%A8%A1%E5%9E%8B%E5%AE%9E%E6%88%98%E9%AB%98%E6%89%8B%E8%AF%BE/06-RAG%E5%AE%9E%E6%88%98%EF%BC%9A%E5%9F%BA%E4%BA%8EChatGLM3-6B_LangChain_Faiss%E6%90%AD%E5%BB%BA%E4%BC%81%E4%B8%9A%E5%86%85%E9%83%A8%E7%9F%A5%E8%AF%86%E5%BA%93.html",
      "summary": "你好，我是悦创。 上一节课，我们通过一个企业内部小助手的案例，学习了 6B 的微调过程。其中，除了微调，还有一种模式就是知识库，用来增强大模型信息检索的能力，我们称之为检索增强生成（RAG），这是目前非常流行的一种做法，知识库模式相比于微调有 2 个好处。 公众号：AI悦创【二维码】 AI悦创·编程一对一 AI悦创·推出辅导班啦，包括「Python 语...",
      "content_html": "<figure><figcaption></figcaption></figure>\n<p>你好，我是悦创。</p>\n<p>上一节课，我们通过一个企业内部小助手的案例，学习了 6B 的微调过程。其中，除了微调，还有一种模式就是知识库，用来增强大模型信息检索的能力，我们称之为检索增强生成（RAG），这是目前非常流行的一种做法，知识库模式相比于微调有 2 个好处。</p>\n<details class=\"hint-container details\"><summary>公众号：AI悦创【二维码】</summary>\n<figure><img src=\"/gzh.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n</details>\n<div class=\"hint-container info\">\n<p class=\"hint-container-title\">AI悦创·编程一对一</p>\n<p>AI悦创·推出辅导班啦，包括「Python 语言辅导班、C++ 辅导班、java 辅导班、算法/数据结构辅导班、少儿编程、pygame 游戏开发、Web、Linux」，招收学员面向国内外，国外占 80%。全部都是一对一教学：一对一辅导 + 一对一答疑 + 布置作业 + 项目实践等。当然，还有线下线上摄影课程、Photoshop、Premiere 一对一教学、QQ、微信在线，随时响应！微信：Jiabcdefh</p>\n<p>C++ 信息奥赛题解，长期更新！长期招收一对一中小学信息奥赛集训，莆田、厦门地区有机会线下上门，其他地区线上。微信：Jiabcdefh</p>\n<p>方法一：<a href=\"http://wpa.qq.com/msgrd?v=3&amp;uin=1432803776&amp;site=qq&amp;menu=yes\" target=\"_blank\" rel=\"noopener noreferrer\">QQ</a></p>\n<p>方法二：微信：Jiabcdefh</p>\n</div>\n<figure><img src=\"/zsxq.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n",
      "date_published": "2025-03-20T15:00:14.000Z",
      "date_modified": "2025-04-10T23:49:50.000Z",
      "authors": [
        {
          "name": "Bornforthis"
        }
      ],
      "tags": []
    },
    {
      "title": "05-🍋柠檬鸡爪",
      "url": "https://bornforthis.cn/column/cookdinner/P02-%E5%87%89%E8%8F%9C%E5%B0%8F%E7%82%92/05-%E6%9F%A0%E6%AA%AC%E9%B8%A1%E7%88%AA.html",
      "id": "https://bornforthis.cn/column/cookdinner/P02-%E5%87%89%E8%8F%9C%E5%B0%8F%E7%82%92/05-%E6%9F%A0%E6%AA%AC%E9%B8%A1%E7%88%AA.html",
      "summary": "1. 食材 汆煮：鲜鸡爪2千克，盐10克，花雕酒50克，葱姜各20克，香叶2克，白胡椒粒2克，陈皮2克 料汁：蒜蓉100克，盐7克，白糖40克，蚝油50克，生抽100克，松茸调味料10克，雪碧750克，百香果2个，柠檬2个，小米辣35克，辣椒油80克，苹果醋30克 2. 步骤 小火慢开（冷水下锅）——>加入：盐巴、花雕酒、葱、姜、香叶、白胡椒粉、陈皮 ...",
      "content_html": "<h2>1. 食材</h2>\n<p>汆煮：鲜鸡爪2千克，盐10克，花雕酒50克，葱姜各20克，香叶2克，白胡椒粒2克，陈皮2克</p>\n<p>料汁：蒜蓉100克，盐7克，白糖40克，蚝油50克，生抽100克，松茸调味料10克，雪碧750克，百香果2个，柠檬2个，小米辣35克，辣椒油80克，苹果醋30克</p>\n<h2>2. 步骤</h2>\n<ol>\n<li>\n<p>小火慢开（冷水下锅）——&gt;加入：盐巴、花雕酒、葱、姜、香叶、白胡椒粉、陈皮</p>\n<details class=\"hint-container details\"><summary>详情</summary>\n\n</details>\n</li>\n<li>\n<p>出锅放入冰块水中——&gt; 去皮</p>\n<details class=\"hint-container details\"><summary>详情</summary>\n\n\n</details>\n</li>\n<li>\n<p>柠檬酱汁：</p>\n<ol>\n<li>\n<p>柠檬的最外层表皮，它的苦味最足，用刀刮掉！</p>\n<details class=\"hint-container details\"><summary>详情</summary>\n<figure><figcaption></figcaption></figure>\n</details>\n</li>\n<li>\n<p>腌制 2h</p>\n</li>\n</ol>\n</li>\n</ol>\n<details class=\"hint-container details\"><summary>公众号：AI悦创【二维码】</summary>\n<figure><img src=\"/gzh.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n</details>\n<div class=\"hint-container info\">\n<p class=\"hint-container-title\">AI悦创·编程一对一</p>\n<p>AI悦创·推出辅导班啦，包括「Python 语言辅导班、C++ 辅导班、java 辅导班、算法/数据结构辅导班、少儿编程、pygame 游戏开发、Web、Linux」，招收学员面向国内外，国外占 80%。全部都是一对一教学：一对一辅导 + 一对一答疑 + 布置作业 + 项目实践等。当然，还有线下线上摄影课程、Photoshop、Premiere 一对一教学、QQ、微信在线，随时响应！微信：Jiabcdefh</p>\n<p>C++ 信息奥赛题解，长期更新！长期招收一对一中小学信息奥赛集训，莆田、厦门地区有机会线下上门，其他地区线上。微信：Jiabcdefh</p>\n<p>方法一：<a href=\"http://wpa.qq.com/msgrd?v=3&amp;uin=1432803776&amp;site=qq&amp;menu=yes\" target=\"_blank\" rel=\"noopener noreferrer\">QQ</a></p>\n<p>方法二：微信：Jiabcdefh</p>\n</div>\n<figure><img src=\"/zsxq.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n",
      "date_published": "2025-04-17T15:53:34.000Z",
      "date_modified": "2025-05-10T10:03:21.000Z",
      "authors": [
        {
          "name": "AI悦创"
        }
      ],
      "tags": []
    },
    {
      "title": "01-煎饼铁盘开锅",
      "url": "https://bornforthis.cn/column/cookdinner/P09-%E9%94%85%E7%B1%BB%E5%BC%80%E9%94%85/01-%E7%85%8E%E9%A5%BC%E9%93%81%E7%9B%98.html",
      "id": "https://bornforthis.cn/column/cookdinner/P09-%E9%94%85%E7%B1%BB%E5%BC%80%E9%94%85/01-%E7%85%8E%E9%A5%BC%E9%93%81%E7%9B%98.html",
      "summary": "1. 开锅 铸铁锅务必要开锅哦（珐琅锅请参考珐琅锅的开锅及保养），具体步骤如下： 先将锅内清洗干净，然后用火烤干，锅内没有水分后，转为小火。 倒入适量食用油，用筷子夹起一张纸巾，将纸巾蘸上部分食用油，将油均匀涂抹在锅内每个角落，持续 2-3 分钟，关火自然冷却。 冷却后重复开锅 2-3 次效果最佳。如有条件建议用猪皮完成上述步骤。等待锅子自然冷却，开锅...",
      "content_html": "<h2>1. 开锅</h2>\n<p>铸铁锅务必要开锅哦（珐琅锅请参考珐琅锅的开锅及保养），具体步骤如下：</p>\n<ol>\n<li>先将锅内清洗干净，然后用火烤干，锅内没有水分后，转为小火。</li>\n<li>倒入适量食用油，用筷子夹起一张纸巾，将纸巾蘸上部分食用油，将油均匀涂抹在锅内每个角落，持续 2-3 分钟，关火自然冷却。</li>\n<li>冷却后重复开锅 2-3 次效果最佳。如有条件建议用猪皮完成上述步骤。等待锅子自然冷却，开锅完成后，即可正常使用。</li>\n</ol>\n<h2>2. 养护</h2>\n<p>使用后保养方法：</p>\n<ol>\n<li>\n<p>烹饪完食物，温热水清洗；</p>\n<blockquote>\n<p>尽量不用洗洁精，洗洁精会把刚刚被锅吸收的油脂洗出来。</p>\n</blockquote>\n</li>\n<li>\n<p>在炉上烤干水汽，避免生锈；</p>\n</li>\n<li>\n<p>锅烤干后在内壁涂上薄薄一层食用油小火加热烧下锅，使食用油沁入锅内进行养护</p>\n<blockquote>\n<p>这一步骤建议前期多进行几次，以后间隔时间可以长一些；</p>\n</blockquote>\n</li>\n<li>\n<p>关火、自然冷却，放置干燥处存放即可；</p>\n</li>\n</ol>\n<details class=\"hint-container details\"><summary>公众号：AI悦创【二维码】</summary>\n<figure><img src=\"/gzh.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n</details>\n<div class=\"hint-container info\">\n<p class=\"hint-container-title\">AI悦创·编程一对一</p>\n<p>AI悦创·推出辅导班啦，包括「Python 语言辅导班、C++ 辅导班、java 辅导班、算法/数据结构辅导班、少儿编程、pygame 游戏开发、Web、Linux」，招收学员面向国内外，国外占 80%。全部都是一对一教学：一对一辅导 + 一对一答疑 + 布置作业 + 项目实践等。当然，还有线下线上摄影课程、Photoshop、Premiere 一对一教学、QQ、微信在线，随时响应！微信：Jiabcdefh</p>\n<p>C++ 信息奥赛题解，长期更新！长期招收一对一中小学信息奥赛集训，莆田、厦门地区有机会线下上门，其他地区线上。微信：Jiabcdefh</p>\n<p>方法一：<a href=\"http://wpa.qq.com/msgrd?v=3&amp;uin=1432803776&amp;site=qq&amp;menu=yes\" target=\"_blank\" rel=\"noopener noreferrer\">QQ</a></p>\n<p>方法二：微信：Jiabcdefh</p>\n</div>\n<figure><img src=\"/zsxq.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n",
      "image": "https://bornforthis.cn/gzh.jpg",
      "date_published": "2025-07-24T10:55:38.000Z",
      "date_modified": "2025-07-24T03:33:03.000Z",
      "authors": [
        {
          "name": "AI悦创"
        }
      ],
      "tags": []
    },
    {
      "title": "01-芝麻香芋",
      "url": "https://bornforthis.cn/column/cookdinner/P07-%E7%89%B9%E8%89%B2%E7%94%9C%E9%A3%9F%E5%B0%8F%E5%90%83/01-%E8%8A%9D%E9%BA%BB%E9%A6%99%E8%8A%8B.html",
      "id": "https://bornforthis.cn/column/cookdinner/P07-%E7%89%B9%E8%89%B2%E7%94%9C%E9%A3%9F%E5%B0%8F%E5%90%83/01-%E8%8A%9D%E9%BA%BB%E9%A6%99%E8%8A%8B.html",
      "summary": "1. 食材 700 克芋头； 40 克白糖； 50 克炼乳； 10 克糯米粉； 20 克玉米淀粉； 油； 李锦记红烧汁； 芝麻； 香葱； 2. 步骤 700 克芋头切厚片蒸 20 分钟——>蒸到筷子一夹就断——>趁热压成芋泥——>40 克白糖——>50 克炼乳——>10 克糯米粉——>20 克玉米淀粉——> 揉捻成面团——>盘子下面铺好玉米淀粉——>把...",
      "content_html": "<h2>1. 食材</h2>\n<ol>\n<li>700 克芋头；</li>\n<li>40 克白糖；</li>\n<li>50 克炼乳；</li>\n<li>10 克糯米粉；</li>\n<li>20 克玉米淀粉；</li>\n<li>油；</li>\n<li>李锦记红烧汁；</li>\n<li>芝麻；</li>\n<li>香葱；</li>\n</ol>\n<h2>2. 步骤</h2>\n<ol>\n<li>700 克芋头切厚片蒸 20 分钟——&gt;蒸到筷子一夹就断——&gt;趁热压成芋泥——&gt;40 克白糖——&gt;50 克炼乳——&gt;10 克糯米粉——&gt;20 克玉米淀粉——&gt; 揉捻成面团——&gt;盘子下面铺好玉米淀粉——&gt;把揉成的面团用铲子压平整——&gt;保鲜膜包上，冷藏 30分钟——&gt; 拿出来，再撒上玉米淀粉——&gt;切成正方体小块——&gt;每一面都裹上粉——&gt;吃不完可以速冻保存；</li>\n<li>油温 180 度左右下锅炸——&gt;晃动锅底，小火慢炸至浮起「表面金黄酥脆捞起」——&gt;直接吃也可以；</li>\n<li>半碗水——&gt;李锦记红烧汁适量——&gt;一点盐、白糖——&gt;煮开勾芡——&gt;淋浇，撒上芝麻、香葱；</li>\n</ol>\n<h2>3. 视频</h2>\n",
      "image": "https://bornforthis.cn/gzh.jpg",
      "date_published": "2025-04-16T22:38:12.000Z",
      "date_modified": "2025-05-10T10:03:21.000Z",
      "authors": [
        {
          "name": "AI悦创"
        }
      ],
      "tags": []
    },
    {
      "title": "01-老婆生日宴菜单｜菜谱",
      "url": "https://bornforthis.cn/column/cookdinner/P00-Plan/2025-year/01-wife-birthday.html",
      "id": "https://bornforthis.cn/column/cookdinner/P00-Plan/2025-year/01-wife-birthday.html",
      "summary": "1. 菜单 2. 食材 3. 制作顺序 Step 1：卤猪蹄（市区的电高压锅）、虎皮凤爪（小熊电饭锅）、糖醋排骨（小高压锅）、奥尔良烤翅（空气炸锅｜烤箱）、跳跳鱼提前炸； Step 2：蒜蓉开背虾、清蒸鱼（大锅｜灶台）； Step 3：焖芋头、汤圆、卤面、海蛎汤 Step 4：腊肠炒花菜、炒小肠青椒、京酱肉丝（提前做摆盘）、空心菜 4. 菜谱 公众号：...",
      "content_html": "<h2>1. 菜单</h2>\n\n",
      "image": "https://bornforthis.cn/gzh.jpg",
      "date_published": "2025-04-16T21:22:05.000Z",
      "date_modified": "2025-05-11T06:43:20.000Z",
      "authors": [
        {
          "name": "黄家蓉宝"
        }
      ],
      "tags": []
    },
    {
      "title": "08-金钱蛋",
      "url": "https://bornforthis.cn/column/cookdinner/P01-%E8%8D%A4%E8%8F%9C%E7%B1%BB/01-%E7%BA%A2%E7%83%A7%E7%B1%BB/08-%E9%87%91%E9%92%B1%E8%9B%8B.html",
      "id": "https://bornforthis.cn/column/cookdinner/P01-%E8%8D%A4%E8%8F%9C%E7%B1%BB/01-%E7%BA%A2%E7%83%A7%E7%B1%BB/08-%E9%87%91%E9%92%B1%E8%9B%8B.html",
      "summary": "1. 食材 详情 2. 步骤 加入八个鸡蛋，水没过——>大火烧开，水开盖上锅盖——>转小火 18 分钟——>煮熟捞出鸡蛋，过冷水——>剥壳后——>鸡蛋切片； 绿辣椒切小丁、小米辣切小圈、大蒜切片； 玉米淀粉 50g、清水 50g； 锅中适量油（可以炸全部鸡蛋即可）——>等油温足够热——>把切片鸡蛋放入淀粉水，正反沾满淀粉水——>加入油锅炸即可——>只要...",
      "content_html": "<h2>1. 食材</h2>\n<p>| 鸡蛋 | 绿辣椒 | 小米椒 | 大蒜 | 玉米淀粉 |<br>\n|</p>\n",
      "image": "https://bornforthis.cn/gzh.jpg",
      "date_published": "2025-06-02T11:04:47.000Z",
      "date_modified": "2025-06-02T03:24:01.000Z",
      "authors": [
        {
          "name": "AI悦创"
        }
      ],
      "tags": []
    },
    {
      "title": "03-川渝第一菜：回锅肉",
      "url": "https://bornforthis.cn/column/cookdinner/P01-%E8%8D%A4%E8%8F%9C%E7%B1%BB/03-%E7%82%92%E8%8F%9C%E7%B1%BB/03-%E5%9B%9E%E9%94%85%E8%82%89.html",
      "id": "https://bornforthis.cn/column/cookdinner/P01-%E8%8D%A4%E8%8F%9C%E7%B1%BB/03-%E7%82%92%E8%8F%9C%E7%B1%BB/03-%E5%9B%9E%E9%94%85%E8%82%89.html",
      "summary": "1. 食材 详情 食材选择：传统回锅肉用二刀肉，现推荐用五花肉，配菜用蒜苗（有的地方叫青蒜）、红椒、葱姜蒜。 肉的处理：五花肉冷水下锅，加葱姜、花椒、酒，煮好捞出晾凉切片，厚度约 3 毫米。 配菜处理： 蒜苗叶和梗分开，梗破为二，斜刀切薄；蒜苗叶切寸段； 准备红椒、葱姜蒜。 调料准备： 需要郫县豆瓣酱； 永川豆豉； 甜面酱，甜面酱可增加香气和甜味。 炒...",
      "content_html": "<h2>1. 食材</h2>\n<p>| 五花肉   | 蒜苗（有的地方叫青蒜） | 红椒 | 葱姜蒜 | 郫县豆瓣酱（川菜之魂） | 豆豉 | 甜面酱 |<br>\n|</p>\n",
      "image": "https://bornforthis.cn/gzh.jpg",
      "date_published": "2025-06-08T19:12:21.000Z",
      "date_modified": "2025-07-02T05:36:19.000Z",
      "authors": [
        {
          "name": "AI悦创"
        }
      ],
      "tags": []
    },
    {
      "title": "02｜学好提示工程，轻松驾驭大模型",
      "url": "https://bornforthis.cn/column/AI%E5%A4%A7%E6%A8%A1%E5%9E%8B%E5%AE%9E%E6%88%98%E9%AB%98%E6%89%8B%E8%AF%BE/02-%E5%AD%A6%E5%A5%BD%E6%8F%90%E7%A4%BA%E5%B7%A5%E7%A8%8B%EF%BC%8C%E8%BD%BB%E6%9D%BE%E9%A9%BE%E9%A9%AD%E5%A4%A7%E6%A8%A1%E5%9E%8B.html",
      "id": "https://bornforthis.cn/column/AI%E5%A4%A7%E6%A8%A1%E5%9E%8B%E5%AE%9E%E6%88%98%E9%AB%98%E6%89%8B%E8%AF%BE/02-%E5%AD%A6%E5%A5%BD%E6%8F%90%E7%A4%BA%E5%B7%A5%E7%A8%8B%EF%BC%8C%E8%BD%BB%E6%9D%BE%E9%A9%BE%E9%A9%AD%E5%A4%A7%E6%A8%A1%E5%9E%8B.html",
      "summary": "你好，我是悦创。 这节课我们好好讲讲提示工程，也就是我们常说的 Prompt Engineering。这一节课的内容非常关键，可以这么说，能否充分使用好 AI 大模型，提示是关键，所以现在已经有一种新的职业诞生，就是提示工程师。 目前国内已经有不少公司在招聘提示工程师，薪水接近软件开发工程师的水平，达到 20 万～30 万人民币，国外有的高级提示工程师...",
      "content_html": "<figure><figcaption></figcaption></figure>\n<p>你好，我是悦创。</p>\n<p>这节课我们好好讲讲提示工程，也就是我们常说的 Prompt Engineering。这一节课的内容非常关键，可以这么说，<strong>能否充分使用好 AI 大模型，提示是关键</strong>，所以现在已经有一种新的职业诞生，就是提示工程师。</p>\n<p>目前国内已经有不少公司在招聘提示工程师，薪水接近软件开发工程师的水平，达到 20 万～30 万人民币，国外有的高级提示工程师，薪水已经超越软件开发工程师水平，达到了惊人的 30 万美金以上，要知道 Google 软件开发工程师的平均年薪也就 20 万美金左右。为什么会出现这样的现象？到底什么是提示工程？想了解这个问题，我们先来聊聊什么是提示。</p>\n<h2>1. 什么是提示？</h2>\n<p>这里你可能会有一些疑问，因为一般在使用大模型产品的时候，我们都是向大模型“提问”，大模型给出“答案”，这个过程也没有看到提示啊？其实不然，如果阅读过 OpenAI 官方使用文档，你就会发现，在官方文档里，你是看不到 question 和 answer 这两个词的，我们能看到的是 prompt 和 completion，翻译过来就是提示和补全，也就是说，我们向大模型提出的问题，其实是给大模型一个提示，让它进行补全，补全的内容就是大模型给我们输出的答案。</p>\n<p>看到这里，你可能又想问了，为什么是提示和补全，而不是提问和答案呢？这就要从大模型训练的原理出发去理解了。上节课我们讲过，GPT 系列模型是基于 Transformer 架构的解码器机制，使用自回归无监督方式进行预训练的。这个训练过程简单来说就是大量的文本输入，不断进行记忆的过程，相比监督学习，效率会更低，但是训练过程简单，可以喂大量的文本语料，上限比较高。</p>\n<p>而我们在使用大模型的时候，先给出提示，大模型会根据提示，来推测补全内容。实际上是根据训练过的“记忆”，一个字一个字地计算概率，取概率最大的那个字进行输出，所以不少人吐槽大模型输出很慢。的确，它是一个字一个字地计算并输出，效率肯定会比较低。</p>\n<p>光从使用角度看，提示还是比较容易理解的，那什么是提示工程呢？</p>\n<h2>2. 什么是提示工程？</h2>\n<p>用过 ChatGPT 的人，心态一般是这样的：</p>\n<blockquote>\n<p>第一天：哇！这个东西好牛啊，还懂人性，回答不对还道歉，太牛了！</p>\n<p>第二天：哎？好像也没啥啊，回答的内容也就那样，看似长篇大论，实则没有新意，感觉也解决不了太多实际问题。</p>\n</blockquote>\n<p>我见过身边很多人都是这样的，那这里我就要问一下你了，你的提示长什么样？可否回想一下，你的提示是不是这样的？</p>\n<ul>\n<li>提示一：请帮我生成一个 PPT 大纲。</li>\n<li>提示二：请帮我生成一个专利创作背景。</li>\n<li>提示三：请帮我写一篇日记。</li>\n<li>提示四：…</li>\n</ul>\n<p>就拿【提示一】来说，试想一下，你有一个秘书小李，想让他帮忙做个 PPT，你们的对话一般来说应该是这样的：</p>\n<p>👨‍🏫：小李，请帮我写一个 PPT。</p>\n<p>👦：老板，您的 PPT 需要什么内容，用来做什么？</p>\n<p>👨‍🏫：我明天去拜访客户，向客户展示我们的新产品。</p>\n<p>👦：那您需要简要介绍还是详细介绍？除了产品还需要放其他内容吗？</p>\n<p>👨‍🏫：简要介绍即可，除了产品介绍，再放一些客户案例。</p>\n<p>👦：好的，老板，您需要什么风格的 PPT 呢？</p>\n<p>👨‍🏫：有科技感一点的。</p>\n<p>👦：好的，老板。</p>\n<p>正常来说，你是需要向小李详细描述你的 PPT 内容的，这样小李才能尽可能准确地制作符合你要求的 PPT，其实上面的对话还不够详细，不出预料，当小李把初稿发给你后，你还会提出一些建议，再次进行修改，有时甚至会修改多轮。</p>\n<p>如果把大模型当作秘书小李的话，那我们给他的提示就不应该是简单的一句话了，而是尽可能地将需求描述清楚，需求描述越详细越准确，大模型输出的内容越符合你的要求。所以说好的提示，包含很多信息，这些信息帮助你和大模型相互了解，所以它是复杂的、规范的，类似于人与人相处，要相互了解才能合作愉快、高效。</p>\n<p>所以提示工程是一门专门研究和大语言模型交互的新型学科，通过不断地开发和优化，帮助用户更好地了解大型语言模型的能力和局限性。换句话说，<strong>提示工程（Prompt Engineering）就是探讨如何设计出最佳提示，用于指导语言模型帮助我们高效完成某项任务。</strong></p>\n<p>提示工程不仅仅是设计和研发提示，它还包含了与大语言模型交互的各种技能和技术。提示工程在实现和大语言模型交互、对接，以及理解大语言模型能力方面都起着重要作用。用户可以通过提示工程来提高大语言模型的安全性，也可以赋能大语言模型，比如借助专业领域知识和外部工具来增强大语言模型的能力。</p>\n<p>换个角度，如果 AI 大模型是你的员工，他能否表现优秀，除了他本身的潜质外，还需要你能够领导好他，也就是我们常说的领导力，在这里叫做 <strong>AI 领导力</strong>。</p>\n<h2>3. 什么是 AI 领导力？</h2>\n<p>做过管理的人都知道，领导力是一个管理者非常重要的素质。在现在这种情况下，AI 大模型其实就是我们的虚拟员工，而且是一个智力高，知识储备量巨大的员工，能否让他有高质量的产出，就是看你怎么带他，怎么领导他。</p>\n<p>那么我就要问了，你确认你能领导一个智商超过 140，大脑几乎掌握了全世界大部分公开知识的员工？一般人我估计不敢轻易给出肯定的答案。但是也不要被吓住，我们需要做的就是提升自身的 AI 领导力。<strong>提示是我们和 AI 大模型沟通的唯一桥梁</strong>，只有熟练掌握提示技巧，才能进一步提升领导力，进而让你轻松驾驭 AI 大模型。</p>\n<h2>4. 如何构造好的提示？</h2>\n<p>获取好的输出结果有几种方式，一种就是不断和模型交互，比如输入很简单，但是通过多轮问答，不断地对输出进行调整；第二种就是一次性尽可能地将输入写好，我更推荐第二种，这样模型就不需要去理解上下文了，一般来说，好的提示可以通过下面这个公式去构造。</p>\n<figure><figcaption></figcaption></figure>\n<ol>\n<li>任务模块：从动作动词开始，无论简单还是复杂，都要明确说明目标，来有效指导输出。</li>\n<li>上下文模块：为大模型提供足够的背景信息，描述清楚用户环境，来缩小可能性，同时可以定义生成任务需要的步骤。</li>\n<li>示例模块：利用示例或框架可以显著提高简历、面试问题或职位描述等各种任务的输出质量。</li>\n<li>角色模块：定义大模型应该效仿的人，例如技术专家、营养师、专业运动员等。</li>\n<li>格式模块：无论是表格、电子邮件、项目符号、代码块、段落，还是期望的输出长度，我们都可以把所需的输出格式可视化，来有效地适应任务。</li>\n<li>语气模块：指定所需的语气，比如休闲、正式、热情或者具体感受，指导大模型匹配写作风格。</li>\n</ol>\n<p>各部分的重要性顺序如下：</p>\n<figure><figcaption></figcaption></figure>\n<p>一个好的提示不一定要包含所有模块，但是最好要包含任务和上下文。无论如何，都要尽可能详细地进行描述。</p>\n<p>这几个模块整体来说是比较易懂的，我简单为你解释下。比如我正在写用户登录模块，打算让大模型为我生成相关的示例代码，我们可以这么写：</p>\n<blockquote>\n<p>你是一个软件开发工程师，请使用 Java 语言，写一个登录的模块，生成相关代码。</p>\n</blockquote>\n<p>我们为模型指定了角色：软件开发工程师，并指定使用 Java 写一个登录模块。以下是 ChatGPT3.5 返回的结果。</p>\n<div class=\"language-java line-numbers-mode has-collapsed-lines collapsed\" data-highlighter=\"shiki\" data-ext=\"java\" style=\"--vp-collapsed-lines:15;--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-java\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">import</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> java.util.HashMap</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">;</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">import</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> java.util.Map</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">;</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">import</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> java.util.Scanner</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">;</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">public</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> class</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> LoginModule</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    private</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> Map</span><span style=\"--shiki-light:#E45649;--shiki-dark:#ABB2BF\">&lt;</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">String</span><span style=\"--shiki-light:#E45649;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> String</span><span style=\"--shiki-light:#E45649;--shiki-dark:#ABB2BF\">&gt;</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\"> userDatabase</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">;</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    public</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> LoginModule</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">        // 初始化用户数据库，实际应用中通常会连接到数据库</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">        userDatabase </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> new</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> HashMap</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">&lt;&gt;();</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">        userDatabase</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">put</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"user1\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"password1\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">);</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">        userDatabase</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">put</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"user2\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"password2\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">);</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">        // 添加更多用户...</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    }</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    public</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> boolean</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> authenticateUser</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">String</span><span style=\"--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\"> username</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">String</span><span style=\"--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\"> password</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">        // 在实际应用中，这里通常会连接到数据库，验证用户名和密码是否匹配</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">        String</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\"> storedPassword</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> =</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\"> userDatabase</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">get</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(username);</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> storedPassword </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">!=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> null</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> &amp;&amp;</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\"> storedPassword</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">equals</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(password);</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    }</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    public</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> static</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> void</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> main</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">String</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">[] </span><span style=\"--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">args</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">        LoginModule</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\"> loginModule</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> =</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> new</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> LoginModule</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">();</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">        Scanner</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\"> scanner</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> =</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> new</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> Scanner</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">System</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">in</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">);</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">        System</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">out</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"请输入用户名: \"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">);</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">        String</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\"> username</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> =</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\"> scanner</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">nextLine</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">();</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">        System</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">out</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"请输入密码: \"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">);</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">        String</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\"> password</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> =</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\"> scanner</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">nextLine</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">();</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> (</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">loginModule</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">authenticateUser</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(username, password)) {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">            System</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">out</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">println</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"登录成功！\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">);</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">        } </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">else</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">            System</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">out</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">println</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"登录失败，用户名或密码错误！\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">);</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">        }</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">        scanner</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">close</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">();</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    }</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">}</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div><div class=\"collapsed-lines\"></div></div><p>可以看出来，并不是我们想要的代码，因为一般情况下我们需要的是 Web 页面登录，而上述结果是一个控制台程序，所以我们接着修改提示。</p>\n<blockquote>\n<p>你是一个软件开发工程师，请使用 Java 语言，写一个 Web 登录的模块，请使用 SpringBoot 框架，前端使用 ReactJS 语言，要求密码使用 MD5 加密。第一步：用户在页面输入用户名和密码，点击登录。第二步：服务端接口收到请求，对参数进行非空验证。第三步：通过数据库查询用户名和密码进行验证。请生成相关代码。</p>\n</blockquote>\n<p>这一次我们不仅指定了角色，还为任务指定了生成步骤，当然模型输出的内容也更加详细了。</p>\n<div class=\"language-java line-numbers-mode has-collapsed-lines collapsed\" data-highlighter=\"shiki\" data-ext=\"java\" style=\"--vp-collapsed-lines:15;--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-java\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">import</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> org.springframework.web.bind.annotation.PostMapping</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">;</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">import</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> org.springframework.web.bind.annotation.RequestBody</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">;</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">import</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> org.springframework.web.bind.annotation.RequestMapping</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">;</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">import</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> org.springframework.web.bind.annotation.RestController</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">;</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">@</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#E5C07B\">RestController</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">@</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#E5C07B\">RequestMapping</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"/api\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">public</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> class</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> UserController</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    @</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#E5C07B\">PostMapping</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"/login\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    public</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> String</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> login</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(@</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#E5C07B\">RequestBody</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> UserLoginRequest</span><span style=\"--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\"> request</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">        // 第二步：非空验证</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> (</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">request</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">getUsername</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">() </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">==</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> null</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> ||</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\"> request</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">getPassword</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">() </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">==</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> null</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">) {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">            return</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> \"用户名和密码不能为空\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">;</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">        }</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">        // 第三步：数据库验证</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> (</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">isValidUser</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">request</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">getUsername</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(), </span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">request</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">getPassword</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">())) {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">            return</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> \"登录成功\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">;</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">        } </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">else</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">            return</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> \"用户名或密码错误\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">;</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">        }</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    }</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    private</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> boolean</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> isValidUser</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">String</span><span style=\"--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\"> username</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">String</span><span style=\"--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\"> password</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">        // 这里应该调用数据库查询用户信息的方法，进行用户名和密码的验证</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">        // 在实际项目中，不应该将密码存储为明文，而是使用哈希算法进行存储和比对</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">        // 这里仅为演示，实际中应该使用更安全的方式</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        return</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> \"admin\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">equals</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(username) </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&amp;&amp;</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> \"21232f297a57a5a743894a0e4a801fc3\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">equals</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">md5</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(password));</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    }</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    private</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> String</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> md5</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">String</span><span style=\"--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\"> input</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">        // 这里是一个简单的MD5加密示例，实际项目中应该使用更安全的加密方式</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">        // 注意：MD5不是安全的加密算法，仅作为演示使用</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">        // 实际项目中应该使用更安全的哈希算法，如BCrypt</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">        // 可以使用Spring Security等库来进行密码的安全处理</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        return</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\"> org</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">apache</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">commons</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">codec</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">digest</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">DigestUtils</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">md5Hex</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(input);</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    }</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">}</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div><div class=\"collapsed-lines\"></div></div><p>加入了 UserController，定义了 RESTful 接口，但是数据库连接部分还是通过注释提示的，没有生成出来，我们可以继续优化提示。</p>\n<blockquote>\n<p>你是一个软件开发工程师。请生成一个 Web 用户登录模块。前端使用 ReactJS+CSS+HTML 进行页面布局和发起 HTTP 请求。后端请使用 Java+SpringBoot+MyBatis 框架，使用 Maven 进行依赖包管理。要求密码使用 MD5 加密，并将具体的数据库连接代码生成出来。请按照以下步骤生成代码。第一步：用户在页面输入用户名和密码，点击登录。第二步：前端发起 HTTP 请求，服务端接口收到请求，对参数进行非空验证。第三步：通过数据库查询用户名和密码进行验证。请生成相关代码。</p>\n</blockquote>\n<p>当我们这样提问后，基本该有的代码都有了，数据库连接也加上了，前端页面的代码也补上了。这是一个简单的示例，需要注意的是，不同的大模型实现机制以及配置不同，你需要通过不断调试，找到合适的方式和大模型进行沟通交互，最终构建最合适的提示。</p>\n<h2>5. 万能工具：生成提示的提示</h2>\n<p>下面我给你展示一个非常强大的功能——生成提示的提示，让 ChatGPT 为你生成你需要的提示。</p>\n<p>你在 ChatGPT 中输入以下内容：</p>\n<p>我想让你成为我的提示工程师。你的目标是帮助我为我的需求制作尽可能好的提示。提示将由你使用。你需要遵循以下流程：</p>\n<ol>\n<li>你的第一反应是问我提示应该是什么。我会提供我的答案，但我们需要通过下一步不断地迭代来改进它。</li>\n<li>根据我的输入，你将生成 2 个部分：\n<ul>\n<li>修改后的提示（提供你重写的提示，它应该要清晰、简洁、易于理解）；</li>\n<li>问题（向我提出任何相关问题以改进提示）。</li>\n</ul>\n</li>\n<li>我们将继续这一迭代过程，我将向你提供更多信息，你也将更新修改后的提示部分中的提示，直到我说我们完成为止。</li>\n</ol>\n<p>将这段提示输入 ChatGPT，ChatGPT 会一步一步询问我们是否需要补充，直到我们回复【我们完成】才结束对话。你可以试试，功能很强大。这里我举一个例子，我们一起看一下。</p>\n<figure><figcaption></figcaption></figure>\n<figure><figcaption></figcaption></figure>\n<figure><figcaption></figcaption></figure>\n<figure><figcaption></figcaption></figure>\n<figure><figcaption></figcaption></figure>\n<p>这个工具的厉害之处在于，只要我们不喊停，它就会一直问，可以把提示调整得非常完善，这一步后，我就主动叫停了。</p>\n<figure><figcaption></figcaption></figure>\n<p>最后生成的提示如下：</p>\n<div class=\"language-text line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"text\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-text\"><span class=\"line\"><span>主题： 为初学者设计的6个月增肌30%、减脂20%计划，结合高蛋白饮食和哑铃力量训练。</span></span>\n<span class=\"line\"><span>内容： 专为无力量训练基础、喜欢高蛋白饮食和有氧运动的个体制定的健身计划。此计划强调使用哑铃进行力量训练，以适应新手的学习曲线，同时促进肌肉增长和脂肪燃烧。每周三次的训练将包括有氧运动和哑铃训练，逐步提高难度以适应身体变化。计划还建议寻找现场教练指导，以确保动作的正确性和安全性，同时使用蛋白粉补充营养，支持恢复和肌肉生长。</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><h2>6. 写给软件工程师的话</h2>\n<p>近一年人工智能发展速度非常快，我个人预测很有可能在五年内颠覆软件开发行业。为什么这么讲？因为软件开发的目的是实现用户和计算机的交互，而大模型的到来，已经改变了人类和计算机的交互形式，未来我们可能不再需要写代码，而是需要学会写提示，也就是<strong>从软件开发工程师向提示工程师转变。我们今天用的代码仓库，几年后可能就变成提示仓库了。</strong></p>\n<p>现在我们软件开发工程师的工作流程，和五年后我们作为提示工程师的工作流程，会有怎样的区别呢？你可以对比一下。</p>\n<figure><figcaption></figcaption></figure>\n<h2>7. 小结</h2>\n<p>这节课我们从与大模型交互方面入手，学习了提示及提示工程，提示是我们与大模型沟通的唯一桥梁，是决定大模型能否高效产出的关键。当然，使用的大模型不同，提示效果可能完全不同，这和我们人与人之间交往一样，不同的人有不同的性格，同一句话有人爱听有人不爱听。所以，和大模型“交往”也需要慢慢摸底，摸清楚对方的习惯和能力。</p>\n<figure><figcaption></figcaption></figure>\n<h2>8. 思考题</h2>\n<p>请你思考一下，我们为什么要为大模型指定角色呢？欢迎你把你思考后的结果分享到评论区，也欢迎你把这节课的内容分享给其他朋友，我们下节课再见！</p>\n\n<details class=\"hint-container details\"><summary>公众号：AI悦创【二维码】</summary>\n<figure><img src=\"/gzh.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n</details>\n<div class=\"hint-container info\">\n<p class=\"hint-container-title\">AI悦创·编程一对一</p>\n<p>AI悦创·推出辅导班啦，包括「Python 语言辅导班、C++ 辅导班、java 辅导班、算法/数据结构辅导班、少儿编程、pygame 游戏开发、Web、Linux」，招收学员面向国内外，国外占 80%。全部都是一对一教学：一对一辅导 + 一对一答疑 + 布置作业 + 项目实践等。当然，还有线下线上摄影课程、Photoshop、Premiere 一对一教学、QQ、微信在线，随时响应！微信：Jiabcdefh</p>\n<p>C++ 信息奥赛题解，长期更新！长期招收一对一中小学信息奥赛集训，莆田、厦门地区有机会线下上门，其他地区线上。微信：Jiabcdefh</p>\n<p>方法一：<a href=\"http://wpa.qq.com/msgrd?v=3&amp;uin=1432803776&amp;site=qq&amp;menu=yes\" target=\"_blank\" rel=\"noopener noreferrer\">QQ</a></p>\n<p>方法二：微信：Jiabcdefh</p>\n</div>\n<figure><img src=\"/zsxq.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n",
      "date_published": "2025-03-16T17:19:32.000Z",
      "date_modified": "2025-04-10T23:49:50.000Z",
      "authors": [
        {
          "name": "Bornforthis"
        }
      ],
      "tags": []
    },
    {
      "title": "01｜洞察本质：从工程学角度看 ChatGPT 为什么会崛起",
      "url": "https://bornforthis.cn/column/AI%E5%A4%A7%E6%A8%A1%E5%9E%8B%E5%AE%9E%E6%88%98%E9%AB%98%E6%89%8B%E8%AF%BE/01-%E6%B4%9E%E5%AF%9F%E6%9C%AC%E8%B4%A8%EF%BC%9A%E4%BB%8E%E5%B7%A5%E7%A8%8B%E5%AD%A6%E8%A7%92%E5%BA%A6%E7%9C%8BChatGPT%E4%B8%BA%E4%BB%80%E4%B9%88%E4%BC%9A%E5%B4%9B%E8%B5%B7.html",
      "id": "https://bornforthis.cn/column/AI%E5%A4%A7%E6%A8%A1%E5%9E%8B%E5%AE%9E%E6%88%98%E9%AB%98%E6%89%8B%E8%AF%BE/01-%E6%B4%9E%E5%AF%9F%E6%9C%AC%E8%B4%A8%EF%BC%9A%E4%BB%8E%E5%B7%A5%E7%A8%8B%E5%AD%A6%E8%A7%92%E5%BA%A6%E7%9C%8BChatGPT%E4%B8%BA%E4%BB%80%E4%B9%88%E4%BC%9A%E5%B4%9B%E8%B5%B7.html",
      "summary": "你好，我是悦创。 2022 年 11 月底，OpenAI 发布了 ChatGPT，2023 年 1 月注册用户超过一亿，成为历史上增长最快的应用，上一个纪录保持者是 TikTok，注册用户超过一亿用时 9 个月。2023 年 3 月开始，ChatGPT 燃爆中国互联网界。 实际上国内外同一时期搞大模型的团队很多，为什么 ChatGPT 会突然火起来？还...",
      "content_html": "<figure><figcaption></figcaption></figure>\n<p>你好，我是悦创。</p>\n<p>2022 年 11 月底，OpenAI 发布了 ChatGPT，2023 年 1 月注册用户超过一亿，成为历史上增长最快的应用，上一个纪录保持者是 TikTok，注册用户超过一亿用时 9 个月。2023 年 3 月开始，ChatGPT 燃爆中国互联网界。</p>\n<p>实际上国内外同一时期搞大模型的团队很多，为什么 ChatGPT 会突然火起来？还有在 ChatGPT 发布后，为什么各个大厂在短时间内相继发布大模型产品？比如 3 月百度发布文心一言，4 月阿里云发布通义千问，5 月科大讯飞发布星火认知大模型等等。</p>\n<figure><figcaption></figcaption></figure>\n<p>我们最容易想到的原因是，OpenAI 在自然语言处理（NLP）方面取得了突破性的进展，这是技术层面看到的。实际上，ChatGPT 背后包含了一系列的资源整合，包括技术、资金、大厂背书等等，以及多个国际巨头的通力合作，比如 OpenAI、微软、NVIDIA、GitHub 等。所以说，<strong>ChatGPT 不仅仅是技术上的突破，更是工程和产品的伟大胜利！</strong></p>\n<p>那么 ChatGPT 具体是如何赢得这场胜利的呢？我们一一来看。</p>\n<h2>1. NLP 技术突破：强势整合技术资源</h2>\n<p>基于 Transformer 架构的语言模型大体上分为两类，一类是以 BERT 为代表的<strong>掩码语言模型</strong>（Masked Language Model，MLM），一类以 GPT 为代表的<strong>自回归语言模型</strong>（Autoregressive Language Model，ALM）。OpenAI 的创建宗旨是：创建造福全人类的安全通用人工智能（AGI），所以创立之初就摒弃了传统 AI 模型标注式的训练方式，因为可用来标注的数据总是有限的，很难做得非常通用。那么为了实现 AGI，OpenAI 在技术上到底做对了什么呢？</p>\n<h3>1.1 基于自回归的无监督训练</h3>\n<p>GPT 系列的模型一直走的是和 BERT 不一样的线路，早些年压力巨大，毕竟 BERT 是 Google 发布的，非常权威。但是 OpenAI 一直认为自回归模型训练潜力更大，尤其在 GPT-2 引入 zero-shot 后，更加有信心了。</p>\n<p>按照人类语言的习惯，语言本身就有先后顺序，而且我们日常说话也是下文依赖上文。所以有人猜测，自回归语言模型代表了标准的语言模型，利用上文信息预测下文，这比传统 AI 预测更加复杂，但是上限更高，更有望通向 AGI，这正是 OpenAI 的愿景。尽管在 GPT-1 和 GPT-2 的探索中没有取得压倒性的效果，但确实验证了标准语言模型在 zero-shot 等方面的潜在能力。</p>\n<p>无监督自回归的训练方式，使 GPT 模型可以接受大量文本数据，所以后面有了 GPT-3，1750 亿的参数规模，使 GPT-3 直接问鼎当时最大的模型，GPT-3 使用了大约 45TB 的文本数据，一次训练费用近 460 万美元，在当时，相比上一代模型 GPT-2，效果已经非常好了，这也是人们所讲的大力出奇迹。</p>\n<p>但是，我们现在来看这个问题，GPT-3 发布时间大概是 2020 年 3 月，当时的 GPT-3 还不具备直接和人类对话的能力。而 ChatGPT 所使用的模型是 GPT-3.5，爆火时间在 2022 年年底到 2023 年 3 月，期间将近 2 年的时间，OpenAI 在做什么呢？答案是他们在想办法让 GPT 模型可以优雅地和人类进行对话。</p>\n<h3>1.2 与人类意识对齐（Alignment）</h3>\n<p>我们知道，人类是有感情的，很多事物是有极限的，比如人再怎么能吃也不可能一顿饭吃 100 个馒头，万一大模型输出的内容有这类意识，那么肯定是不合理的，所以要进行微调对齐。</p>\n<p>GPT-3 和 GPT-3.5 其实是两个不同的系列，使用过 OpenAI API 的人应该知道，还有几个细化的模型，比如 code-davinci、text-davince 系列。顾名思义，code-davince 就是 OpenAI 另一个产品 codex 使用的模型，在 text-davince-001 的基础上使用源代码进行训练，产生了 code-davinci-002 模型（codex）。再后来在 code-davinci-002 模型基础上，基于有监督的指令微调，产生了 text-davinci-002，最后在 text-davinci-002 模型基础上，使用 RLHF，产生了 text-davinci-003 和 ChatGPT 模型。演进过程如图所示：</p>\n<figure><figcaption></figcaption></figure>\n<p>GPT-3 经过充分训练，但是依然不是一个适合与人类进行对话的模型，所以从 GPT-3 到 GPT-3.5 再到 InstructGPT 和 ChatGPT，参数规模并没有太大变化，主要是经过了各种技术的微调，说白了就是去<strong>适配人类情景</strong>。其中，最突出的就是 RLHF。RLHF 就是 Reinforcement Learning From Human Feedback（人类反馈强化学习）的简称。关于 RLHF 的详细介绍，我们会放在后面的章节中。</p>\n<h3>1.3 突现能力（Emergent Ability）</h3>\n<p>突现能力是指大语言模型展现出来的特有的强大能力，比如复杂推理、思维链等。这些是 NLP 领域一直追求的能力，在大模型出现后，这些能力也随之浮现出来。我们举一个简单的例子。</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">问题：小明每天早饭吃2个馒头，他一个月会吃掉多少包馒头？</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">一个月按30天说，共吃掉60个馒头，每包5个馒头的话，总共12包。</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">答案：</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">12</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>这个推理看着简单，实际上对于 AI 来说有一定的难度，因为语言和数学混在一起了。在早期 GPT-3 模型上进行类似的推理，准确率并不高，低于 40%，后来在 code-davinci-002 上进行推理，准确率能达到 80% 以上。为什么性能会有这么大的提升？</p>\n<p>很明显原因不是模型规模，因为 code-davinci-002 在规模上并没有扩大，唯一能解释的就是 <strong>code-davinci-002 是基于代码进行训练的</strong>，这些突现能力是大模型经过大量代码训练后展现出来的能力。也有人说，面向过程的编程跟人类逐步解决任务的过程很类似，面向对象编程跟人类将复杂任务分解为多个简单任务的过程很类似。所以有人认为，代码训练和思维链及复杂推理有很强的相关性，不过到目前为止没有非常确定的证据可以证明这一点。</p>\n<p>我们可以总结一下。</p>\n<ol>\n<li>模型不是越大越好。论参数，GPT-3 的 1750 亿不是参数最大的模型，比如，微软和英伟达联合开发的 Megatron-Turing 模型拥有超过 5000 亿个参数，但是在性能方面并不是最好的，因为模型未经充分地训练。</li>\n<li>RLHF 也不是最早用在 GPT 上的，却在恰当的时机用到了 ChatGPT 身上。</li>\n<li>在语言模型上使用大量代码进行训练，只有 codex 这么做了。</li>\n</ol>\n<p>所以，ChatGPT 在技术上的突破可以理解为：</p>\n<p v-pre=\"\" class=\"katex-block\"><span class=\"katex-display\"><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\" display=\"block\"><semantics><mrow><mtext>自回归语言模型</mtext><mo>+</mo><mtext>充分无监督训练</mtext><mo>+</mo><mtext>大量代码训练</mtext><mo>+</mo><mtext>有监督指令微调</mtext><mo>+</mo><mtext>RLHF</mtext></mrow><annotation encoding=\"application/x-tex\">\\text{自回归语言模型}+\\text{充分无监督训练}+\\text{大量代码训练}+\\text{有监督指令微调}+\\text{RLHF}\n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.7667em;vertical-align:-0.0833em;\"></span><span class=\"mord text\"><span class=\"mord cjk_fallback\">自回归语言模型</span></span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.7667em;vertical-align:-0.0833em;\"></span><span class=\"mord text\"><span class=\"mord cjk_fallback\">充分无监督训练</span></span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.7667em;vertical-align:-0.0833em;\"></span><span class=\"mord text\"><span class=\"mord cjk_fallback\">大量代码训练</span></span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.7667em;vertical-align:-0.0833em;\"></span><span class=\"mord text\"><span class=\"mord cjk_fallback\">有监督指令微调</span></span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord text\"><span class=\"mord\">RLHF</span></span></span></span></span></span></p>\n<p>放眼望去，全球仅此一家！那这么多技术叠加在一起，怎么才能“大力出奇迹”呢？答案就是进行超大规模预训练。</p>\n<h2>2. 超大规模数据集：超过 40T 的文本数据</h2>\n<p>大模型训练首先需要搞定高质量数据集，我们分两个点去考虑。</p>\n<p>首先，我向你介绍下基础模型 GPT-3 的训练数据集。GPT-3 模型具有 1750 亿个参数，训练数据集大约 500B 个 token（1B=1 billion，也就是 10 亿）。下面是训练数据大概的组成结构：</p>\n<figure><figcaption>数据源于官方的 GPT-3 论文《Language Models are Few-Shot Learners》</figcaption></figure>\n<p>原始大约 45T 的纯文本数据，经历过滤后，大概是 750G 的高质量文本数据。</p>\n<p>我们再来看下 ChatGPT 的训练数据。ChatGPT 属于 GPT-3.5 系列，官方并没有明确说明这个模型的参数规模，所以网上看到的大部分的数据都是猜测，有人说 15 亿，也有人说 20 亿甚至 1500 亿。但是大概率，ChatGPT 的参数规模是小于 GPT-3 的，其训练数据基于大量对话型数据进行指令微调，典型训练数据如下：</p>\n<ul>\n<li><strong>Persona-Chat 的数据集</strong>：专门用于训练 ChatGPT 等会话式 AI 模型。由两个人类参与者之间的超过 160,000 条对话组成，每个参与者都被分配了一个独特的角色来描述他们的背景、兴趣和个性。这使得 ChatGPT 能够学习如何生成个性化且与对话的特定上下文相关的响应。</li>\n<li><strong>康奈尔电影对话语料库</strong>：包含电影脚本中角色之间对话的数据集。包括 10,000 多个电影角色对之间的 200,000 多次对话，涵盖各种主题和类型。</li>\n<li><strong>Ubuntu 对话语料库</strong>：寻求技术支持的用户与 Ubuntu 社区支持团队之间多轮对话的集合。它包含超过 100 万个对话，使其成为用于对话系统研究的最大的公开数据集之一。</li>\n<li><strong>DailyDialog</strong>：各种主题的人与人对话的集合，从日常生活对话到有关社会问题的讨论。数据集中的每个对话都由几个回合组成，并标有一组情感、情绪和主题信息。</li>\n</ul>\n<p>除了这些数据集之外，ChatGPT 还接受了互联网上大量非结构化数据的训练，包括网站、书籍和其他文本源。这使得 ChatGPT 能够从更一般的意义上了解语言的结构和模式，然后可以针对对话管理或情感分析等特定应用进行微调。</p>\n<p>有这么多数据了，接着就要进行预训练了。下面这一步卡住了大部分大模型厂商，那就是<strong>计算资源</strong>。对于 OpenAI 这种创业公司而言，无疑是很大的困难，那他们是怎么解决的呢？没错，找金主爸爸。</p>\n<h2>3. 找对了金主爸爸</h2>\n<p>OpenAI 做对了一件非常重要的事儿，那就是找钱，而且还是找大钱，动辄几亿美元的投入。GPT-3 的单次训练成本高达 460 万美元。在前景未知的情况下，这么大的投入是非常难的。找钱成了 OpenAI 非常重要的事情，为了找钱，OpenAI 从开源转为闭源。</p>\n<p>实际上，早期 OpenAI 是开源的，创办宗旨就是创建通用人工智能，造福人类，但是大模型训练需要大量的计算资源和数据，这是实打实需要资金投入的，所以 OpenAI 由开源转为闭源，设计了一种商业模式来吸引投资人，并吸引大量资金，其中最主要的就是微软。下面我向你介绍下这种商业模式。</p>\n<p>OpenAI 母公司是 OpenAI Inc，属于非营利性质组织，这种情况下资本无法进入，所以后来成立了一家子公司，叫 OpenAI LP，现在我们常说的 OpenAI，其实就是 OpenAI LP，这是一家纯粹的商业化公司，这家公司设置了最高 100 倍的回报上限，以此来权衡盈利和非盈利属性，也可以叫做“有限盈利”，既迎合资本家利益，也看似符合母公司非盈利组织的创建初衷。</p>\n<figure><figcaption></figcaption></figure>\n<p>通过这种股权结构，成功获得微软累计超过 100 亿美金的投资，这里不得不说，微软为 OpenAI 带来的不仅仅是钱，更是强大的影响力，毕竟全世界人民是认微软的，包括我们中国人。</p>\n<p>当模型完成大规模训练后，接下来就是面世了，OpenAI 的玩法很直接，直接产品化，让大家随便玩。</p>\n<h2>4. 产品化开放：让大家随便玩</h2>\n<p>ChatGPT 成功之处在于，愿意公开免费给普通用户使用，虽然各大厂商都在宣称自己在搞大模型，且有多么厉害，但真正产品化后开放给用户的，还要数 ChatGPT。</p>\n<h3>4.1 便捷使用</h3>\n<p>大部分的 AI 厂家只发布模型，感兴趣的技术人员去 Huggingface 下载，自己部署把玩，这样就把模型限制在了非常小的一个范围内。</p>\n<p>而 ChatGPT 不一样，发布的是普通大众用户都可以使用的产品。通过邮箱注册就可以使用，全天候不限时，直接通过网页对话，<strong>使用门槛非常低</strong>。这要放在国内，还不得让你下载个 App，甚至拉几个朋友才可以用。毕竟这背后是实打实的 GPU 算力成本，据说 2022 年 ChatGPT 的算力费用（包含训练和推理）＋人力成本接近 5 亿美金，试问一下哪个小厂具备这样的实力？而哪个大厂又会在看不到业务前景的背景下，每年投这么多钱去玩？但 OpenAI 做到了。</p>\n<p>从 2024 年 4 月份开始，ChatGPT 开启无需注册即可使用的模式，彻底成为互联网基础设施。</p>\n<h3>4.2 适用场景多</h3>\n<p>OpenAI 官方公开的 ChatGPT 使用场景有 30 类（参考<a href=\"https://platform.openai.com/examples\" target=\"_blank\" rel=\"noopener noreferrer\">官方链接</a>），可以用于代码编写、代码翻译、智能问答、语音识别、模拟面试、情感分析、机器翻译、智能客服等多个领域。这使得更多的人能够感受到 ChatGPT 带来的便利和价值，容易获得大众的支持和信任。</p>\n<h3>4.3 使用效果好</h3>\n<p>在 ChatGPT 之前，市面上已经有很多 AI 问答机器人产品，比如微软小冰、小度，用过的人都知道，它们都有很多局限性。小冰是由小模型组成的，只能同时处理特定类型任务，无法相互关联，小度也一样，这类产品无法做通用性的问答，无法像 ChatGPT 一样，像是真人在回答，甚至还有记忆、有感情。</p>\n<h3>4.4 工程化应用</h3>\n<p>工程化即系统化、模块化、规范化的一个过程。我们做工程技术的开发人员很清楚，一个优秀的产品背后一定是有着惊人的技术参数，就拿支付宝来说，双十一高峰期，50 万笔 / 秒的支付吞吐量，背后是大量的服务堆出来的，比如数百万台的服务器、大量的分布式技术的应用，如缓存、消息、文件存储等等。</p>\n<p>ChatGPT 也一样，OpenAI 不是仅仅提供一个模型，让我们自己部署自己玩，而是直接将以大模型为内核的整套技术完成了产品化。对于两个月注册用户过亿的世界级产品来讲，这里面涉及到的技术可想而知，除了 AI 本身涉及的技术外，常见的工程化技术一样少不了。Web 相关的我们就不讲了，主要分享下和模型训练相关的技术。</p>\n<p>为了方便进行大模型训练。2020 年，微软为 OpenAI 在 Azure 上搭建了计算集群，包含 285000 个 AMD infiniBand 连接的 CPU 内核，另外还有 10000 个 NVIDIA V100 Tensor Core GPU，是当时世界上第五大超级计算机，也是有史以来在公共云中（Azure）建立的最大的超级计算机。</p>\n<p>我们知道，大模型训练动不动就是几周、几个月的训练，而如果服务器出现故障或者网络连接不稳定，怎么办？肯定不希望从头开始。那么如何实现容错呢？</p>\n<p>微软开发了 Project Forge，即 Azure 容器化和全局调度服务，可以保证 AI 计算负载保持高水平的利用率；通过建立透明检查点，定期增量保存模型的状态和代码，出现故障，恢复到最近检查点；同时硬件厂家 NVIDIA 也做了调整，他们的 GPU 实现了 CRIU（用户模式下的检查点恢复），可以恢复 GPU 的内存使用，最终和 CPU 的检查点保持一致。软件和硬件协同工作，提高了效率。</p>\n<p>所以光是模型训练这一步，为了实现可靠性，就集微软工程部门、微软研究院、OpenAI 团队、NVIDIA 团队共同努力于一体。同时，还涉及了隐私计算、私密 GPU、TE 空间等等。除此之外，OpenAI 还雇佣了大量工人（约 7.7 万人）进行人工标注，总体硬件成本接近 10 亿美金，单日运营成本高达 70 万美金，真的是很烧钱。</p>\n<h2>5. 小结</h2>\n<p>这节课我从宏观方面向你介绍了 ChatGPT 崛起的原因，相信你也对 ChatGPT 有了更深入的理解。下面我们再简单总结一下。所谓<strong>工程化主要就是指集技术、数据、产品、资源于一身，是一个系统性、规范性的工程项目</strong>，很多人想到 ChatGPT，就想到了大模型本身，其实这是片面的，具体你可以参考下面思维导图再回顾一下细节。</p>\n<p>AI 大模型还处于发展非常迅速的阶段，实际上天天都在发生变化，所以很多事情都还没有定论，我们需要保持开放的心态，不断接纳，不断学习。下一节课，我会从如何用好大模型这个角度，给你讲解下<strong>提示词工程</strong>，这也是刚接触 AI 大模型的用户非常容易忽略的问题，当然这也是能否用好 AI 大模型的核心。</p>\n<h2>6. 思考题</h2>\n<p>学完了这节课的内容，请你来思考 2 个问题，ChatGPT 已经这么强大了，那它是否已经具备了人类大脑的思维？还有 AI 到底能否代替我们目前的工作？欢迎你把你的观点分享到评论区，我们一起讨论，如果你觉得这节课的内容对你有帮助的话，也欢迎你分享给其他朋友，我们下节课再见！</p>\n\n<details class=\"hint-container details\"><summary>公众号：AI悦创【二维码】</summary>\n<figure><img src=\"/gzh.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n</details>\n<div class=\"hint-container info\">\n<p class=\"hint-container-title\">AI悦创·编程一对一</p>\n<p>AI悦创·推出辅导班啦，包括「Python 语言辅导班、C++ 辅导班、java 辅导班、算法/数据结构辅导班、少儿编程、pygame 游戏开发、Web、Linux」，招收学员面向国内外，国外占 80%。全部都是一对一教学：一对一辅导 + 一对一答疑 + 布置作业 + 项目实践等。当然，还有线下线上摄影课程、Photoshop、Premiere 一对一教学、QQ、微信在线，随时响应！微信：Jiabcdefh</p>\n<p>C++ 信息奥赛题解，长期更新！长期招收一对一中小学信息奥赛集训，莆田、厦门地区有机会线下上门，其他地区线上。微信：Jiabcdefh</p>\n<p>方法一：<a href=\"http://wpa.qq.com/msgrd?v=3&amp;uin=1432803776&amp;site=qq&amp;menu=yes\" target=\"_blank\" rel=\"noopener noreferrer\">QQ</a></p>\n<p>方法二：微信：Jiabcdefh</p>\n</div>\n<figure><img src=\"/zsxq.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n",
      "date_published": "2025-03-16T16:36:23.000Z",
      "date_modified": "2025-04-10T23:49:50.000Z",
      "authors": [
        {
          "name": "Bornforthis"
        }
      ],
      "tags": []
    },
    {
      "title": "开篇词｜开发工程师如何进阶为AI应用型人才？",
      "url": "https://bornforthis.cn/column/AI%E5%A4%A7%E6%A8%A1%E5%9E%8B%E5%AE%9E%E6%88%98%E9%AB%98%E6%89%8B%E8%AF%BE/00-%E5%BC%80%E7%AF%87%E8%AF%8D-%E5%BC%80%E5%8F%91%E5%B7%A5%E7%A8%8B%E5%B8%88%E5%A6%82%E4%BD%95%E8%BF%9B%E9%98%B6%E4%B8%BAAI%E5%BA%94%E7%94%A8%E5%9E%8B%E4%BA%BA%E6%89%8D%EF%BC%9F.html",
      "id": "https://bornforthis.cn/column/AI%E5%A4%A7%E6%A8%A1%E5%9E%8B%E5%AE%9E%E6%88%98%E9%AB%98%E6%89%8B%E8%AF%BE/00-%E5%BC%80%E7%AF%87%E8%AF%8D-%E5%BC%80%E5%8F%91%E5%B7%A5%E7%A8%8B%E5%B8%88%E5%A6%82%E4%BD%95%E8%BF%9B%E9%98%B6%E4%B8%BAAI%E5%BA%94%E7%94%A8%E5%9E%8B%E4%BA%BA%E6%89%8D%EF%BC%9F.html",
      "summary": "你好，我是悦创。 欢迎你加入这个专栏，和我来一场 AI 大模型深度游。 近年来，我开始深入研究 AI 领域，阅读了数百篇相关论文，逐渐领略到这一领域的魅力与潜力。对于我们这些具备开发基础的技术人员来说，AI 无疑是一个充满机遇的新领域。近期的两会上，人工智能也再次成为国家战略焦点，预示着未来十年到十五年的行业发展红利。从互联网 + 到人工智能 +，我们...",
      "content_html": "<figure><figcaption></figcaption></figure>\n<p>你好，我是悦创。</p>\n<p>欢迎你加入这个专栏，和我来一场 AI 大模型深度游。</p>\n<p>近年来，我开始深入研究 AI 领域，阅读了数百篇相关论文，逐渐领略到这一领域的魅力与潜力。对于我们这些具备开发基础的技术人员来说，AI 无疑是一个充满机遇的新领域。近期的两会上，人工智能也再次成为国家战略焦点，预示着未来十年到十五年的行业发展红利。<strong>从互联网 + 到人工智能 +，我们将迎来新一轮技术革新和人才需求的增长。</strong></p>\n<p>我相信，在未来的发展中，AI 将引领我们走向更加智能、高效的新时代，所以它非常值得我们花时间好好去钻研。</p>\n<h2>1. 转型为 AI 应用型工程师的难点</h2>\n<p>对于广大软件开发人员来说，人工智能的深度研究可能会因为它本身的复杂性而令人生畏。然而，我们完全可以将注意力转向<strong>人工智能的应用领域</strong>。</p>\n<p>其实不用我多说，作为一个技术开发人员，你可能早已投身于这股滚滚热潮之中了，因为人工智能本身就是技术领域的一个重要分支。敏锐如你我，经过这一年多的时间，应该已经尝试了个遍。不过在应用 AI 大模型的过程中，你应该也遇到了很多问题。</p>\n<p>比如：</p>\n<ul>\n<li>小团队如何解决 GPU 与存储空间等资源问题？</li>\n<li>如何在众多模型中选择适合自己领域的模型并进行优化？</li>\n<li>如何从 0 到 1 构建一个自己领域内的大模型？</li>\n<li>将微调后的大模型应用于具体的业务场景，要考虑哪些因素？</li>\n<li>没有机器学习和深度学习基础，怎么深度使用大模型？</li>\n<li>如何在确保兼容性的情况下，将大模型集成到现有技术栈中？</li>\n<li>如何在确保兼容性的情况下，将大模型集成到现有技术栈中？</li>\n<li>……</li>\n</ul>\n<p>无论你是自己探索，还是为企业布局 AI 做准备，这些都是避不开的问题。不过你也不用担心，这些问题你都可以在课程中找到答案。</p>\n<h2>2. 开发工程师入局 AI 的最佳路径</h2>\n<figure><figcaption></figcaption></figure>\n<p>刚刚的那些问题其实也正是开发工程师想要转变为 AI 应用型 工程师的难点。要想克服这些难点，我们首先要做的就是持续更新自己的知识体系，对 AI 的发展和应用情况有一个清楚的认知，来适应 AI 领域的快速变化。现在了解 AI 讯息的渠道很多，无论是公众号、社区，还是一些技术网站，都是稳定的信息来源，可以源源不断地获取最新动态。</p>\n<p>其次是部署一些有代表性的模型产品进行试用，比如 LLaMA、ChatGLM 等，为你后面大模型选型打下基础，毕竟体验过后才有发言权。</p>\n<p>此外你还需要学习相关的技术，AI 技术的本质是机器学习，是一个独立的技术体系，学习起来会有一定的难度，不过这些机器学习的原理并不要求你全部掌握，只掌握你领域内最核心的技术原理就可以了，比如大语言模型技术原理中的 Transformer 架构、Word2Vec 等等。</p>\n<p>最后，积累丰富的实际项目经验同样至关重要，这有助于将理论知识有效地转化为解决具体业务问题的能力，这也正是企业最看重的一项能力。生成式 AI 适合大部分行业，因为符合人类语言环境，只要有语言的地方，基本都能找到生成式 AI 的适用场景，即便你所在行业业务方面没有适用的场景，但是我们还是可以把 AI 作为个人助手，来辅助我们做很多事情，所以你要想办法找到场景，将自己所学的技术进行实践。</p>\n<p>对于想要入局 AI 的研发工程师，我觉得最好的学习路径就是这样。</p>\n<h2>3. 这门课程是如何设计的？</h2>\n<p>我根据这条最佳的学习路径，由浅入深地把课程分成了 5 个章节。</p>\n<figure><figcaption></figcaption></figure>\n<h3>3.1 第一章：小试牛刀，理解基础概念</h3>\n<p>在这部分，我会向你介绍 ChatGPT 的发展，以及大语言模型中非常重要的概念：提示和智能体。学完了这一章的内容之后，你就会初步认识到 AI 的重要性，对研发工程师该着重从哪方面入手有一个清晰的认知。</p>\n<h3>3.2 第二章：超燃实战，深度玩转 AI 模型</h3>\n<p>这一章，我会带你进行各种尝试，来感受大模型的魅力，学完这一章，你将学会如何部署、微调、RAG、封装大模型，这部分内容就是你在企业里落地大模型应用的基础。</p>\n<h3>3.3 第三章：打入核心，挑战底层技术原理</h3>\n<p>从这一章开始，我会带你深入技术细节，理解大模型的原理。相信你在体验完大模型后，一定会有很多疑问，比如大模型的权重文件里到底存放的是什么？大模型推理原理是什么样的？所有的疑问将会在学完这一章后全部解开。</p>\n<h3>3.4 第四章：终极玩法，从 0 到 1 构建大模型</h3>\n<p>当你学完原理后如何才能将所学知识吃透呢？那就需要亲自上手实战了，我们将使用上一章学到的知识，自己一步一步构建一个大模型，你甚至可以根据自己的需求去构建其他模型，比如翻译、分类、个人小助手等场景，我相信这会非常酷。</p>\n<h3>3.5 第五章：热点速递，AI 行业发展趋势预测</h3>\n<p>这一章节我们会深入探讨了 AI 行业的最新发展趋势，包括 Mamba 模型、Sora、机器人与大模型、人工智能与无人机，以及 AI 发展的下一阶段 <code>Q-Star(*)</code> 的概念。通过学习这些内容，你将了解到 AI 技术如何在不同领域产生深远影响，以及这些新兴技术将会如何塑造我们未来的工作和生活方式。</p>\n<h2>4. 写在最后</h2>\n<p>无论你当前处于何种阶段，是否已具备 AI 技术基础，都不必过于忧虑。根据创新扩散定律，当前 AI 领域正处于早期接受者的阶段，这意味着行业仍在快速发展但尚未成熟的阶段。因此，你拥有足够的时间来深入学习和探索。我们要保持<strong>短期跟进，长期看好</strong>的心态。人工智能无疑是未来的趋势，大方向不会错。现在就是上车的好时机，跟上队伍的节奏，不断学习和进步。</p>\n<p>我希望在探索人工智能的道路上你不仅仅能够学到 AI 相关的知识，更重要的能够<strong>养成数据驱动与模型驱动的思维</strong>，掌握处理和分析数据的技能，将数据作为大模型的基石，深刻理解模型的工作原理和应用场景。希望这门课程能够为你打开人工智能技术世界的大门，激发你的灵感，引领你走向更广阔的未来。</p>\n\n<details class=\"hint-container details\"><summary>公众号：AI悦创【二维码】</summary>\n<figure><img src=\"/gzh.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n</details>\n<div class=\"hint-container info\">\n<p class=\"hint-container-title\">AI悦创·编程一对一</p>\n<p>AI悦创·推出辅导班啦，包括「Python 语言辅导班、C++ 辅导班、java 辅导班、算法/数据结构辅导班、少儿编程、pygame 游戏开发、Web、Linux」，招收学员面向国内外，国外占 80%。全部都是一对一教学：一对一辅导 + 一对一答疑 + 布置作业 + 项目实践等。当然，还有线下线上摄影课程、Photoshop、Premiere 一对一教学、QQ、微信在线，随时响应！微信：Jiabcdefh</p>\n<p>C++ 信息奥赛题解，长期更新！长期招收一对一中小学信息奥赛集训，莆田、厦门地区有机会线下上门，其他地区线上。微信：Jiabcdefh</p>\n<p>方法一：<a href=\"http://wpa.qq.com/msgrd?v=3&amp;uin=1432803776&amp;site=qq&amp;menu=yes\" target=\"_blank\" rel=\"noopener noreferrer\">QQ</a></p>\n<p>方法二：微信：Jiabcdefh</p>\n</div>\n<figure><img src=\"/zsxq.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n",
      "date_published": "2025-03-16T14:19:35.000Z",
      "date_modified": "2025-04-10T23:49:50.000Z",
      "authors": [
        {
          "name": "Bornforthis"
        }
      ],
      "tags": []
    },
    {
      "title": "01-字符串内容补充",
      "url": "https://bornforthis.cn/Books/02-SupplementaryArticles/Python/01-string.html",
      "id": "https://bornforthis.cn/Books/02-SupplementaryArticles/Python/01-string.html",
      "summary": "1. 何为迭代？ 点击展开阅读 在学习 Python 时，我们经常会听到 “可迭代”（iterable） 这个词。对于初学者来说，这个概念可能有些抽象。那么，什么是“可迭代”？它和“不可迭代”有什么区别？今天我们就用通俗易懂的方式来讲解这个概念，让你一看就懂！这部分的知识，也是为了便于后续的学习而增加的。 用一个类似的知识来辅助下面知识点的理解：分子属...",
      "content_html": "<h2>1. 何为迭代？</h2>\n<details class=\"hint-container details\"><summary>点击展开阅读</summary>\n<p>在学习 Python 时，我们经常会听到 <strong>“可迭代”（iterable）</strong>  这个词。对于初学者来说，这个概念可能有些抽象。那么，什么是“可迭代”？它和“不可迭代”有什么区别？今天我们就用通俗易懂的方式来讲解这个概念，让你一看就懂！这部分的知识，也是为了便于后续的学习而增加的。</p>\n<p>用一个类似的知识来辅助下面知识点的理解：分子属于可迭代对象，原子属于不可迭代对象。为什么这么说呢：分子可以拆分成原子，但原子属于不可再拆分。可以再被拆分的称为可迭代，不可再被拆分的称为不可迭代。</p>\n<h3>1. 什么是：“可迭代”？</h3>\n<p>在 Python 编程中，“可迭代”（iterable）是指 <strong>可以一个一个取出元素的东西</strong>。</p>\n<h4>1.1 举个简单的例子</h4>\n<p>想象你有一本书，书里有很多页。你可以一页一页地翻，这本书就是<strong>可迭代的</strong>，因为你可以“遍历”它的每一页。</p>\n<p>再比如：想象你有一个<strong>音乐播放列表</strong>，里面有很多歌曲，你可以一首一首地播放。这个<strong>播放列表</strong>就是<strong>可迭代的</strong>，因为你可以<strong>逐个获取</strong>里面的每一首歌，并且按顺序播放或随机播放。</p>\n<p>在 Python 中，<strong>可迭代的对象</strong>包括：</p>\n<p>| <strong>对象类型</strong>         | <strong>示例代码</strong>                         | <strong>说明</strong>                                   |<br>\n|</p>\n</details>\n",
      "date_published": "2025-05-04T06:54:06.000Z",
      "date_modified": "2025-05-07T11:20:58.000Z",
      "authors": [
        {
          "name": "AI悦创"
        }
      ],
      "tags": []
    },
    {
      "title": "SCIF30005：Forest Fire Mini Project",
      "url": "https://bornforthis.cn/1v1/54-BananaYuShu/Other/SCIF30005-Forest-Fire-Mini-Project.html",
      "id": "https://bornforthis.cn/1v1/54-BananaYuShu/Other/SCIF30005-Forest-Fire-Mini-Project.html",
      "summary": "Overview The topic of the project is the forest fire model, a type of cellular automaton which is introduced in the ‘Forest Fire’ video, found on Blackboard under week 19. The r...",
      "content_html": "<h2>Overview</h2>\n<p>The topic of the project is the forest fire model, a type of cellular automaton which is introduced in the ‘Forest Fire’ video, found on Blackboard under week 19. The rules are briefly explained below, but you should watch the video for a more detailed explanation.</p>\n<p>The deadline for submission is 12:30pm, on Wednesday of week 23. You should submit:</p>\n<ul>\n<li>your C++ code</li>\n<li>a 5-6 page report</li>\n</ul>\n<p>You will not be penalised for going slightly over the page limit, but if you are significantly over, you should consider whether you are e.g. including more graphs than is necessary to justify your conclusions. You do not need to submit any code used to generate graphs or otherwise post-process your output, or any bash scripts that you may have used.</p>\n<h2>Model Rules</h2>\n<p>A square grid of size <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>N</mi></mrow><annotation encoding=\"application/x-tex\">N</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.10903em;\">N</span></span></span></span> is randomly filled with trees, with probability <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>p</mi></mrow><annotation encoding=\"application/x-tex\">p</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.625em;vertical-align:-0.1944em;\"></span><span class=\"mord mathnormal\">p</span></span></span></span> that any given cell contains a tree. To start the fire, any living trees in the top row are then set on fire. Then, for each point on the grid at time step <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>t</mi></mrow><annotation encoding=\"application/x-tex\">t</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6151em;\"></span><span class=\"mord mathnormal\">t</span></span></span></span>:</p>\n<ul>\n<li>any living tree next to a tree which was burning at step <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>t</mi><mo>−</mo><mn>1</mn></mrow><annotation encoding=\"application/x-tex\">t− 1</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6984em;vertical-align:-0.0833em;\"></span><span class=\"mord mathnormal\">t</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">−</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6444em;\"></span><span class=\"mord\">1</span></span></span></span> starts burning</li>\n<li>any tree which was burning at step <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>t</mi><mo>−</mo><mn>1</mn></mrow><annotation encoding=\"application/x-tex\">t− 1</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6984em;vertical-align:-0.0833em;\"></span><span class=\"mord mathnormal\">t</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">−</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6444em;\"></span><span class=\"mord\">1</span></span></span></span> is now dead</li>\n<li>all other sites stay in the same state (i.e. empty sites remain empty, living trees with no burning neighbours remain alive, dead trees remain dead).</li>\n</ul>\n<p>A neighbour is defined as a cell to the left, right, above or below the cell we are interested in, with diagonal cells <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>n</mi><mi>o</mi><mi>t</mi></mrow><annotation encoding=\"application/x-tex\">not</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6151em;\"></span><span class=\"mord mathnormal\">n</span><span class=\"mord mathnormal\">o</span><span class=\"mord mathnormal\">t</span></span></span></span> considered to be neighbours (i.e. we are using a Von Neumann neighbourhood). The simulation proceeds until no more trees are burning.</p>\n<h2>Implementation</h2>\n<p>You should implement the forest fire model in C++, using <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>M</mi><mi>P</mi><mi>I</mi></mrow><annotation encoding=\"application/x-tex\">MPI</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">MP</span><span class=\"mord mathnormal\" style=\"margin-right:0.07847em;\">I</span></span></span></span> to parallelise a <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>s</mi><mi>i</mi><mi>n</mi><mi>g</mi><mi>l</mi><mi>e</mi></mrow><annotation encoding=\"application/x-tex\">single</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8889em;vertical-align:-0.1944em;\"></span><span class=\"mord mathnormal\">s</span><span class=\"mord mathnormal\">in</span><span class=\"mord mathnormal\" style=\"margin-right:0.03588em;\">g</span><span class=\"mord mathnormal\" style=\"margin-right:0.01968em;\">l</span><span class=\"mord mathnormal\">e</span></span></span></span> <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>r</mi><mi>u</mi><mi>n</mi></mrow><annotation encoding=\"application/x-tex\">run</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.4306em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord mathnormal\">u</span><span class=\"mord mathnormal\">n</span></span></span></span> of the model, i.e. it should be possible to run the code for a single starting grid, grid size <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>N</mi></mrow><annotation encoding=\"application/x-tex\">N</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.10903em;\">N</span></span></span></span> , and probability <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>p</mi></mrow><annotation encoding=\"application/x-tex\">p</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.625em;vertical-align:-0.1944em;\"></span><span class=\"mord mathnormal\">p</span></span></span></span>, while using multiple <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>M</mi><mi>P</mi><mi>I</mi></mrow><annotation encoding=\"application/x-tex\">MPI</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">MP</span><span class=\"mord mathnormal\" style=\"margin-right:0.07847em;\">I</span></span></span></span> tasks.</p>\n<p>The C++ code should contain the following features:</p>\n<ul>\n<li>\n<p>the ability to read in an initial grid from a text file, for which an example will be supplied</p>\n</li>\n<li>\n<p>the ability to generate a random starting grid of size <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>N</mi></mrow><annotation encoding=\"application/x-tex\">N</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.10903em;\">N</span></span></span></span> with probability <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>p</mi></mrow><annotation encoding=\"application/x-tex\">p</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.625em;vertical-align:-0.1944em;\"></span><span class=\"mord mathnormal\">p</span></span></span></span></p>\n</li>\n<li>\n<p>the ability to average over <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>M</mi></mrow><annotation encoding=\"application/x-tex\">M</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.10903em;\">M</span></span></span></span> independent runs, e.g. for <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>M</mi></mrow><annotation encoding=\"application/x-tex\">M</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.10903em;\">M</span></span></span></span> starting grids which were initialised with different random seeds</p>\n</li>\n<li>\n<p>the code should output:</p>\n<ul>\n<li>the number of steps before the fire stops burning</li>\n<li>whether or not the fire reached the bottom of the grid</li>\n<li>the time taken to run a given simulation</li>\n</ul>\n</li>\n</ul>\n<p>You will also need to run the code for different probabilities <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>p</mi></mrow><annotation encoding=\"application/x-tex\">p</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.625em;vertical-align:-0.1944em;\"></span><span class=\"mord mathnormal\">p</span></span></span></span> and grid sizes <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>N</mi></mrow><annotation encoding=\"application/x-tex\">N</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.10903em;\">N</span></span></span></span> . It is up to you whether you do this within your C++ code (e.g. using a loop over probabilities <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>p</mi></mrow><annotation encoding=\"application/x-tex\">p</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.625em;vertical-align:-0.1944em;\"></span><span class=\"mord mathnormal\">p</span></span></span></span>), or by using a bash script to run your code repeatedly with different inputs.</p>\n<h2>Model Convergence</h2>\n<p>In the video introducing the forest fire model, we talked about convergence with respect to a) the number of random starting grids, <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>M</mi></mrow><annotation encoding=\"application/x-tex\">M</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.10903em;\">M</span></span></span></span> (i.e. the number of repeat runs) and b) the size of the grid, <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>N</mi></mrow><annotation encoding=\"application/x-tex\">N</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.10903em;\">N</span></span></span></span>. For example, if you run the code once with a given random starting grid, and then run it again with a different starting grid, the number of steps the simulation runs for may not be the same, even for the same <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>N</mi></mrow><annotation encoding=\"application/x-tex\">N</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.10903em;\">N</span></span></span></span> and <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>p</mi></mrow><annotation encoding=\"application/x-tex\">p</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.625em;vertical-align:-0.1944em;\"></span><span class=\"mord mathnormal\">p</span></span></span></span> values, due to the effects of randomness. If, however, you run the code <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>M</mi></mrow><annotation encoding=\"application/x-tex\">M</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.10903em;\">M</span></span></span></span> times and average the results, for a large enough value of <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>M</mi></mrow><annotation encoding=\"application/x-tex\">M</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.10903em;\">M</span></span></span></span> the average number of steps taken will no longer change significantly. I.e. for a large enough value of <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>M</mi></mrow><annotation encoding=\"application/x-tex\">M</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.10903em;\">M</span></span></span></span> , further increases in <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>M</mi></mrow><annotation encoding=\"application/x-tex\">M</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.10903em;\">M</span></span></span></span> will result in only negligible changes to the average behaviour. In other words, the model has converged.</p>\n<p>For this project, we will focus only on convergence with respect to the number of repeat runs, <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>M</mi></mrow><annotation encoding=\"application/x-tex\">M</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.10903em;\">M</span></span></span></span> . You may use a fixed grid size of <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>N</mi><mo>=</mo><mn>100</mn></mrow><annotation encoding=\"application/x-tex\">N = 100</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.10903em;\">N</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6444em;\"></span><span class=\"mord\">100</span></span></span></span>. Using your code, you should answer the following questions:</p>\n<ul>\n<li>is <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>M</mi><mo>=</mo><mn>50</mn></mrow><annotation encoding=\"application/x-tex\">M = 50</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.10903em;\">M</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6444em;\"></span><span class=\"mord\">50</span></span></span></span> a sufficient number of repeats to reach convergence?</li>\n<li>does the answer depend on the initial probability <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>p</mi></mrow><annotation encoding=\"application/x-tex\">p</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.625em;vertical-align:-0.1944em;\"></span><span class=\"mord mathnormal\">p</span></span></span></span>, and if so, how?</li>\n</ul>\n<p>Your answer should be backed up by data, and you should describe how you came to this conclusion,as well as any strengths and/or limitations of your approach. For example, did you have to make any compromises about the number of calculations performed, and given unlimited time, would you therefore do any further calculations?</p>\n<h2>Performance Analysis</h2>\n<p>The final aspect of the project is to explore the parallel performance of the model using BlueCrystal4. For this part of the project, we are not interested in the behaviour of the model itself, only the time taken to complete a run, and how this varies with the number of <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>M</mi><mi>P</mi><mi>I</mi></mrow><annotation encoding=\"application/x-tex\">MPI</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">MP</span><span class=\"mord mathnormal\" style=\"margin-right:0.07847em;\">I</span></span></span></span> tasks.</p>\n<p>Since the performance is intrinsically linked to the problem size, you should generate timing data for three different values of <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>N</mi></mrow><annotation encoding=\"application/x-tex\">N</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.10903em;\">N</span></span></span></span> :</p>\n<ul>\n<li><span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>N</mi><mo>=</mo><mn>50</mn></mrow><annotation encoding=\"application/x-tex\">N = 50</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.10903em;\">N</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6444em;\"></span><span class=\"mord\">50</span></span></span></span></li>\n<li><span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>N</mi><mo>=</mo><mn>100</mn></mrow><annotation encoding=\"application/x-tex\">N = 100</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.10903em;\">N</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6444em;\"></span><span class=\"mord\">100</span></span></span></span></li>\n<li><span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>N</mi><mo>=</mo><mn>500</mn></mrow><annotation encoding=\"application/x-tex\">N = 500</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.10903em;\">N</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6444em;\"></span><span class=\"mord\">500</span></span></span></span></li>\n</ul>\n<p>You may run these calculations using <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>p</mi><mo>=</mo><mn>0.6</mn></mrow><annotation encoding=\"application/x-tex\">p = 0.6</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.625em;vertical-align:-0.1944em;\"></span><span class=\"mord mathnormal\">p</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6444em;\"></span><span class=\"mord\">0.6</span></span></span></span>, averaging over <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>M</mi><mo>=</mo><mn>50</mn></mrow><annotation encoding=\"application/x-tex\">M = 50</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.10903em;\">M</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6444em;\"></span><span class=\"mord\">50</span></span></span></span> runs.</p>\n<p>Present and comment on your results, including a discussion of how the grid size influences the performance and why, as well as the metrics you have used to assess the performance (walltime, speedup etc.). State the maximum number of <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>M</mi><mi>P</mi><mi>I</mi></mrow><annotation encoding=\"application/x-tex\">MPI</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">MP</span><span class=\"mord mathnormal\" style=\"margin-right:0.07847em;\">I</span></span></span></span> tasks you would use for each of the three grid sizes, and why. Your discussion should also include any factors from your <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>M</mi><mi>P</mi><mi>I</mi></mrow><annotation encoding=\"application/x-tex\">MPI</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">MP</span><span class=\"mord mathnormal\" style=\"margin-right:0.07847em;\">I</span></span></span></span> implementation which impact on performance, e.g. your choice of <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>M</mi><mi>P</mi><mi>I</mi></mrow><annotation encoding=\"application/x-tex\">MPI</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">MP</span><span class=\"mord mathnormal\" style=\"margin-right:0.07847em;\">I</span></span></span></span> communication scheme and data distribution.</p>\n<h2>input_grid.txt</h2>\n<div class=\"language-text line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"text\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-text\"><span class=\"line\"><span>1 0 1 0 1 1</span></span>\n<span class=\"line\"><span>0 1 1 0 0 0</span></span>\n<span class=\"line\"><span>0 0 1 1 1 0</span></span>\n<span class=\"line\"><span>1 1 0 0 0 1</span></span>\n<span class=\"line\"><span>0 0 1 1 0 1</span></span>\n<span class=\"line\"><span>1 1 0 1 0 1</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><h2>Report</h2>\n<p>This is a mini project, and so the mark scheme takes into account both technical aspects, i.e. your code, including correctness, use of C++, choice of <span v-pre=\"\" class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>M</mi><mi>P</mi><mi>I</mi></mrow><annotation encoding=\"application/x-tex\">MPI</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.13889em;\">MP</span><span class=\"mord mathnormal\" style=\"margin-right:0.07847em;\">I</span></span></span></span> implementation etc., and how you have used your code to answer the questions, i.e. your report. Make sure you read the instructions carefully and answer all questions in your report. You should also include sufficient data to backup your conclusions,as well as a discussion of any limitations, including potential future work that could be performed to address any of these limitations or extend the project.</p>\n<p>代码全在仓库中：<a href=\"https://github.com/AndersonHJB/SCIF30005-Forest-Fire-Mini-Project\" target=\"_blank\" rel=\"noopener noreferrer\">https://github.com/AndersonHJB/SCIF30005-Forest-Fire-Mini-Project</a></p>\n<h2>Try</h2>\n<h3>1. 环境调试</h3>\n\n<h2>V0.1</h2>\n\n<details class=\"hint-container details\"><summary>公众号：AI悦创【二维码】</summary>\n<figure><img src=\"/gzh.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n</details>\n<div class=\"hint-container info\">\n<p class=\"hint-container-title\">AI悦创·编程一对一</p>\n<p>AI悦创·推出辅导班啦，包括「Python 语言辅导班、C++ 辅导班、java 辅导班、算法/数据结构辅导班、少儿编程、pygame 游戏开发、Web、Linux」，全部都是一对一教学：一对一辅导 + 一对一答疑 + 布置作业 + 项目实践等。当然，还有线下线上摄影课程、Photoshop、Premiere 一对一教学、QQ、微信在线，随时响应！微信：Jiabcdefh</p>\n<p>C++ 信息奥赛题解，长期更新！长期招收一对一中小学信息奥赛集训，莆田、厦门地区有机会线下上门，其他地区线上。微信：Jiabcdefh</p>\n<p>方法一：<a href=\"http://wpa.qq.com/msgrd?v=3&amp;uin=1432803776&amp;site=qq&amp;menu=yes\" target=\"_blank\" rel=\"noopener noreferrer\">QQ</a></p>\n<p>方法二：微信：Jiabcdefh</p>\n</div>\n<figure><img src=\"/zsxq.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n",
      "image": "https://bornforthis.cn/gzh.jpg",
      "date_published": "2025-03-14T10:58:32.000Z",
      "date_modified": "2025-04-10T23:49:50.000Z",
      "authors": [
        {
          "name": "AI悦创"
        }
      ],
      "tags": []
    },
    {
      "title": "Assignment 5： Pawns on the World Stage – Pawns Board, part 1",
      "url": "https://bornforthis.cn/1v1/93-LiquidLeon/Assignment5-Pawns-on-the-World-Stage%E2%80%93Pawns-Board-part1.html",
      "id": "https://bornforthis.cn/1v1/93-LiquidLeon/Assignment5-Pawns-on-the-World-Stage%E2%80%93Pawns-Board-part1.html",
      "summary": "1. Purpose In this project, you will be building a two-player game with a graphical interface. The design and implementation of this game is left open-ended, for you to figure o...",
      "content_html": "<h2>1. Purpose</h2>\n<p>In this project, you will be building a two-player game with a graphical interface. The design and implementation of this game is left open-ended, for you to figure out, explain, and justify. There will be several components to this project, so do not assume that <em>everything</em> in your code must neatly be described as either “model”, “view”, or “controller”.</p>\n<h2>2. Pawns Board gameplay</h2>\n<p>Pawns Board is a two-player game played on a board of cells and custom cards. The game is a variation of a new card game called <a href=\"https://finalfantasy.fandom.com/wiki/Queen's_Blood\" target=\"_blank\" rel=\"noopener noreferrer\">Queen’s Blood</a>. In the game, each player has a color—red or blue—, a deck of cards, and a hand made from their respective decks.</p>\n<p>To start the game, each player must be given a deck of cards to play with and the board must be constructed.</p>\n<p>There must be enough cards in each deck to possible fill every cell on the board. Additionally, in <em>our</em> game, there can only be two copies of any card in a deck. That means there can be duplicates, but not triples of any given card. The deck for each player will be read in from a separate file.</p>\n<p>The board in our game is rectangular and its dimensions must be specified before the game starts. For <em>our</em> game, the number of rows must be positive (meaning greater than 0) and the number of columns must not only be greater than 1, but they must be odd. This allows for interesting interactions to occur in the center column of the board.</p>\n<p>Game play begins with both players being dealt an equal number of cards to their hands from their decks. The board also starts with no cards on it. However, the cells in the first and last column start with a single <em>pawn</em> in each cell. The first column’s pawns belong to the red player. The last column’s pawns belong to the blue player</p>\n<p>An initial layout of the game with 3 rows and 5 columns might look like this:</p>\n<figure><figcaption></figcaption></figure>\n<p>With a valid board created and valid decks for each player, each player is dealt their cards at random from the list. The starting size of each player’s hand is also passed in at the start of the game, but it cannot be greater than a third of the deck size. Player Red always goes first.</p>\n<p>On each turn, the current player first draws a card from their deck if there are cards remaining in their deck. If not, then no card is drawn. Then they can take one of two actions: pass or place a card. If the player chooses to pass, then their turn ends and the current player switches to the other player of the game.</p>\n<p>For the player chooses to place a card instead, they must place their card in a cell that has enough of their own pawns to cover the cost of the card.</p>\n<p>That newly placed card can then affect the board by adding pawns to other cells or converting pawns from the opponent’s ownership to the current player’s ownership. Once a card has been properly placed, the turn changes over to the other player.</p>\n<p>The game ends when both players pass their turn, one after the other. The winner is determined by calculating the score of each row.</p>\n<p>In the following subsections, we will dive into the cards, the board, scoring, and detailed information on how placing a card works in this game.</p>\n<h2>3. The cards</h2>\n<p>Each card in the game has a name, a cost, a value score, and a five by five board demonstrating the card’s influence on the board. Costs are either one, two, or three pawns. A <em>value score</em> is any positive integer and is used to determine the overall score of the game. Influence determines how the cells on the board relative to the card are affected. Consider the following card below</p>\n<figure><figcaption></figcaption></figure>\n<p>The name, cost, and value score are depicted in text on the card itself. This card, named Security, has a cost of 1 and a value score of 2. The grey grid depicts the card’s influence. The orange square represents the card itself. If a square on the influence board is cyan, like in the above picture, then it affects the cell relative to where the card is placed on the board. If a square on the influence board is grey, then nothing happens on those cells. This will come into play when we discuss placing a card on the actual board.</p>\n<p>We will be supplying cards to the game via files that contain the decks for each player. See the relevant section later in the assignment.</p>\n<p>Two cards are the same if they have the same name, cost, value score, and influence grid.</p>\n<h2>4. The board</h2>\n<p>A board is a rectangular container of cells. Cells can either contain pawns, cards, or nothing. Each cell can contain anywhere between 0 and 3 pawns on a cell. If a cell has a pawn or a card, then it is owned by one of the players of the game. Cells with cards cannot change ownership. Cell with pawns, however, can change ownership depending on the cards the current turn player places on the board. Here is another example of a larger valid board for the game in the middle of play.</p>\n<h2>5. Scoring the game</h2>\n<p>In the game, each row tallies the scores for each player. Those scores, which we will call row-scores, are determined by summing the value scores of each card owned by that player. Consider the row shown in the following image. You will see grey squares with numbers on them. Those are the row-scores as calculated by the game. The leftmost number is the red player’s row-score and the rightmost number is the blue player’s row-score.</p>\n<figure><figcaption></figcaption></figure>\n<p>We can see which player owns which card by looking at the color of the cell. We can see here that the red player has played cards with value scores of 1 and 1, giving them a row-score of 2. Similarly, we can see that the blue player has played cards with value scores of 3, 1, and 1, giving them a row-score of 5.</p>\n<p>We can calculate each players <em>total score</em> at any point during the game. To do so, we need to examine each row. For each row, we look at the row-scores for each player on that row. The player with the higher row-score adds their row-score to their total score. The player with the lower row-score gains zero points for their total score. If the row-scores are the same for both players, neither player gains points. After reviewing all the row-scores, we compare the total scores for each player. The player with the higher total score wins. If the total scores are tied, then the game ends in a tie.</p>\n<p>As an example, consider the following game.</p>\n<figure><figcaption></figcaption></figure>\n<p>Let us figure out the total score for each player.</p>\n<ul>\n<li>Player Blue wins the first row with 8 row-score over Red’s 1 row-score. Blue gets 8 points while Red gets 0 points.</li>\n<li>Player Blue wins the second row with 5 row-score over Red’s 2 row-score. Blue gets 5 points while Red gets 0 points.</li>\n<li>Player Red wins the third row with 7 row-score over Blue’s 2 row-score. Red gets 7 points while Blue gets 0 points.</li>\n</ul>\n<p>By the end of scoring, Player Red has 7 points while Player Blue has 13 points. If the game ends here (which it definitely will), Blue will be the winner.</p>\n<p>As another example, consider this different game.</p>\n<figure><figcaption></figcaption></figure>\n<p>Reminder that pawns do not affect the score in any way. With that in mind, let us start calculating the total score for the players.</p>\n<ul>\n<li>Player Blue wins the first row with 3 row-score over Red’s 2 row-score. Blue gets 3 points while Red gets 0 points.</li>\n<li>Player Red wins the second row with 3 row-score over Blue’s 1 row-score. Red gets 3 points while Blue gets 0 points.</li>\n<li>The third row ends in a tie. Red and Blue get 0 points.</li>\n</ul>\n<p>Since the final score for Red is 3 and the final score for Blue is 3, the game is tied so far! If the game ends here, then the game is a tie with no winner.</p>\n<h2>6. Placing a card</h2>\n<p>The current turn player can either choose to pass or place a card. We will focus on placing a card as that has actual effects on the board.</p>\n<h3>6.1. Legally placing a card</h3>\n<p>A player can place one of the cards in their hand onto a cell if the following conditions are satisfied</p>\n<ul>\n<li>the cell contains pawns the player owns AND</li>\n<li>the cell contains at least enough pawns to cover the cost of the card</li>\n</ul>\n<p>If both conditions are not satisfied, the player must choose another card that does satisfy the conditions. If none satisfy the conditions, the player <em>must</em> pass. If both conditions are satisfied, then the pawns on that cell are removed and replaced with the card. Naturally, the player removes the card from their hand to place it on the board.</p>\n<p>Using the starting board from the start of the assignment as an example, players can only play cards that cost one pawn on the board because for each player, all the cells they own have one pawn.</p>\n<p>Consider the following board.</p>\n<figure><figcaption></figcaption></figure>\n<p>Right in the middle of the board, the red player can place cards that cost one or two pawns, but not any that cost three pawns.</p>\n<p>In the middle of the final column, the blue player can place cards that cost one, two, or three pawns because that cell contains three pawns.</p>\n<p>Naturally, player red cannot place cards on any cell with blue pawns. Similarly, player blue cannot place cards on any cell with red pawns.</p>\n<h3>6.2. Card Influence on the Board</h3>\n<p>Once the card is placed, the card’s influence spreads on the board according to that card’s influence grid. The influence grid is always relative to the card’s position. All cells relative in position to the card’s position on the board can be affected. You can think of it like laying the influence grid over the board, centering it on the card that was just placed. For example, say we place a card in the bottom left of the board. The image below represents the possible area that can be affected.</p>\n<figure><figcaption></figcaption></figure>\n<p>Notice that not every cell might be effected. Some of the influence grid’s squares might fall off the board, so nothing happens. Players must consider whether playing a card in a particular cell will allow them to maximize that card’s influence.</p>\n<p>When you perform that overlap, all the cyan squares in the influence grid represent the cells that the card influences. The grey and orange squares do not influence any cells. As an example, consider the following pictures, one of a card called the Mandragora with its influence grid, and another showing what cells placing that card can influence after overlaying the influence grid over the grid, centered on that card.</p>\n<figure><figcaption>A card with a particular influence grid</figcaption></figure>\n<figure><figcaption> Highlighted cells on the grid that could affected after placing the card in bottom left. The orange cell is overlayed to remind the reader where the center of the influence grid is.</figcaption></figure>\n<p>Now that we have determined how to figure out which cells are influenced, we must discuss <em>how</em> they are influenced. Recall a cell either has a card, pawns, or nothing. We will walk through each scenario separately by focusing on a single cell affected by a card’s influence.</p>\n<p>For these subsections, we will use the following card to focus on only one cell on the board.</p>\n<figure><figcaption></figcaption></figure>\n<h4>6.2.1. Influence on Cards</h4>\n<p>If the cell to influence has a card, <em>nothing happens</em>.</p>\n<h4>6.2.2. Influence on Nothing</h4>\n<p>If the cell to influence has nothing on it, then the cell gains a single pawn owned by the current turn player. In the following example, we can see a before and after of this effect.</p>\n<figure><figcaption><strong>Before placing</strong>: Player Red will place the card on the cell with two red pawns</figcaption></figure>\n<figure><figcaption><strong>After placing and influence</strong>: Result of the influence of that card. Notice the cell in the middle now has one red pawn</figcaption></figure>\n<h4>6.2.3. Influence on Pawns</h4>\n<p>If the cell to influence has pawns on it, the effect changes depending on whether the current turn player owns the pawns or not.</p>\n<p>If the current turn player owns the pawns, then the number of pawns on that cell increases by one. However, there can only be a maximum of 3 pawns on a single cell.</p>\n<figure><figcaption><strong>Before placing</strong>:Player Red will place the card on the cell with two red pawns</figcaption></figure>\n<figure><figcaption><strong>After placing and influence</strong>:Result of the influence of that card. Notice the cell in the middle now has two red pawns instead of one.</figcaption></figure>\n<p>If the current turn player does NOT own the pawns, then the number of pawns on that cell does <em>not</em> increase. Instead, the current turn player takes ownership of those pawns. You can see this play out in the following images.</p>\n<figure><figcaption><strong>Before placing</strong>：Player Red will place the card on the cell with two red pawns</figcaption></figure>\n<figure><figcaption><strong>After placing and influence</strong>：Result of the influence of that card. Notice the cell in the middle now has two red pawn instead of the two blue pawns</figcaption></figure>\n<p>This allows players to gain the upper hand by claiming pawns the opponent was saving for higher cost cards.</p>\n<h4>6.2.4. Putting it all together</h4>\n<p>Putting together these rules, we can now visualize the result of playing the Mandragora in the bottom left. The images below show the card on the left and the resulting board for placing the card on the bottom left of a standard starting board.</p>\n<figure><figcaption><strong>Card to place</strong>:A card with a particular influence grid</figcaption></figure>\n<figure><figcaption><strong>Board after placing card</strong>:Adding the card changed the cell above the card and the two to the right of the card</figcaption></figure>\n<p>Notice number of pawns above the card increased to two pawns. Furthermore, the two cells to the right of the card gained a red pawn.</p>\n<p>For another example not in a corner, consider a play where the red player is somehow able to place a different card in the middle of the board.</p>\n<figure><figcaption><strong>Card to place</strong>:A card with a particular influence grid</figcaption></figure>\n<figure><figcaption><strong>Board after placing card</strong>:Adding the card changed the cells adjacent in the cardinal directions</figcaption></figure>\n<p>Notice that since every cyan square on the influence grid actually overlayed with a cell on the board, they all took effect.</p>\n<p>Finally, consider a play where the red player instead placed the same card in the top left instead.</p>\n<figure><figcaption><strong>Card to place</strong>:A card with a particular influence grid</figcaption></figure>\n<figure><figcaption><strong>Board after placing card</strong>: Only the cells to the right and below the card are changed. Influence squares that fall off the grid have no effect on the board</figcaption></figure>\n<p>Notice that some of the cyan squares actually don’t overlap with a cell on the board, so they exert no influence.</p>\n<h4>6.2.5. Influence and the Blue Player</h4>\n<p>Keep in mind the blue player is on the right side of the board. To allow the red and blue player to use the same cards, when the blue player looks at what their card can influence, the influence grid is <em>mirrored</em> across the columns (i.e. the y-axis). You can see this in the example below with the Mandragora card.</p>\n<figure><figcaption><strong>Card to Red’s view</strong>:A card with a particular influence grid from red's point of view</figcaption></figure>\n<figure><figcaption><strong>Card from Blue’s view</strong>:The same card from blue's point of view. Notice the rows don't flip, but the columns do</figcaption></figure>\n<p>Therefore, influence is also mirrored when the card is placed on the board. You can see this in the images below. When red plays their Mandragora in the middle, the influence spreads to the right and above. When Blue plays their Mandragora in the bottom right, the influence still spreads above, but it spreads to the <em>left</em> instead.</p>\n<figure><figcaption><strong>Board after Red plays</strong>:Red's Mandragora influences to the right</figcaption></figure>\n<figure><figcaption><strong>Board after Blue plays</strong>:Blue's Mandragora influences to the left</figcaption></figure>\n<h2>7. Architectural choices</h2>\n<p>A multiplayer game involves several interacting components: you have multiple <em>players</em>, that each <em>interact</em> with a <em>visualization</em> of the <em>grid</em>, along with a <em>rules-keeper</em> to ensure the game is played legally.</p>\n<p>In our setting, the cards, board, and the rules-keeper (objects or methods that make sure the rules of the game are always followed) comprise our model: together, they are what distinguish one instance of the game from another.</p>\n<p>There are multiple ways to view the game; we will discuss two below.</p>\n<p>Depending on how the game is viewed, we might want to design different controllers for the game.</p>\n<p>The game also has some further customization not mentioned in the overview, but could come up in future assignments including the extra credit. For instance, influence only adds pawns or takes control of existing pawns. However, the game Pawns Board is based on has different <em>types</em> of influence, like increasing or decreasing the value scores of cards.</p>\n<p>And then there are the user-players (an object that the users actually play the game through), which are not part of the model, view, or controller. User-players make decisions about what move they want to make (not be confused with the player entities of Red and Blue in the model), so they “have a different interface” than the other components discussed so far.</p>\n<h3>7.1. Modeling the game</h3>\n<p>You will need to represent the cards, the players, the board, and all of their contents. You likely will have to figure out how to represent the coordinate system of the grid, so as to describe the locations of all the cells on the board.</p>\n<p>You will need to figure out how to let users make moves. Your implementation will need to (among other tasks) enforce the rules of the game, to make sure that players take turns, that moves are legal, that influence is applied on the board, and that the winner of the game can be determined.</p>\n<p><strong>About variant rules:</strong> While variant influence effects are briefly mentioned, they are <strong>not to be implemented</strong> as we have not discussed what they are. We mention them now in case that has an effect on how you design the model.</p>\n<p><strong>Hint:</strong> your primary model interface may not be all that complicated. As with all our design tasks so far, consider all the nouns you notice in this game’s description, and all the verbs describing their interactions, observations, or mutations, and those become your interfaces and methods.</p>\n<h3>7.2. Visualizing the game</h3>\n<p>You are <em>not required in this assignment</em> to create a GUI view of your game. Instead, you will start with a simpler textual view, similar to the previous project, to make it easier to see the interim progress of your game. We recommend a straightforward rendering of the board itself and the row-scores, using <code>_</code> for empty cells , an integer of 1, 2, or 3 for the number of pawns on the board, <code>R</code> for a card owned by the red player , and <code>B</code> for a card owned by the blue player. For example, see the graphical and textual views below for a representation of a game in play where player Blue is the current player.</p>\n<figure><figcaption><strong>Visual view</strong></figcaption></figure>\n<div class=\"language- line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-\"><span class=\"line\"><span>Textual view</span></span>\n<span class=\"line\"><span>2 RR__3 0</span></span>\n<span class=\"line\"><span>0 2__1B 1</span></span>\n<span class=\"line\"><span>0 11_1B 3</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><h4>7.3<code> </code>Controlling the game</h4>\n<p>You do not need to implement any sort of controller in this assignment, though you are encouraged to think about how to do so — we will build a controller in future assignments.</p>\n<h3>8<code> </code>Players – human or machine?</h3>\n<p>In a future assignment, we <em>might</em> ask you to implement a simple AI user-player for this game. This will enable several possible scenarios, including solitaire play (person vs computer) and fully-automated play (which may be useful for testing). You do not have to implement a computer user-player right now, but you should design your model so that different user-player implementations could exist for human or machines to play your game. You should attempt to design a user-player interface that allows this to happen.</p>\n<p>In a design document (in a separate text file), explain how you envision instantiating user-players and your model, so that you could play a few moves of the game. This might be one part of your README (see below), but probably should be a separate file.</p>\n<p>We will give additional guidance in future assignments over how we suggest you implement user-players; the goal in this assignment is for you to think through the design possibilities and explain what you think might be an appropriate design.</p>\n<h2>9. Reading Deck Configuration Files</h2>\n<p>Configuration files are a great way of setting up game states without having to manually create them in a test file. We will be using configuration files to instantiate the grid and cards for our game. This files seemingly play a special role, but do belong in one of our 3 regular components (model, view, controller). You must decide where they go based on the purposes of each component, what the classes that read these files actually do, and which component best represents that purpose.</p>\n<p>For this section, it may be helpful to read up on the <code>FileReader</code> and <code>Scanner</code> documentation from Oracle. The goal is to help you practice some software archaeology and help you figure out how you learn to use new classes.</p>\n<h3>9.1. About files and file paths</h3>\n<p>Your program needs to work on any computer, which means on any operating system. However, different operating systems describe paths to files in different ways. For instance, Windows uses</p>\n<div class=\"language- line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-\"><span class=\"line\"><span>\"\\\"</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div></div></div><p>to separate folders while Macs and Linux use</p>\n<div class=\"language- line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-\"><span class=\"line\"><span>\"/\"</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div></div></div><p>. Furthermore, when graded, your projects won’t be opened on your computer, but on someone else’s. So how do we decide on a location for the files you will be reading so your program works regardless of the computer and how do you write that location in code when you need to read in a file?</p>\n<p>For the location, IntelliJ actually has a solution. Any code run in IntelliJ automatically assumes that file paths start from the <em>project folder</em>. Consider the following possible project setup</p>\n<div class=\"language-bash line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"bash\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-bash\"><span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">+-</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> src/</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">| </span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">+-</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> cs3500/</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">| | </span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">+-</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> pawnsboard/</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">| | | </span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">+-</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> ...</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> (more </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">stuff</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">+-</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> test/</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">| </span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">+-</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> cs3500/</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">| | </span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">+-</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> pawnsboard/</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">| | | </span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">+-</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> ...</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> (more </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">test</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> stuff</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">+-</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> board.config</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>I can read the board.config file in my code by giving the appropriate object the path as a String as follows</p>\n<div class=\"language-bash line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"bash\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-bash\"><span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">String</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> path</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> =</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> \"deck.config\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">;</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">File</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> config</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> =</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> new</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> File</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">path</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">);</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>However, we cannot leave random files sitting in the project folder because that clutters the project itself. So instead, we place all files that support the program like config files in a folder called docs like below.</p>\n<div class=\"language-bash line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"bash\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-bash\"><span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">+-</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> docs/</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">| </span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">+-</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> deck.config</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">+-</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> src/</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">| </span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">+-</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> cs3500/</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">| | </span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">+-</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> pawnsboard/</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">| | | </span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">+-</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> ...</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> (more </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">stuff</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">+-</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> test/</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">| </span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">+-</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> cs3500/</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">| | </span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">+-</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> pawnsboard/</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">| | | </span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">+-</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> ...</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> (more </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">test</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> stuff</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>That brings us to the other issue: how to write paths in Java that are independent of any operating system. Java’s file class actually has something for us! There is a static constant called <code>separator</code> which changes depending on the operating system. Let’s say we wanted to create a <code>File</code> object for <code>deck.config</code>. We can write the following code</p>\n<div class=\"language-bash line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"bash\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-bash\"><span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">String</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> path</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> =</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> \"docs\"</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> +</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> File.separator</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> +</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> \"deck.config\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">;</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">File</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> config</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> =</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> new</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> File</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">path</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">);</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>Use this knowledge to write tests and code that will read files on any computer.</p>\n<h3>9.2 Deck Configuration File</h3>\n<p>If you get a file that does not correspond to the format listed below, the behavior is unspecified. This means you can let <strong>anything</strong> happen as a result. If you do choose a specific behavior, make sure to document it in the code.</p>\n<p>This file is a list of cards in the following format</p>\n<div class=\"language- line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-\"><span class=\"line\"><span>CARD_NAME COST VALUE</span></span>\n<span class=\"line\"><span>ROW_0</span></span>\n<span class=\"line\"><span>ROW_1</span></span>\n<span class=\"line\"><span>ROW_2</span></span>\n<span class=\"line\"><span>ROW_3</span></span>\n<span class=\"line\"><span>ROW_4</span></span>\n<span class=\"line\"><span>CARD_NAME COST VALUE</span></span>\n<span class=\"line\"><span>ROW_0</span></span>\n<span class=\"line\"><span>ROW_1</span></span>\n<span class=\"line\"><span>ROW_2</span></span>\n<span class=\"line\"><span>ROW_3</span></span>\n<span class=\"line\"><span>ROW_4</span></span>\n<span class=\"line\"><span>CARD_NAME COST VALUE</span></span>\n<span class=\"line\"><span>...</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>Each card consists of one line with its name (with no spaces), an integer between 1 and 3 inclusive for the cost, and a positive (greater than 0) integer for the value score of the card. Then there are 5 lines, each made of 5 characters, representing the influence grid of the card. There are 3 possible characters that can appear in the influence grid</p>\n<ul>\n<li>\"X\": This indicates the card has no influence on that cell.</li>\n<li>\"I\": This indicates the card does have influence on that cell.</li>\n<li>\"C\": This indicates the card’s position. This must only exist in the middle of the grid on ROW_2’s third character. It cannot appear anywhere else</li>\n</ul>\n<p>A valid card file only has lines for cards as formatted as specified above.</p>\n<p>What follows is an example of a deck configuration file with two cards.</p>\n<div class=\"language- line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-\"><span class=\"line\"><span>Security 1 2</span></span>\n<span class=\"line\"><span>XXXXX</span></span>\n<span class=\"line\"><span>XXIXX</span></span>\n<span class=\"line\"><span>XICIX</span></span>\n<span class=\"line\"><span>XXIXX</span></span>\n<span class=\"line\"><span>XXXXX</span></span>\n<span class=\"line\"><span>Bee 1 1</span></span>\n<span class=\"line\"><span>XXIXX</span></span>\n<span class=\"line\"><span>XXXXX</span></span>\n<span class=\"line\"><span>XXCXX</span></span>\n<span class=\"line\"><span>XXXXX</span></span>\n<span class=\"line\"><span>XXIXX</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><h2>10. Showing functionality</h2>\n<p>Since you are creating the interfaces yourselves, we cannot possibly write JUnit tests to check your functionality. However, the functionality of your model is integral to your success in this project and for your grade.</p>\n<p>To show that functionality, you must add a class called <code>PawnsBoard</code> that only has a <code>main</code> method. Just like with <code>PokerPolygonsGame</code>, this is a class that cannot be in the model, view, or controller packages, but instead exists in your project’s package at the same level as the model, view, or controller packages. In this main method, you must do the following:</p>\n<ul>\n<li>Read in a deck configuration file of your own creation. This file must contain enough cards to play on a board made of 3 rows and 5 columns.</li>\n<li>Initialize a model and start the game. The board must be 3 rows by 5 columns. The two players must use the same deck read in from that configuration file you made and have a starting hand size of 5. The decks <em>must not be shuffled</em> at any point.</li>\n<li>Play the game until no cards can be placed on the board. You are free to have players pass as needed, but both players must place cards on the board. After each action a player takes (placing a card or passing), the textual view must be printed to the console to show how the game is progressing.</li>\n</ul>\n<p>We will use this main method to check the functionality of your model.</p>\n<h2>11. What to do</h2>\n<ol>\n<li>Design a model to represent the game. This may consist of one or more interfaces, abstract classes, concrete classes, enums, etc. Consider carefully what operations it should support, what invariants it assumes, etc. Your model implementation should be general enough for multiple board sizes.</li>\n<li>Design classes to read in the deck configurations. This many consist of one or more interfaces, abstract class, concrete classes, etc.</li>\n<li><strong>You are required to identify and document at least one class invariant for the implementation of your main model class, and ensure that your implementation enforces it.</strong></li>\n<li>Document your model well. Be sure to document clearly what each type and method does, what purpose it serves and why it belongs in the model.</li>\n<li>Write a README file (see below).</li>\n<li>Implement your model. If some method of your model cannot be implemented because it requires details we have not yet provided, you may leave the method body blank for now — but leave a comment inside the method body explaining why it’s empty and what details you’re waiting for. If your implementation makes additional assumptions about invariants (beyond those asserted by the interface), document them.</li>\n<li>Create a deck configuration file with enough cards to play a game on a 3 row and 5 column board.</li>\n<li>Implement the main method in the <code>PawnsBoard</code> class as described previously.</li>\n<li>Test your model thoroughly. You are encouraged to do the following : an Examples class to give readers a quick understanding of your model (like you did in HW1), a ModelInterface-testing class that lives <em>outside</em> your model package, to ensure you’re testing the publicly visible signatures of your model, and an Implementation-testing class that lives <em>inside</em> your model package, that can test package-visible functionality that isn’t part of your model interface.</li>\n<li>Implement the textual rendering of your model described above, so we can visualize your data. Leave enough comments in your code that TAs know how to use your code to produce a visualization of a model. Test your textual rendering.</li>\n<li>Design a user-player interface, such that human or AI players could interact with the model, and explain your design. You do not have to implement this interface for this assignment. You don’t even necessarily need to define this interface as a Java <code>interface</code>, but merely as a clearly-written English description in a text file.</li>\n</ol>\n<p>We will not be autograding this assignment, but you should emulate the textual view output above as precisely as possible, as we will likely be looking at it on future assignments.</p>\n<h2>12. How to write a good <code>README</code> file</h2>\n<p>A good README file needs to quickly explain to the reader what the codebase’s overall purpose is, what its design is, and where to find relevant functionality within the codebase. (Just because your code organization is obvious to <em>you</em> does not mean it’s obvious to a newcomer to your code!)</p>\n<p>A README file does not have to be <em>long</em> in order to be <em>effective</em>, but it does need to be better than merely formulaic.</p>\n<p>README files need to be in a predictable place in your codebase, or else readers won’t easily be able to find them. Typically, place them in the topmost directory of your project, or in a toplevel <code>docs/</code> directory.</p>\n<p>Consider the following outline as a good starting point for your READMEs, and elaborate from here. This is not a verbatim requirement, but rather a launch-point for you to explain your code.</p>\n<ul>\n<li>\n<p><strong>Overview:</strong> What problem is this codebase trying to solve? What high-level assumptions are made in the codebase, either about the background knowledge needed, about what forms of extensibility are envisioned or are out of scope, or about prerequisites for using this code?</p>\n</li>\n<li>\n<p><strong>Quick start:</strong> give a short snippet of code (rather like a simple JUnit test) showing how a user might get started using this codebase.</p>\n</li>\n<li>\n<p><strong>Key components:</strong> Explain the highest-level components in your system, and what they do. It is trite and useless to merely say “The model represents the data in my system. The view represents the rendering of my system. ...” This is a waste of your time and the reader’s time. Describe which components “drive” the control-flow of your system, and which ones “are driven”.</p>\n<blockquote>\n<p><strong>Key subcomponents:</strong> Within each component, give an overview of the main nouns in your system, and why they exist and what they are used for.</p>\n</blockquote>\n</li>\n<li>\n<p><strong>Source organization:</strong> Either explain for each component where to find it in your codebase, or explain for each directory in your codebase what components it provides. Either way, supply the reader with a “map” to your codebase, so they can navigate around.</p>\n</li>\n</ul>\n<p>Notice that almost everything in the README file corresponds strongly with the purpose statements of <em>classes and interfaces</em> in your code, but probably does not get into the detailed purpose statements of <em>methods</em> in your code, invariants in your data definitions, etc. Those implementation details belong in Javadoc on the relevant code files. You <em>may</em> choose to mention some key methods as entry points into your code (perhaps in the Quick start section’s examples), but you should not overburden the README with such lower-level detail.</p>\n<h2>13. What to submit</h2>\n<p>Submit any files created in this assignment, along with your design document. Make certain you include your README file, which should give the graders an overview of what the purposes are for every class, interface, etc. that you include in your model, so that they can quickly get a high-level overview of your code. It does <em>not</em> replace the need for proper Javadoc!</p>\n<h2>14. Grading standards</h2>\n<p>For this assignment, you will be graded on</p>\n<ul>\n<li>the design of your model interface(s), in terms of clarity, flexibility, and how plausibly it will support needed functionality;</li>\n<li>the appropriateness of your representation choices for the data, and the adequacy of any documented class invariants (please comment on why you chose the representation you did in the code);</li>\n<li>the choice of component for your classes that read files</li>\n<li>the deck configuration file to play and test the game</li>\n<li>the forward thinking in your design, in terms of its flexibility, use of abstraction, etc.</li>\n<li>the correctness and style of your implementation, and</li>\n<li>the comprehensiveness and correctness of your test coverage.</li>\n</ul>\n<h2>15. Submission</h2>\n<p>Please submit your homework to <a href=\"https://handins.ccs.neu.edu/\" target=\"_blank\" rel=\"noopener noreferrer\">https://handins.ccs.neu.edu/</a> by the above deadline. Then be sure to complete your self evaluation by its due date.</p>\n<details class=\"hint-container details\"><summary>公众号：AI悦创【二维码】</summary>\n<figure><img src=\"/gzh.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n</details>\n<div class=\"hint-container info\">\n<p class=\"hint-container-title\">AI悦创·编程一对一</p>\n<p>AI悦创·推出辅导班啦，包括「Python 语言辅导班、C++ 辅导班、java 辅导班、算法/数据结构辅导班、少儿编程、pygame 游戏开发、Web、Linux」，全部都是一对一教学：一对一辅导 + 一对一答疑 + 布置作业 + 项目实践等。当然，还有线下线上摄影课程、Photoshop、Premiere 一对一教学、QQ、微信在线，随时响应！微信：Jiabcdefh</p>\n<p>C++ 信息奥赛题解，长期更新！长期招收一对一中小学信息奥赛集训，莆田、厦门地区有机会线下上门，其他地区线上。微信：Jiabcdefh</p>\n<p>方法一：<a href=\"http://wpa.qq.com/msgrd?v=3&amp;uin=1432803776&amp;site=qq&amp;menu=yes\" target=\"_blank\" rel=\"noopener noreferrer\">QQ</a></p>\n<p>方法二：微信：Jiabcdefh</p>\n</div>\n<figure><img src=\"/zsxq.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n",
      "date_published": "2025-03-12T07:47:23.000Z",
      "date_modified": "2025-04-10T23:49:50.000Z",
      "authors": [
        {
          "name": "AI悦创"
        }
      ],
      "tags": []
    },
    {
      "title": "Lecture 14 The Observer Pattern",
      "url": "https://bornforthis.cn/1v1/93-LiquidLeon/Lecture14-The-Observer-Pattern.html",
      "id": "https://bornforthis.cn/1v1/93-LiquidLeon/Lecture14-The-Observer-Pattern.html",
      "summary": "In the last lecture we introduced the idea of a “Features interface” that described a way to isolate the controller from the low-level Swing components inside the view, and simu...",
      "content_html": "<p>In the <a href=\"https://course.ccs.neu.edu/cs3500/lec_gui_basics_notes.html\" target=\"_blank\" rel=\"noopener noreferrer\">last lecture</a> we introduced the idea of a “<code>Features</code> interface” that described a way to</p>\n<ul>\n<li>isolate the controller from the low-level Swing components inside the view, and</li>\n<li>simultaneously, allow the view to have multiple UI components trigger the same logical callback on the controller.</li>\n</ul>\n<p>We called these “high-level events”, since they were application-specific events as opposed to “low-level” general-purpose events. This idea of defining our own application-specific events is a very common one, and generalizes the <code>Features</code> interface idea into something known as the Observer Patern.</p>\n<h2>1. Motivating example: buying concert tickets</h2>\n<p>Suppose you are interested in getting tickets for a popular upcoming concert. You know that tickets will sell out quickly, and you don’t want to miss your opportunity. So you signup for the mailing list for the ticket service, and wait for an email telling you that tickets are now available. Of course, mailing lists being what they are, you’ll probably get a bunch of unwanted messages telling you about uninteresting concerts as well, so you need to read the emails to check which concert has just gone on sale.</p>\n<p>Let’s try to represent this in code.</p>\n<h2>2. Setting the stage</h2>\n<p>Let’s assume we have a <code>class TicketSeller</code> that handles ticket sales for lots of concerts, and a <code>class Person</code> to represent you or other people interested in concerts. (To keep things simple, we’ll just assume each concert has a unique name that we’ll represent as a <code>String</code>; in practice, the data here might be more interesting, but it’ll obscure the pattern we’re looking for here.)</p>\n<div class=\"language-java line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"java\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-java\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">class</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> TicketSeller</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">  Ticket</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> purchaseTicketFor</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">String</span><span style=\"--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\"> concertName</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> { ... </span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">sell</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> a ticket ... }</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">}</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">class</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> Person</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">  void</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> tryToBuyTicketFor</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">String</span><span style=\"--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\"> concertName</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    ???</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">  }</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">}</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>If a concert is sold out or not even available yet, then <code>TicketSeller#purchaseTicketFor</code> will fail, so our goal is to call that method as soon as possible, but no sooner. So in <code>Person#tryToBuyTicketsFor</code>, we can’t immediately call that method. Instead, we need to “sign up for the mailing list” somehow.</p>\n<p>To do that, let’s define an interface</p>\n<div class=\"language-java line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"java\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-java\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">interface</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> TicketNotificationSubscriber</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">  void</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> ticketsAvailableFor</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">String</span><span style=\"--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\"> concertName</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">);</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">}</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>This is the analogue of the <code>Features</code> interface from last lecture. With <code>Features</code>, our controller was interested in being called back, so it registered with the view, and the view called its methods when appropriate. Here, our <code>TicketSeller</code> will call the <code>ticketsAvailableFor</code> method on any objects that have signed up for such notifications, and our <code>Person</code> objects will implement that interface and sign up for the notifications.</p>\n<div class=\"language-java line-numbers-mode has-collapsed-lines collapsed\" data-highlighter=\"shiki\" data-ext=\"java\" style=\"--vp-collapsed-lines:15;--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-java\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">class</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> Person</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> implements</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> TicketNotificationSubscriber</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">  void</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> tryToBuyTicketsFor</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">String</span><span style=\"--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\"> concertName</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">TicketSeller</span><span style=\"--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\"> seller</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">    seller</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">signUpForNotifications</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">this</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">);</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">  }</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">  public</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> void</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> ticketsAvailableFor</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">String</span><span style=\"--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\"> concertName</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">    // the seller will call us back when concerts become available</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">  }</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">}</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">class</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> TicketSeller</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">  void</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> signUpforNotifications</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">TicketNotificationSubscriber</span><span style=\"--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\"> obs</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    ???</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">  }</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">}</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div><div class=\"collapsed-lines\"></div></div><p>Now we just have to connect the last few pieces. The <code>TicketSeller</code> will need to maintain a “mailing list” of everyone who’s signed up to be notified. And whenever a new concert is announced, it should broadcast that announcement to everyone who’s signed up:</p>\n<div class=\"language-java line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"java\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-java\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">class</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> TicketSeller</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">  List</span><span style=\"--shiki-light:#E45649;--shiki-dark:#ABB2BF\">&lt;</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">TicketNotificationSubscriber</span><span style=\"--shiki-light:#E45649;--shiki-dark:#ABB2BF\">&gt;</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\"> subscriers </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> new</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> ArrayList</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">&lt;&gt;</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">()</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">;</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">  void</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> signUpForNotifications</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">TicketNotificationSubscriber</span><span style=\"--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\"> sub</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">    this</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">subscribers</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">add</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(sub);</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">  }</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">  void</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> announceNewConcert</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">String</span><span style=\"--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\"> name</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> (</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">TicketNotificationSubscriber</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\"> sub</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> :</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\"> this</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">subscribers</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">) {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">      sub</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">ticketsAvailableFor</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(name);</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    }</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">  }</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">}</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>Finally, we can complete the <code>Person</code> implementation. Notice that they’ll get notified for <em>all</em> concerts, so they need to keep track of the one concert they’re interested in:</p>\n<div class=\"language-java line-numbers-mode has-collapsed-lines collapsed\" data-highlighter=\"shiki\" data-ext=\"java\" style=\"--vp-collapsed-lines:15;--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-java\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">class</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> Person</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> implements</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> TicketNotificationSubscriber</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">  String</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\"> interestedInConcert</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">;</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">  TicketSeller</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\"> seller</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">;</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">  void</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> tryToBuyTicketsFor</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">String</span><span style=\"--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\"> concertName</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">TicketSeller</span><span style=\"--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\"> seller</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">    this</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">interestedInConcert</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> =</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> concertName;</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">    this</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">seller</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> =</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> seller;</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">    seller</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">signUpForNotifications</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">this</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">);</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">  }</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">  public</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> void</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> ticketsAvailableFor</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">String</span><span style=\"--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\"> concertName</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> (</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">concertName</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">equals</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">this</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">interestedInConcert</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)) {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">      // Hooray, tickets are available for the concert we're interested in</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">      seller</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">purchaseTicketFor</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(concertName);</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    }</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">  }</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">}</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div><div class=\"collapsed-lines\"></div></div><p>Notice the similarities to <code>ActionListener</code>s: the <code>Person</code> gets called back with the name of what event has occurred, and can choose what to do about it based on that information. Notice also the differences: the callback here is talking about <em>concerts</em>, which is clearly a very application-specific sort of event.</p>\n<h2>3. Enhancements and subtleties</h2>\n<p>The names <code>TicketSeller</code>, <code>signUpForNotifications</code>, <code>TicketNotificationSubscriber</code> and <code>ticketsAvailableFor</code> are whimsical and application-specific, but they illustrate an important point: this pattern applies to high-level events just as well as to low-level events. Regardless of the name, the Observer Pattern describes this common scenario, of multiple entities that are interested in messages being sent by some common source. There can be many observers for a single message-sender, and a single observer might be interested in many message-senders.</p>\n<p>The general names for this pattern look as follows:</p>\n<div class=\"language-java line-numbers-mode has-collapsed-lines collapsed\" data-highlighter=\"shiki\" data-ext=\"java\" style=\"--vp-collapsed-lines:15;--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-java\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">class</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> Subject</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">  List</span><span style=\"--shiki-light:#E45649;--shiki-dark:#ABB2BF\">&lt;</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">Observer</span><span style=\"--shiki-light:#E45649;--shiki-dark:#ABB2BF\">&gt;</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\"> observers</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">;</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">  void</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> addObserver</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">Observer</span><span style=\"--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\"> obs</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> { </span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">observers</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">add</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(obs); }</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">  // This method gets called by other methods in the Subject class as needed</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">  private</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> void</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> notifyAllSomethingHappened</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> (</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">Observer</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\"> obs</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> :</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\"> this</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">observers</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">) {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">      obs</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">somethingHappened</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">();</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    }</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">  }</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">}</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">interface</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> Observer</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">  void</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> somethingHappend</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">();</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">}</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">class</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> SomeObserver</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> implements</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> Observer</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">  void</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> somethingHappened</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> { ... }</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">}</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">// somewhere in the code</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">someSubject</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">addObserver</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(someObserver);</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div><div class=\"collapsed-lines\"></div></div><ul>\n<li>We might want to enhance the <code>Subject</code> class to allow <em>unsubscribing</em> from notifications, via a <code>removeObserver</code> method.</li>\n<li>We might want to send more information along in the <code>somethingHappened</code> method, including which <code>Subject</code> sent the notification, or what the notification is about.</li>\n<li>Currently, each <code>Person</code> gets notified for <em>all</em> concerts, leading to a lot of spammy messages. We might want to enhance the <code>addObserver</code> method to specify what notifications we’re interested in, and allow the <code>TicketSeller</code> to only send the notifications we care about. In general, we might want the <code>Subject</code> class to maintain a mapping from specific topics to the observers interested in just those topics, and only <code>somethingHappened()</code> the observers that care about that topic. This leads to a more complex <code>Subject</code> implementation, but a <em>possibly</em> more-efficient system overall.</li>\n<li>Our current <code>Observer</code> interface has only a single method in it. But as we saw with <code>Features</code>, there could easily be multiple application-specific notifications we might want to send.</li>\n<li>Thinking about the <code>TicketSeller</code> again, if it sends out a notification for each individual concert, then the amount of spam depends on how many concerts there are. We might instead want to group together several updates into a single <em>batch notification</em> (for example, configuring Piazza to notify you for each individual post, vs notifying you once every few hours with a batch of posts at once).</li>\n</ul>\n<p>The Observer pattern is a general-purpose event handling mechanism, and hopefully it’s clear that its utility generalizes beyond just handling UI events.</p>\n<h2>1. 观察者模式要解决什么问题？</h2>\n<p>在很多应用场景中，我们都有这样一种需求：<strong>当某个对象（通常称为“主题”Subject）发生变化时，希望能够及时通知其他对这个变化感兴趣的对象（通常称为“观察者”Observer）</strong></p>\n<p>例如：文中“演唱会订票”例子里，<code>TicketSeller</code> 就好比是“主题”，有新演唱会门票开始发售（“事件”）时，需要通知所有“订阅”它的人（“观察者”），让他们赶紧来买票。</p>\n<p>这个模式也常出现在 GUI 开发中，Swing 或其他图形库中都有类似的事件监听器概念：一个按钮被点击时，就通知所有监听这个按钮点击事件的观察者。</p>\n<p><strong>关键点：</strong></p>\n<ol>\n<li>主题（Subject）维护一个观察者列表。</li>\n<li>当主题发生变化时，就循环通知所有已注册（订阅）的观察者。</li>\n<li>观察者可以有不同的逻辑，根据事件信息做出不同反应。</li>\n</ol>\n<h2>2. 先看一个简化的“演唱会订票”示例思路</h2>\n<ol>\n<li><strong>TicketNotificationSubscriber</strong>: 这是观察者接口(Observer)，表示“任何想订阅新演唱会通知”的人（或对象），必须实现此接口，并实现一个回调方法 <code>ticketsAvailableFor(String concertName)</code>，用来接收“通知”。</li>\n<li><strong>TicketSeller</strong>: 这是主题(Subject)，\n<ul>\n<li>会维护一个“已订阅”列表（List），里面放的都是实现了 <code>TicketNotificationSubscriber</code> 接口的对象。</li>\n<li>当它宣布有新的演唱会（<code>announceNewConcert(String name)</code>）时，就会把这个消息广播给所有订阅者。</li>\n</ul>\n</li>\n<li><strong>Person</strong>: 具体的观察者（Observer）的实现类之一，\n<ul>\n<li>它想要订阅某个演唱会的门票通知，就调用 <code>seller.signUpForNotifications(this)</code> 把自己注册到 <code>TicketSeller</code>。</li>\n<li>当收到通知 <code>ticketsAvailableFor(String concertName)</code>，就判断是不是自己关心的演唱会，如果是，就执行购买票的逻辑。</li>\n</ul>\n</li>\n</ol>\n<p>和我们常见的 GUI 监听器类似，但事件名是业务相关的“门票可用事件”，而非鼠标点击、键盘输入等底层事件，因此它也被称为“高层事件”或“应用特定事件”。</p>\n<h2>3. 一步步带你实现</h2>\n<p>下面我们写一个完整的示例，放在一个文件里演示。可以把它保存为 <code>ObserverPatternDemo.java</code> 并编译运行（当然也可以拆分成多个文件，这里为了演示方便，放在一起）。</p>\n\n<h2>4. 扩展与思考</h2>\n<p>上面是最简洁的一种实现方式。在实际项目中，根据需求不同，还可能会有一些变体或增强：</p>\n<ol>\n<li><strong>增加取消订阅（unregister / removeObserver）</strong>：有时观察者不再对某些事件感兴趣，需要在主题中把自己移除。</li>\n<li><strong>增加多种通知类型</strong>：比如不仅仅是“演唱会开始发售”这一种事件，可能还有“演唱会售罄”之类的事件，此时观察者接口里可以有多个方法。</li>\n<li><strong>过滤特定主题</strong>：如讲义中提到的，如果观众只想听一个歌手或者只想了解某些演出，就可以让 <code>TicketSeller</code> 更智能地发送更“精准”的通知。</li>\n<li><strong>批量通知</strong>：有时不想一有消息就通知，可以几个小时发送一次“综合”消息，比如常见的邮件订阅选项“立即通知”VS“每日/每周汇总”。</li>\n</ol>\n<p>无论如何，核心点不变：<strong>主题维护一组观察者对象，发生某件事时调用观察者接口的方法进行回调，从而让观察者对该事件做出相应处理。</strong> 这就是观察者模式(Observer Pattern)。</p>\n<h2>5. 小结</h2>\n<ul>\n<li><strong>问题场景</strong>：当某个对象发生“某种变化”时，需要通知其他感兴趣的对象。</li>\n<li>核心结构：\n<ul>\n<li>主题(Subject)保存一个观察者(Observer)列表；</li>\n<li>主题发生事件时，依次调用<code>observer.回调方法()</code>去通知。</li>\n</ul>\n</li>\n<li><strong>适用范围非常广</strong>：图形界面的按钮点击、网络状态变更的通知、订阅-发布系统等都可归为观察者模式。</li>\n</ul>\n<p>希望这个例子和逐步实现的过程能帮你真正理解并掌握“观察者模式”。如果你把上面的代码都放在一个文件里（或者按照各个类拆成多个文件），编译运行，就可以亲眼看到程序如何在“广播事件”时通知所有观察者了。</p>\n<details class=\"hint-container details\"><summary>公众号：AI悦创【二维码】</summary>\n<figure><img src=\"/gzh.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n</details>\n<div class=\"hint-container info\">\n<p class=\"hint-container-title\">AI悦创·编程一对一</p>\n<p>AI悦创·推出辅导班啦，包括「Python 语言辅导班、C++ 辅导班、java 辅导班、算法/数据结构辅导班、少儿编程、pygame 游戏开发、Web、Linux」，全部都是一对一教学：一对一辅导 + 一对一答疑 + 布置作业 + 项目实践等。当然，还有线下线上摄影课程、Photoshop、Premiere 一对一教学、QQ、微信在线，随时响应！微信：Jiabcdefh</p>\n<p>C++ 信息奥赛题解，长期更新！长期招收一对一中小学信息奥赛集训，莆田、厦门地区有机会线下上门，其他地区线上。微信：Jiabcdefh</p>\n<p>方法一：<a href=\"http://wpa.qq.com/msgrd?v=3&amp;uin=1432803776&amp;site=qq&amp;menu=yes\" target=\"_blank\" rel=\"noopener noreferrer\">QQ</a></p>\n<p>方法二：微信：Jiabcdefh</p>\n</div>\n<figure><img src=\"/zsxq.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n",
      "image": "https://bornforthis.cn/gzh.jpg",
      "date_published": "2025-03-12T07:05:47.000Z",
      "date_modified": "2025-04-10T23:49:50.000Z",
      "authors": [
        {
          "name": "AI悦创"
        }
      ],
      "tags": []
    },
    {
      "title": "Lecture 13 GUI Basics",
      "url": "https://bornforthis.cn/1v1/93-LiquidLeon/Lecture13-GUI-Basics.html",
      "id": "https://bornforthis.cn/1v1/93-LiquidLeon/Lecture13-GUI-Basics.html",
      "summary": "原文 1. 主要内容 Model： 负责存储和封装数据逻辑； View： 负责展示数据，可以是文本界面，也可以是图形界面； Controller： 负责协调用户输入与对 Model 的操作，并通知 View 做出相应更新； 我们会先展示一个文本界面版本，随后演示如何切换到图形界面（GUI），以及如何一步步改进、解耦视图和控制器、处理键盘事件等。 Sta...",
      "content_html": "<details class=\"hint-container details\"><summary>原文</summary>\n<div class=\"language-java line-numbers-mode has-collapsed-lines collapsed\" data-highlighter=\"shiki\" data-ext=\"java\" style=\"--vp-collapsed-lines:15;--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-java\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">## </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1.</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> Introduction</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> to </span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">Views</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">So</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> far we’ve worked on designing </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">*</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">models</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">*</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> to represent the data relevant to a problem domain</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> in a form that encapsulates the data behind an </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">interface</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> that</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> clients can use without having to know any implementation details. The model is responsible for ensuring that it can’t get stuck in a bogus or invalid state, and exposes whatever appropriate observations and operations are needed while still preserving this integrity constraint.</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\">We’ve also worked on simple synchronous *controllers* that allow users to interact with a model, in a form that encapsulates the user interactions and can provide feedback to users without having to redundantly ensure any integrity constraints. Moreover, controllers can be customized or enhanced without needing to change the model, making the model more convenient to use without making it any more complex.</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\">Now, it’s time to introduce the third part of the MVC trio: *views*. Views are renderings of the data in the model, and can be as simple as printing debug output to a console, as complex as fancy graphical user interfaces, or anything in between. Dealing with GUIs also brings additional challenges, and we will discuss some of them.</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\">### 1.1 Outline</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\">This lecture starts by adding a text-based, interactive view to the program. This is closest to our earlier design for the controller, but it carves out a view cleanly. This example also illustrates the typical interactions between the model, view and controller in a simple manner.</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\">We then progressively transition to graphical user interfaces. We start with *poorly-designed but working* code, and improve it in three stages. Initially, the code for the view will directly manipulate the model. Our first incremental improvement will decouple the view from the model so that it need not — and in fact *cannot* — do so. Our second improvement will add a new feature to the view, and add the ability to control that in the controller. Finally, our third improvement will generalize the controller to make its UI triggers more customizable.</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\">The code for this lecture is available at the top of this page, as the [MVC code](https:</span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">//course.ccs.neu.edu/cs3500/lec/gui_basics/code.zip) link. The second link provides code for a program with an incomplete GUI. It is recommended that you complete this exercise to practice with GUIs. Finally the third link provides a solution for this GUI.</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\">## 2. Design</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\">All examples in this lecture follow a common design. The model state (interface `IModel` and implementation `Model`) consists of a single `String` and offers methods to get and update it. All views (coupled with controllers wherever applicable) expose functionality to interactively show this string, and to update it.</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\">### 3` `Text-based UI</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\">In the TextUI directory we show a text-based user interface. The IView </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">interface</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> encapsulates</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> all the methods that a view’s client would need to call: note how they correspond roughly to the “things” that a controller would need to tell the view to do. The TextView </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">class</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> implements</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> this interface. It transmits all messages to a PrintStream object provided to it through its constructor. Similar to the design in [Lecture 8](https:</span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">//course.ccs.neu.edu/cs3500/lec_controllers_mocks_notes.html) this allows us to test the view using any suitable PrintStream object.</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\">The IController </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">interface</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> represents</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> a controller: it has only method which is called to give control of the application to the controller. The TextController </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">class</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> implements</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> the controller. It works with IModel, IView and Scanner objects to handle model, view and data input functionality respectively. At its heart, the controller goes through a loop that provides users with some options, takes further inputs depending on the chosen options and delegates to the model and view accordingly. Since the sequence of operations is largely fixed, this qualifies as a *synchronous* controller.</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\">## 4. Stage 1: Introduction to GUIs</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\">In the BadDesignButFunctional directory, we have a poorly written implementation of a simple program that uses the same model, but a graphical user interface.</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\">Our `main()` method constructs a `Model`, and constructs a view that is given a reference to the model. The view interface (`IView`) has only three methods: to obtain the text the user has typed in to the text box, to clear that text box, and to echo a string to the label in the UI. The implementation of the view, `JFrameView`, is markedly more complicated in appearance than expected, but it breaks down into several simpler parts.</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\">### 4.1 Frames and controls</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\">Our program uses the Swing framework to show its UI. In Swing, an individual window is known as a *frame*, which can contain controls known as *components*. To create our own window, we design a </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">class</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> that</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> subclasses from `JFrame`, do some work to establish the components in it, and then call `setVisible` to display the window. Within the constructor of our frame, we create four components: a *label* to show some text, a *text box* to edit text, and two *buttons*. Adding several controls to a frame requires that we give them a *layout*, which describes the spatial relationships between the controls. In this example, we’re using a `FlowLayout`, which allows the controls to wrap around as we resize the window. (Try running the project and resizing the window to be narrower than the controls are.) Different layout managers allow adding controls in [different ways](https:</span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">//docs.oracle.com/javase/tutorial/uiswing/layout/visual.html). Once controls are added to the UI, the `pack()` method is used tell the layout manager to determine the actual positions and sizes of all the controls.</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\">In order for the controls to do anything, however, we need to add an *event handler* to them. An event handler, or *callback*, is simply a function that gets called when something interesting occurs. In our case, the clicking of different buttons should trigger a callback. In the jargon of Swing, clicking on buttons triggers their *action*, and so we must supply a function object that </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">implements</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> the [`</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">ActionListener</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\">`](https:</span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">//docs.oracle.com/javase/8/docs/api/java/awt/event/ActionListener.html) interface. (Other controls have additional events besides “actions”.) For convenience, Swing allows us to label each button with a so-called *action command*, which is a `String` of our choosing: when the `ActionListener`’s callback is invoked, it will be given an [`ActionEvent`](https://docs.oracle.com/javase/8/docs/api/java/awt/event/ActionEvent.html) object that knows the action command of the button that was clicked. In this way, we can use a single listener to listen to multiple buttons at once, and distinguish them by means of this command string. See the calls to `setActionCommand` and `setActionListener` and the implementation of `actionPerformed` in JFrameView.java for an example:</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\">\\```java</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\">class </span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">JFrameView</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> extends</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> JFrame</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> implements</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> ActionListener</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">  public</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> JFrameView</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">String</span><span style=\"--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\"> caption</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">IModel</span><span style=\"--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\"> model</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    ...</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    echoButton </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> new</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> JButton</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"Echo\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">);           </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">// Create a button,</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">    echoButton</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">setActionCommand</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"Echo Button\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">); </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">// set its command,</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">    echoButton</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">addActionListener</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">this</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">);         </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">// set the callback,</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">    this</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">add</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(echoButton);                       </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">// and add it to the UI</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    exitButton </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> new</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> JButton</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"Exit\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">);           </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">// ditto, for another button</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">    exitButton</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">setActionCommand</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"Exit Button\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">);</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">    exitButton</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">addActionListener</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">this</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">);</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">    this</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">add</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(exitButton);</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    ...</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">  }</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">  @</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#E5C07B\">Override</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">  public</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> void</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> actionPerformed</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">ActionEvent</span><span style=\"--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\"> e</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    switch</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> (</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">e</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">getActionCommand</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()) {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    case</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> \"Echo Button\"</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">:</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> ...</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    case</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> \"Exit Button\"</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">:</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> ...</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    }</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">  }</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">  ...</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">}</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">\\```</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">**</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">Note</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">:</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">**</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> Combining</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\"> the event handlers of multiple buttons into a single function is only temporarily convenient</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">:</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> often</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> the code we want to run </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> one button is completely different from the code we want to run </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> a different button</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> so there’s not much benefit from merging them </span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">all</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\"> Instead</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> it is more common to create anonymous objects</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> or</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> (even terser) lambda expressions</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> so that each button gets its own custom </span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">handler</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\"> We</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">’ll see other idioms of setting up listeners below</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">## </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">5.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> Stage </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">2</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">:</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> Decoupling</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> the view from the model</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">The</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\"> code above technically works</span><span style=\"--shiki-light:#E45649;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\"> but it is very poorly designed</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">:</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> the view is responsible </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> mutating the model</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> which means there’s no separation of concerns between </span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">this</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> view and any controller</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> and </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> we wanted to use the model with another sort of view</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> we’d be out of </span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">luck</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\"> In</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> the </span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">BasicMVC</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> directory</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> we start to remedy </span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">this</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\"> In</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> particular</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> we want to separate out all the parts of the code that mutate the model</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> and isolate them within a controller</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">To</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> do</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\"> this</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> we create a `Controller`</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> class</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> that</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> takes in the model and the view — at their </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">interface</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> types</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\">, not at their concrete </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">class</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> types</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\">. We revise the view so that it no longer has access to the model at all. (This is overly drastic; we merely want to ensure that the view does not have *mutable* access to the model. We can revisit this later.) We next add a method to the view interface, `void setListener(ActionListener)`, which is the key indirection needed here. Instead of the view directly implementing the response to events, this method allows the view to take in a listener object and *forward* any events it receives to that listener.</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\">\\```java</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">public</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> class</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> JFrameView</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> extends</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> JFrame</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> implements</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> IView</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">  public</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> JFrameView</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">String</span><span style=\"--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\"> caption</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> { </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">// NOTE: No model!</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    ...</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    echoButton </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> new</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> JButton</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"Echo\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">); </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">// NOTE: No action listener</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">    echoButton</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">setActionCommand</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"Echo Button\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">);</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">    this</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">add</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(echoButton);</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    exitButton </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> new</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> JButton</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"Exit\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">);</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">    exitButton</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">setActionCommand</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"Exit Button\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">);</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">    this</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">add</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(exitButton);</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    ...</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">  }</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">  public</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> void</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> setListener</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">ActionListener</span><span style=\"--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\"> listener</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">    echoButton</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">addActionListener</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(listener); </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">// Rather than adding *this* as a listener,</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">    exitButton</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">addActionListener</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(listener); </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">// add the provided one instead.</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">  }</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">  ...</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">}</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">public</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> class</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> Controller</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> implements</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> ActionListener</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">  public</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> Controller</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">IModel</span><span style=\"--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\"> m</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">IView</span><span style=\"--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\"> v</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">    this</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">model</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> =</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> m;</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">    this</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">view</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> =</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> v;</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">    view</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">setListener</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">this</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">);</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">    view</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">display</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">();</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">  }</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">  @</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#E5C07B\">Override</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">  public</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> void</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> actionPerformed</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">ActionEvent</span><span style=\"--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\"> e</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    switch</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> (</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">e</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">getActionCommand</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()) {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">      case</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> \"Echo Button\"</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">:</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> ...  </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">// same code as before, but now</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">      case</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> \"Exit Button\"</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">:</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> ...  </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">// it's extracted out of the view</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    }</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">  }</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">}</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">\\```</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">The</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> controller is now the only part of the system that has mutable access to the </span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">model</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\"> Because</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> it requested that the view register itself as the listener </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> the buttons</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> the controller gets called exactly when necessary</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> and it can decide what mutations to perform on the </span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">model</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\"> The</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> view doesn’t even know that it’s received a controller object</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">:</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> as far as it’s aware</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> the controller is simply a random `ActionListener`</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> (</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">**</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">Note</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">:</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">**</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> It</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> is overly simplified to have the `Controller` directly implement `ActionListener` — after all</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> there might be many controls inside the view that could raise action events</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> and so having a </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">*</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">single</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">*</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> `ActionListener` isn’t a scalable </span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">approach</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\"> A</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> better approach would be to have the `Controller` </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">*</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">have</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">*</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> one or more `ActionListener`s — </span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">i</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">e</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.,</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> preferring composition over inheritance — but we use </span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">this</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> simplified form </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> now to reduce the number of classes in </span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">this</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> example</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">**</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">Note</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">:</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">**</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> there is a subtle difference between the `setListener` method we’ve defined on our `IView` interface</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> and the `addActionListener` method present on the </span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">Swing</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\"> components</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">:</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> our method’s name implicitly intends </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> only </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">*</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">one</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">*</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> listener at a time</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> but </span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">Swing</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> components allow </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> multiple </span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">listeners</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\"> When</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> we have multiple listeners</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> we’ll sometimes say that the control </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">*</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">broadcasts</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">*</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> its event to whoever’s listening</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> or that it </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">*</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">publishes</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">*</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> its event to whoever’s </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">*</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">subscribed</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">*</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> to </span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">it</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\"> There</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">’s nothing limiting us from implementing </span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">this</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> more general approach</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> but that generality wasn’t needed here</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">## </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">6.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> Stage </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">3</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">:</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> Enhancing</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> the view with keyboard support</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">Our</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\"> next addition of functionality is shown in the </span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">KeyboardEvents</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\"> directory</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">:</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> we want to add some keyboard</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">triggered </span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">behaviors</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\"> Specifically</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> we’ll add two fancy features to our UI</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">:</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> the ability to toggle the color of the text from black to red and back</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> and the ability to temporarily show the text in all</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">caps</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\"> We</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">’ll </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">switch</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> colors every time we type the `</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'d'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">` key</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> and we’ll temporarily capitalize the text </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">while</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> we’re pressing and holding the `</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'c'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">` </span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">key</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\"> Interestingly</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> only one of these two </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">new</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> features requires adding a new method to our view interface</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">First</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> we’ll need to generalize our `setListener` method</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> to take in a [`KeyListener`](https</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">:</span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">//docs.oracle.com/javase/8/docs/api/java/awt/event/KeyListener.html) as well as an `ActionListener`. A `KeyListener` is analogous to a `ActionListener`, but as the name suggests, it listens for keyboard-related events. There are *three* such events: when a key is pressed, when a key is typed, and when a key is released. Pressing and holding down a key for a while will typically generate one key-pressed event, several key-typed events, and one key-released event. Just as `ActionListener`s accept `ActionEvent`s, `KeyListener`s accept [`KeyEvent`s](https://docs.oracle.com/javase/8/docs/api/java/awt/event/KeyEvent.html) containing information about which key was involved. We’ll use the `keyTyped` event to toggle the color of the text, use the `keyPressed` event to capitalize the text, and use the `keyReleased` event to un-capitalize the text.</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">For</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> now</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> we’ll simply have our controller implement the `KeyListener`</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> interface</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> also</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\">, and pass itself along as the second argument to `view.setListeners`. Again, note that the view doesn’t know or care that the exact same object is being passed in as the two distinct listeners: the types ensure that it doesn’t matter. (**Note:** And again, this is overly simplified, and we ought to have a distinct </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">class</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> implement</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> this `KeyListener` interface, rather than have the `Controller` </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">class</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> do</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> everything itself.)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\">To implement the color changing, we’ll need to add a method to our view </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">interface</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> to</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> toggle the color of the text. This is intrinsically a view-specific thing, since the controller cannot know exactly how the text is displayed or which control it needs to change color. (That would leak internal implementation details of the view, and in any case, the controller only knows it has an `IView` rather than a particular view class.)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\">To implement the capitalization, note that we *do not* actually mutate the model! This is both a good thing and a necessary thing: suppose the model text contained a mixture of upper- and lower-case letters. If we mutated the model and capitalized everything, then we would not be able to undo that change later. Instead, we ask the model for its content, and inform the view that it should display a capitalized version of the that content. (This view-only change is analogous to “zooming in” while editing a picture in Photoshop or some other image editor: the view is technically displaying only a subset of the pixels of the document, and moreover is displaying them at far more than one screen pixel per document pixel! If “zooming in” actually mutated the document, then we’d lose information and be unable to “zoom out” again.)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\">## 7. Aside 1: Low-level and high-level events</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\">Within the `KeyListener` interface, there is a qualitative difference between the key-pressed and key-released events, and the key-typed event. Individual key events are incredibly, tediously low-level. Just trying to type a capital `'A'` generates *five* events: the Shift key was pressed; the A key was pressed; the letter `'A'` was typed; the A key was released; the Shift key was released. (The last two events might happen in either order, depending on which key was released first.) Notice that only one key-typed event occurred, though, and it contained exactly the text that was typed.</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\">If we had to deduce which keys were typed, merely from the key-pressed and key-released events, we’d quickly lose track. Java (and most GUI toolkits) thankfully translate those sequences into higher-level key-typed events. And this translation has an addtional benefit: consider typing non-English text on a typical QWERTY keyboard. We clearly need to type mutliple physical keys to produce one logical character (this is sometimes known as “chord” input, by analogy with pressing multiple keys on a piano keyboard), and this translation lets us ignore the individual key-pressed and key-released events if we only want to consider what text was typed.</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\">On the other hand, if we want to keep track of which keys are pressed (e.g. to control a player’s motion while a key is held down), we need to resort to the lower-level events.</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\">This low-level/high-level distinction is not clearly defined, and depends on perspective. Would we consider `ActionEvent`s to be low-level or high-level? On the one hand, they’re clearly much *higher-level* than individual [`MouseEvent`s](https:</span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">//docs.oracle.com/javase/8/docs/api/java/awt/event/MouseEvent.html), which are analogous to `KeyEvent`s and indicate when a mouse button is pressed, released, or clicked, or when it enters or exits some area. Indeed, `JButton`s register themselves as `MouseListener`s, and translate the relevant mouse-clicked event into an `ActionEvent`! (They also register themselves as `KeyListener`s, and generate `ActionEvent`s when the Enter key is pressed.) But at the same time, the *user* of our view might not care which particular buttons we happened to use to implement the view, and there might well be multiple buttons that trigger identical actions: from that perspective, action events are too *low-level* and should be implementation details hidden behind some abstraction barrier.</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\">Designing a view and controller properly requires considering what level of detail we want to expose in the events that the view forwards to the controller. Our current designs expose far too low-level detail: “something happened with the following action command”, or “some key was pressed/typed/released”. These events are very general, and have no specific semantics for our application. Let’s consider the different enhancements we can make, using either low-level or high-level events. We’ll find that we might want to translate generic low-level events into application-specific high-level ones.</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\">## 8. Stage 4: Making the controller more flexible using low-level events</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\">Many applications run on multiple systems (e.g. Windows, Mac and Linux), and have hotkeys to perform various common actions — but the exact hotkey differs on each platform. It would be a shame to have to recompile the code in order to support these different keys. Similarly, many applications allow the user to customize the hotkeys that control the application. Here, it’s outright impossible for users to recompile the program to customize its behavior! Our next generalization aims to alleviate this lack of flexibility.</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\">Our prior attempt hard-coded the keys in the various key event-listeners. In the KeyboardMaps directory, we generalize this so that we can reconfigure hotkeys at runtime. To accomplish this, we design a new `KeyListener` implementation that uses dictionaries of `Runnable`s instead of `switch` statements in its event handlers. Specifically, our `KeyboardListener` will contain a `Map</span><span style=\"--shiki-light:#C18401;--shiki-dark:#ABB2BF\">&lt;</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">Integer</span><span style=\"--shiki-light:#C18401;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> Runnable</span><span style=\"--shiki-light:#C18401;--shiki-dark:#ABB2BF\">&gt;</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\">` dictionary for its key-pressed event handler, another such dictionary for its key-released handler, and a `Map</span><span style=\"--shiki-light:#C18401;--shiki-dark:#ABB2BF\">&lt;</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">Character</span><span style=\"--shiki-light:#C18401;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> Runnable</span><span style=\"--shiki-light:#C18401;--shiki-dark:#ABB2BF\">&gt;</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\">` dictionary for its key-typed handler. (These `Runnable`s are examples of the command pattern, which we talked about several lectures ago.)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\">The handlers are pleasingly straightforward:</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\">\\```java</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">// In the KeyboardListener class</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\">@Override</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">public</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> void keyTyped(KeyEvent e) </span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">{</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">  if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> (</span><span style=\"--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">keyTypedMap</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">containsKey</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">e</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">getKeyChar</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()))</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">    keyTypedMap.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">get</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">e</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">getKeyChar</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">())</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">run</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">();</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">}</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">// analogously for the other two events</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">\\```</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">Because</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> the dictionaries are data</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> we can mutate them at runtime </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> we so choose</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> and therefore change which keys are mapped to which responses</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> (</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">For</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> variety’s sake</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> we show three different syntaxes </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> creating `Runnable`s</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">:</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> explicit classes</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> anonymous classes</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> and lambda expressions</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">\\```java</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">// In the Controller class</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">  private</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> void</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> configureKeyBoardListener</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">() {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">    Map</span><span style=\"--shiki-light:#E45649;--shiki-dark:#ABB2BF\">&lt;</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">Character</span><span style=\"--shiki-light:#E45649;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> Runnable</span><span style=\"--shiki-light:#E45649;--shiki-dark:#ABB2BF\">&gt;</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\"> keyTypes </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> new</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> HashMap</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">&lt;&gt;</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">()</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">;</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">    Map</span><span style=\"--shiki-light:#E45649;--shiki-dark:#ABB2BF\">&lt;</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">Integer</span><span style=\"--shiki-light:#E45649;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> Runnable</span><span style=\"--shiki-light:#E45649;--shiki-dark:#ABB2BF\">&gt;</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\"> keyPresses </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> new</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> HashMap</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">&lt;&gt;</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">()</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">;</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">    Map</span><span style=\"--shiki-light:#E45649;--shiki-dark:#ABB2BF\">&lt;</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">Integer</span><span style=\"--shiki-light:#E45649;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> Runnable</span><span style=\"--shiki-light:#E45649;--shiki-dark:#ABB2BF\">&gt;</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\"> keyReleases </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> new</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> HashMap</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">&lt;&gt;</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">()</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">;</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">    // Uses an explicit function-object class to provide the implementation</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">    keyReleases</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">put</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">KeyEvent</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">VK_C</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">new</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> MakeOriginalCase</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">());</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">    // Uses an anonymous object to provide the implementation</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">    keyPresses</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">put</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">KeyEvent</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">VK_C</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">new</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> Runnable</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">() {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">      public</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> void</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> run</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">        String</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\"> text</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> =</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\"> model</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">getString</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">();</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">        text </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\"> text</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">toUpperCase</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">();</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">        view</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">setEchoOutput</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(text);</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">      }</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    });</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">    // Uses lambda-syntax to provide the implementation</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">    keyTypes</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">put</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'r'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, () </span><span style=\"--shiki-light:#C18401;--shiki-dark:#C678DD\">-&gt;</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> { </span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">view</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">toggleColor</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(); });</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">    KeyboardListener</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\"> kbd </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> new</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> KeyboardListener</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">()</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">;</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">    kbd</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">setKeyTypedMap</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(keyTypes);</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">    kbd</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">setKeyPressedMap</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(keyPresses);</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">    kbd</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">setKeyReleasedMap</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(keyReleases);</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">    this</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">view</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">addKeyListener</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(kbd);</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">  }</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">\\```</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">(</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">In</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> the same manner as </span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">this</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> `KeyboardListener`</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> our implementation also generalizes the `ActionListener` implementation into a dictionary that maps action commands to `Runnable`s</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">This</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> transformation</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> which converts </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">*</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">explicit control flow</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">*</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> (the `</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">switch</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">` statements we had earlier) into </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">*</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">data</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">*</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> (the keys of the `Map`) is a very common one in </span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">programming</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\"> We</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">’ve clearly improved things somewhat</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> but we’re not finished</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">:</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> after all</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> we hard</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">code the keys of the `Map` (as we did in the calls to `</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">keyPresses</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">put</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">` above)</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> we haven’t really fixed anything</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> right</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">?</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> Fortunately</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> we know a way around </span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">this</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">:</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> by using a combination of a </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">*</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">reader</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">*</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> and </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">*</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">builder</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">*</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> we could read in a “user preferences file” to figure out what keys to put in the maps</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> and then our code is completely agnostic to exactly which keys are needed </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> which handlers</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">## </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">9.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> Stage </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">5</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">:</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> Decoupling</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> the view from the controller using high</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">level events</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">The</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> previous generalization relied on the view exposing its low</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">level events to the </span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">controller</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\"> However</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> we might reasonably want to trigger the same behavior from multiple </span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">UI</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\"> controls</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\"> In</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> the </span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">GeneralCommandCallbacks</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\"> directory</span><span style=\"--shiki-light:#E45649;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\"> we take </span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">this</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\"> approach</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">:</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> our view can toggle the color of the text either via a button</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> or via typing the `</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'t'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">` key</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> (</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">This</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> is a simplified example</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> but is a stand</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">in </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> typical toolbar buttons doing the same thing as hotkey shortcuts</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">The</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> key innovation in </span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">this</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> design is that we’ve eliminated the `ActionListener`s and `KeyListener`s from the controller and </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">*</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">also</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">*</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> from the `IView` </span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">interface</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\"> Instead</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> we have a </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">new</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> `addFeatures` method that takes in a new interface</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> `Features`</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> whose methods are the various high</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">level features and abilities of our </span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">view</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\"> Our</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> *</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">prior</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">*</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> interfaces exposed low</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">level events saying</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> instance</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> “Hey</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> a button with </span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">this</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> action command has been clicked</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">;</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> what should be done</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">?</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">” These </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">*</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">new</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">*</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> callbacks say</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> example</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> “</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">The</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\"> user has requested to make the display uppercase</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">;</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> what should be done</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">?</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">”</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> This </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">interface</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> is</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> bigger than the `ActionListener` interface, but it’s also much more application-specific, and it advertises exactly the responsibilities a controller has to uphold for this view. It also successfully encapsulates the action commands that we leaked in prior designs: the view is now free to change those commands without breaking the controller at all.</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\">This design is quite elegant, and does the best job of loosening the coupling between the view and the controller: by encapsulating the details of which physical controls do what, the view is much more abstracted away, and the logical </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">interface</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> that</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> it presents to the controller is much more application-specific. Note that the `Controller` </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">class</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> and</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> the `Features` </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">interface</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> know</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> absolutely nothing about Swing: they don’t even `import` the packages! Just like our model doesn’t need to know about how it’s being displayed, so too our controller doesn’t really need to know how the views are implemented. When possible, aspire to interfaces like this one, but be prepared to fall back to lower-level events when necessary.</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\">**Note:** It might seem odd that the `toggleColor` method is both a callback on the `Features` interface *and* a method on the `IView` interface — why can’t the view handle this internally? Indeed, it possibly could! (And in some circumstances, the view definitely *should* handle some events entirely internally: for instance, when implementing a text editor, the view should probably internally handle the sequence of low-level events that indicate the user has selected a stretch of text. Once the user does something with that text — deletes it, replaces it, copies it, etc. — the view can raise a semantically relevant high-level event with the selected content.) But consider a “bigger” version of our current program, where we have *two* views that we want to keep </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">synchronized</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\">: if either of them has toggled its color, both should toggle their colors together. The only way to ensure this synchronization is for the view to forward the event to the controller, which can in turn decide to tell *both* views how to update themselves.</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\">**Note:** Once again, in the sample code and in the snippets below, we write that the `Controller` `implements` `Features` directly: we use an is-a relationship. A better approach is to use a has-a relationship, and have a dedicated object that </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">implements</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> the `</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">Features</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\">` interface instead. </span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">We</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> omit this variant here</span><span style=\"--shiki-light:#C18401;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> because there are enough other details to focus on right now!</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\">## 10. </span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">Aside</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> 2: </span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">Designing</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> a </span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">Features</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> interface</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">In</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> the previous section we introduced a `</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">Features</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\">` interface</span><span style=\"--shiki-light:#C18401;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> that hid the *</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">Swing</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\">*-specific event listeners and instead exposed *application*-specific events. </span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">But</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> how are we to know what sort of application-specific events we should have? </span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">It</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\">’s difficult to give a one-size-fits-all answer here</span><span style=\"--shiki-light:#C18401;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> since by definition this will be rather application-specific. </span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">Instead</span><span style=\"--shiki-light:#C18401;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> we can articulate some guidelines to follow:</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\">- </span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">Avoid</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> any view-specific classes in the `</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">Features</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\">` interface wherever possible. </span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">Above</span><span style=\"--shiki-light:#C18401;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> we said to eliminate any mention of </span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">Swing</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\">-specific events</span><span style=\"--shiki-light:#C18401;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> and generalized it further so that the controller did not need to depend on the </span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">Swing</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> library at all. </span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">We</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> can easily come up with a plausible counterexample to this generality: suppose we were building a drawing program</span><span style=\"--shiki-light:#C18401;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> and the view allows the user to choose a color to draw with. </span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">Surely</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> the `</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">Features</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\">` interface should expose the `java.awt.</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">Color</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\">` that the user picked? </span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">In</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> this case</span><span style=\"--shiki-light:#C18401;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> though</span><span style=\"--shiki-light:#C18401;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> the *model* also depends on `java.awt.</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">Color</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\">`</span><span style=\"--shiki-light:#C18401;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> and so the view isn’t introducing any new dependencies. </span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">If</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> the model chose a different class to represent its colors</span><span style=\"--shiki-light:#C18401;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> then the `</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">Features</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\">` interface ought to expose *that*</span><span style=\"--shiki-light:#C18401;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> rather than the </span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">Swing</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> color directly.</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\">- </span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">Treat</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> the methods in the `</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">Features</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\">` interface as *requests from the user*. </span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">In</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> particular</span><span style=\"--shiki-light:#C18401;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> a view might allow a user to attempt various editing operations that the controller might prohibit</span><span style=\"--shiki-light:#C18401;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> or that the model might reject as invalid. </span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">In</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> our example above</span><span style=\"--shiki-light:#C18401;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> “requesting an uppercase display” fits into this mindset. </span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">Additionally</span><span style=\"--shiki-light:#C18401;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> brainstorming “what might the user try to do?” can help articulate all the possible features a user might want from the program</span><span style=\"--shiki-light:#C18401;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> which in turn can help design the `</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">Features</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\">` methods needed.</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\">- </span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">Not</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> all view-specific events need to turn into `</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">Features</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\">` requests. </span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">However</span><span style=\"--shiki-light:#C18401;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> events that never make it to the controller are therefore intrinsically uncontrollable. </span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">In</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> sophisticated </span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">GUIs</span><span style=\"--shiki-light:#C18401;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> a single controller might need to synchronize multiple views: for instance</span><span style=\"--shiki-light:#C18401;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> a [split-screen text editor](https:</span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">//camo.githubusercontent.com/c535bd502fea4873724e2bebc144d3e2f4fe075e/68747470733a2f2f662e636c6f75642e6769746875622e636f6d2f6173736574732f32352f3131393038312f37333938343237612d366339362d313165322d393464632d3839363462333237333131332e706e67) could have two views of the same file, whose contents should be changed in tandem. A [video editor](https://helpx.adobe.com/content/dam/help/en/after-effects/how-to/camera-animation/jcr_content/main-pars/image_1685031719/camera-animation_step2.jpg) might have a timeline view at the bottom of the screen, as well as controls for the effects and a preview window, all of which must stay consistent. A [spreadsheet](https://www.exceldashboardtemplates.com/wp-content/uploads/2017/05/Copy-an-Excel-Chart-on-Same-Worksheet-Keeps-Same-Data-Reference-Final-Copied-Charts.png) might have a grid showing many cells of data, a textbox to edit a single cell, and a graph of multiple cells’ data, again which all must stay consistent. When implementing event handlers inside a particular view, consider whether the change being handled might need to be synchronized with multiple views: if so, then it should be raised as a `Features` request. If not, then it *might* be entirely handled within the view. For instance, scrolling a single text file might not need to inform the controller that the file has been scrolled, and so scrolling could be handled entirely within the view. On the other hand, a [diff viewer](https://www.git-tower.com/blog/media/pages/posts/diff-tools-windows/037ea85d83-1690885042/meld.png) that compares two files might wnat to scroll both files in unison, and so any scroll changes would need to be raised to the controller’s attention so that it can synchronize both views.</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\">- </span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">When</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> a `</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">Features</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\">` event is raised to the controller’s attention</span><span style=\"--shiki-light:#C18401;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> the view *probably* shouldn’t mutate itself</span><span style=\"--shiki-light:#C18401;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> but rather wait for the controller to tell it to do so — this is in keeping with thinking of features as requests rather than demands. </span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">We</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> noted this above</span><span style=\"--shiki-light:#C18401;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> where `toggleColor` was both a method in the `</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">Features</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\">` interface and also a method on the view</span><span style=\"--shiki-light:#C18401;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> and the controller’s implementation of the `toggleColor` method turned around and called the view’s method</span><span style=\"--shiki-light:#C18401;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> and we said this might seem overly roundabout. </span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">We</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> gave one example where this was needed for synchronization of multiple views. </span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">Another</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> might be triggering some resource-limited effect (where the resource might be tracked by the model</span><span style=\"--shiki-light:#C18401;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> like in-game bonuses</span><span style=\"--shiki-light:#C18401;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> or the resource might be controller-specific</span><span style=\"--shiki-light:#C18401;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> like live-streaming a video of a gameplay). </span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">The</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> view shouldn’t modify itself until the controller (and possibly model too) has confirmed that the request can go through.</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\">- </span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">Any</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> event that is handled entirely within the view is intrinsically more difficult to test. </span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">We</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> would have to synthesize the low-level </span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">UI</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> events</span><span style=\"--shiki-light:#C18401;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> which may be impractical or even impossible to do sufficiently. </span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">By</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> decoupling the particular </span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">UI</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> event that triggers behavior from the `</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">Features</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\">` implementation that actually provides the behavior</span><span style=\"--shiki-light:#C18401;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> we limit the hard-to-test code to just the “wiring” between the event listeners and the `</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">Features</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\">` object. </span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">Since</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> all the interesting behavior is now in the `</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">Features</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\">` object</span><span style=\"--shiki-light:#C18401;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> and since its methods depend only on application-specific concepts and types</span><span style=\"--shiki-light:#C18401;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> we can easily create a mock view that triggers `</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">Features</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\">` methods without needing the actual </span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">Swing</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> events. </span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">This</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> allows for test cases analogous to those we saw in [</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">Lecture</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> 8](https:</span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">//course.ccs.neu.edu/cs3500/lec_controllers_mocks_notes.html), with all the benefits they bring.</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\">## 11. </span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">Stage</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> 6: </span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">Further</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> enhancements using `</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">InputMap</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\">`s and `</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">ActionMap</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\">`s</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">Our</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> last revision eliminated the flexibility of dynamically changing hotkeys and reverted to hard-coding the keys in the view’s implementation of its own key listener. </span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">Combining</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> the flexibility of the `</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">KeyboardListener</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\">` and its dictionaries</span><span style=\"--shiki-light:#C18401;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> with the high-level events of the `</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">Features</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\">` interface</span><span style=\"--shiki-light:#C18401;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> is aesthetically tricky: who should control which keys do what? </span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">In</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> some sense</span><span style=\"--shiki-light:#C18401;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> it almost feels like the choice should be made not by our current controller</span><span style=\"--shiki-light:#C18401;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> which is controlling a particular model and view</span><span style=\"--shiki-light:#C18401;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> but rather to some hypothetical “application controller”</span><span style=\"--shiki-light:#C18401;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> that controls the overall application. </span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">We</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\">’ve already encountered this in practice: in </span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">IntelliJ</span><span style=\"--shiki-light:#C18401;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> there are both project-specific settings and application-wide settings</span><span style=\"--shiki-light:#C18401;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> and different dialogs control those different features.</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">Additionally</span><span style=\"--shiki-light:#C18401;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> implementing the keyboard-listening dictionaries is tedious: surely this functionality could be implemented once and for all</span><span style=\"--shiki-light:#C18401;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> and we wouldn’t need to redo it in every single application?</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">The</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> solution</span><span style=\"--shiki-light:#C18401;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> once again</span><span style=\"--shiki-light:#C18401;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> is a layer of indirection. </span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">We</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\">’ve seen above that </span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">Swing</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> components have a notion of an *action command*</span><span style=\"--shiki-light:#C18401;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> and that we can cause code to run depending on which action was triggered. </span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">Combining</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> several of these actions together should seem reminiscent of the `</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">KeyboardListener</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\">` dictionaries we just built. </span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">In</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> fact</span><span style=\"--shiki-light:#C18401;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> Swing</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> has a concept of an [`</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">ActionMap</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\">`](https:</span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">//docs.oracle.com/javase/8/docs/api/javax/swing/ActionMap.html), which is essentially just such a dictionary from action commands to actions.[1](https://course.ccs.neu.edu/cs3500/lec_gui_basics_notes.html#(counter-()._(gentag._23._lecturegui_basics))) An `Action` in Swing has many potential subclasses; we’ll focus on the `AbstractAction` class, which we can subclass ourselves to create new action handlers. For instance, we might write</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\">\\```java</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">Action</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> makeOriginalCase = new </span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">AbstractAction</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\">() </span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">{</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">  public</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> void</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> actionPerformed</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">ActionEvent</span><span style=\"--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\"> e</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">    String</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\"> text</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> =</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\"> model</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">getString</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">();</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">    view</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">setEchoOutput</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(text);</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">  }</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">};</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">Action</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\"> makeCaps </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> new</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> AbstractAction</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">() {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">  public</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> void</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> actionPerformed</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">ActionEvent</span><span style=\"--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\"> e</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">    String</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\"> text</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> =</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\"> model</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">getString</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">();</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    text </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\"> text</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">toUpperCase</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">();</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">    view</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">setEchoOutput</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(text);</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">  }</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">}</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">;</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">Action</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\"> toggleColor </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> new</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> AbstractAction</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">() {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">  public</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> void</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> actionPerformed</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">ActionEvent</span><span style=\"--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\"> e</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">    view</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">toggleColor</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">();</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">  }</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">}</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">;</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">\\```</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">This</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> is all well and good</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> and now we have yet one more way of representing runnable bits of code</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> but how should we actually associate these actions with their keyboard triggers</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">?</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> First</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> we associate these `Action`s with their action commands</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">:</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">\\```java</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">// Somewhere in our View class:</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">aComponent</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">getActionMap</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">().</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">put</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"restoreLowercase\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, makeOriginalCase);</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">aComponent</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">getActionMap</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">().</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">put</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"makeCaps\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, makeCaps);</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">aComponent</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">getActionMap</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">().</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">put</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"toggleColor\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, toggleColor);</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">\\```</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">We</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\"> then need the second piece of the indirection</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">:</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> an [`InputMap`](https</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">:</span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">//docs.oracle.com/javase/8/docs/api/javax/swing/InputMap.html). `InputMap`s associate [`KeyStroke`s](https://docs.oracle.com/javase/8/docs/api/javax/swing/KeyStroke.html) with action commands. A `KeyStroke` describes our key-press, key-release, and key-type low-level events in a uniform manner. When a low-level key event matches something in an `InputMap`, the associated action command is looked up in the `ActionMap` and fired. So we can continue our code as follows:</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">\\```java</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">// Somewhere in our View class:</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">// Use simplest constructor to describe a key-press</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">aComponent</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">getInputMap</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">().</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">put</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">KeyStroke</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">getKeyStroke</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">KeyEvent</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">VK_C</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">), </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"makeCaps\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">);</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">// Use another constructor to describe key-releases</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">aComponent</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">getInputMap</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">().</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">put</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">KeyStroke</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">getKeyStroke</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">KeyEvent</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">VK_C</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">true</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">), </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"restoreLowercase\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">);</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">// Yet another constructor lets us describe key-typed events</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">aComponent</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">getInputMap</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">().</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">put</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">KeyStroke</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">getKeyStroke</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"typed r\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">), </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"toggleColor\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">);</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">\\```</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">**</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">Note</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">:</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">**</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> `InputMap`s and `ActionMap`s apply only to `JComponent`s</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> and not to `JFrame`s </span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">directly</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\"> However</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> we can easily add a component to our frame </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> the sole purpose of handling key events</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> and we [can specify](https</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">:</span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">//docs.oracle.com/javase/tutorial/uiswing/misc/keybinding.html) that its `InputMap` be used whenever the frame has focus at all.</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">This</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> seems like a lot of machinery to introduce</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> and it would be unwieldy </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> it weren’t so </span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">reusable</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\"> The</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> critical design patterns here are</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">:</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> We</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> have a mechanism </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> translating low</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">level</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> (`KeyEvent`s) into mid</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">level action commands</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> We</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> have transformed control </span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">flow</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> (of what code to run based on what key was pressed) into </span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">data</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> (a map of `KeyStroke`s)</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> We</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> have a mechanism from translating mid</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">level action commands into actual runnable actions</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">The</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\"> code still suffers from one problem</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">:</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> the `Action`s themselves feel like they belong in the </span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">controller</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> (since they refer to `model` and `view`)</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> but are referenced directly in the </span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">view</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> (in the `</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">getActionMap</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">()</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">put</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(...)</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">` lines)</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\"> We</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> can combine these maps with our `Features` design</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> to get one </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">final</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> translation from mid</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">level action commands to high</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">level events</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">:</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">\\```java</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">// NOTE: this class makes no mention of Actions or Controllers.</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">public</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> class</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> JFrameView</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> extends</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> JFrame</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> implements</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> IView</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">  KeyComponent</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\"> keyComponent</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">;</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">  public</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> JFrameView</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">String</span><span style=\"--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\"> caption</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">    super</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(caption);</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    ...</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">    this</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">keyComponent</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> =</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> new</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> KeyComponent</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">();</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">    this</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">add</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(keyComponent);</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">  }</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">  public</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> void</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> setHotKey</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">KeyStroke</span><span style=\"--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\"> key</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">String</span><span style=\"--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\"> featureName</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">    this</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">keyComponent</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">getInputMap</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">().</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">put</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(key, featureName);</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">  }</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">  public</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> void</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> addFeatures</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">Features</span><span style=\"--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\"> features</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">    this</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">keyComponent</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">addFeatures</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(features);</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">  }</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">}</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">// NOTE: Neither does this class!  It only refers to Features.</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">class</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> KeyComponent</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> extends</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> JPanel</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">  List</span><span style=\"--shiki-light:#E45649;--shiki-dark:#ABB2BF\">&lt;</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">Features</span><span style=\"--shiki-light:#E45649;--shiki-dark:#ABB2BF\">&gt;</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\"> featureListeners </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> new</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> ArrayList</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">&lt;&gt;</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">()</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">;</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">  // Includes this new feature listener in responding to keys</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">  void</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> addFeatures</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">Features</span><span style=\"--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\"> f</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> { </span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">this</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">featureListeners</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">add</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(f); }</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">  KeyComponent</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">    // Install action command -&gt; Feature callback associations</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">    this</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">getActionMap</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">().</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">put</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"makeCaps\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">new</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> AbstractAction</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">() {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">      public</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> void</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> actionPerformed</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">ActionEvent</span><span style=\"--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\"> e</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> (</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">Features</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\"> f</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> :</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> featureListeners)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">          f</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">makeUppercase</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">();</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">      }</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    });</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">    this</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">getActionMap</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">().</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">put</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"restoreLowercase\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">new</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> AbstractAction</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">() {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">      public</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> void</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> actionPerformed</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">ActionEvent</span><span style=\"--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\"> e</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> (</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">Features</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\"> f</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> :</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> featureListeners)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">          f</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">restoreLowercase</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">();</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">      }</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    });</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">    this</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">getActionMap</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">().</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">put</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"toggleColor\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">new</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> AbstractAction</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">() {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">      public</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> void</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> actionPerformed</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">ActionEvent</span><span style=\"--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\"> e</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> (</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">Features</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\"> f</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> :</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> featureListeners)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">          f</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">toggleColor</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">();</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">      }</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    });</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    ...</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">  }</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">}</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">// NOTE: Only the Controller needs to know how to implement Features.</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">public</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> class</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> Controller</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> implements</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> Features</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">  private</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> IModel</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\"> model</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">;</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">  private</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> IView</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\"> view</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">;</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">  ...</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">  // These are the high-level event handlers we care about:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">  @</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#E5C07B\">Override</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">  public</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> void</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> toggleColor</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">    view</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">toggleColor</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">();</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">  }</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">  @</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#E5C07B\">Override</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">  public</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> void</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> makeUppercase</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">    String</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\"> text</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> =</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\"> model</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">getString</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">();</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    text </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\"> text</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">toUpperCase</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">();</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">    view</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">setEchoOutput</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(text);</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">  }</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">  @</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#E5C07B\">Override</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">  public</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> void</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> restoreLowercase</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">    String</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\"> text</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> =</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\"> model</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">getString</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">();</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">    view</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">setEchoOutput</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(text);</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">  }</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">  // This attaches this controller as our features listener</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">  public</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> void</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> setView</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">IView</span><span style=\"--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\"> v</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">    this</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">view</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> =</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> v;</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">    view</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">addFeatures</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">this</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">);</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">    // Choose the keys we want</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">    view</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">setHotKey</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">KeyStroke</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">getKeyStroke</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"pressed c\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">), </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"makeCaps\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">);</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">    view</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">setHotKey</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">KeyStroke</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">getKeyStroke</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"released c\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">), </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"restoreLowercase\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">);</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">    view</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">setHotKey</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">KeyStroke</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">getKeyStroke</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"typed r\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">), </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"toggleColor\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">);</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">  }</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">  ...</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">}</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">\\```</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">## </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">12.</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> Exercises</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">At</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> the top of </span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">this</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> lecture are starter files </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> a </span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">GUI</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> version of the </span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">Turtles</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> example we worked through in [Lecture </span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">10</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">](https</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">:</span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">//course.ccs.neu.edu/cs3500/lec_commands_notes.html). The `TurtleGraphicsView` does not currently do anything. Enhance this code with a new `TurtlePanel` class that `extends JPanel`, and override its `paintComponent` method to draw whatever you want, just to confirm that it works.</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">Next</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> enhance the `IView`</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> interface</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> so</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> you can pass the relevant information from the model, through the controller, into the view and into your `TurtlePanel` class. Once you’ve connected the pieces, use this information in your `paintComponent` implementation to draw the turtle’s trace.</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\">The links at the top of the lecture include a “solution” implementation; do not to look at that until you’ve tried to implement this yourself.</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\">The `IView` </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">interface</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> contains</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\"> one method for setting up an event listener. What is its signature? Does it seem like a high-level event to you, or a low-level one? If you think it’s too low-level, can you think of a better, higher-level signature to use? If you think it’s sufficiently high-level, why do you think so?</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E06C75\">1`Action`s themselves are more generally useful in Swing than just for keyboard interaction, but we’ll focus on just the keyboard part here.</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div><div class=\"collapsed-lines\"></div></div></details>\n<h2>1. 主要内容</h2>\n<ol>\n<li><strong>Model</strong>： 负责存储和封装数据逻辑；</li>\n<li><strong>View</strong>： 负责展示数据，可以是文本界面，也可以是图形界面；</li>\n<li><strong>Controller</strong>： 负责协调用户输入与对 Model 的操作，并通知 View 做出相应更新；</li>\n</ol>\n<p>我们会先展示一个<strong>文本界面</strong>版本，随后演示如何切换到<strong>图形界面</strong>（GUI），以及如何一步步改进、解耦视图和控制器、处理键盘事件等。</p>\n<h2>Stage 1: 实现基础 Model</h2>\n<h3>1. Model 接口</h3>\n<ul>\n<li><strong>代码名称</strong>： <code>IModel.java</code></li>\n<li><strong>功能</strong>： 定义了一个最简单的模型接口，只有 <code>get/set</code> 字符串的方法，供后续 view 和 Controller 调用。</li>\n</ul>\n<div class=\"language-java line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"java\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-java\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">public</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> interface</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> IModel</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">  /**</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">   * 获取当前存储的字符串</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">   * </span><span style=\"--shiki-light:#A626A4;--shiki-light-font-style:italic;--shiki-dark:#C678DD;--shiki-dark-font-style:italic\">@return</span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"> 模型中的字符串</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">   */</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">  String</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> getString</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">();</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">  /**</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">   * 设置新的字符串</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">   * </span><span style=\"--shiki-light:#A626A4;--shiki-light-font-style:italic;--shiki-dark:#C678DD;--shiki-dark-font-style:italic\">@param</span><span style=\"--shiki-light:#383A42;--shiki-light-font-style:italic;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\"> str</span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"> 要设置的新字符串</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">   */</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">  void</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> setString</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">String</span><span style=\"--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\"> str</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">);</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">}</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p><strong>代码逐行注释</strong>：</p>\n<ol>\n<li><code>public interface IModel { ... }</code>：定义一个接口，命名为 <code>IModel</code>。</li>\n<li><code>String getString();</code>：声明一个方法用于读取当前字符串。</li>\n<li><code>void setString(String str);</code>：声明一个方法用于更新当前字符串。</li>\n</ol>\n<h3>2. Model 类</h3>\n<ul>\n<li>\n<p><strong>代码名称</strong>：<code>Model.java</code></p>\n</li>\n<li>\n<p><strong>功能</strong>：<code>IModel</code> 接口的具体实现，内部用一个 <code>String</code> 来存储数据。</p>\n</li>\n</ul>\n<div class=\"language-java line-numbers-mode has-collapsed-lines collapsed\" data-highlighter=\"shiki\" data-ext=\"java\" style=\"--vp-collapsed-lines:15;--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-java\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">public</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> class</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> Model</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> implements</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> IModel</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">  private</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> String</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\"> data</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">;</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">  /**</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">   * 构造函数，初始化字符串为空或给定初值</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">   */</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">  public</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> Model</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">    this</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">data</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> =</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> \"\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">;</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">  }</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">  @</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#E5C07B\">Override</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">  public</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> String</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> getString</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    return</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\"> this</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">data</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">;</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">  }</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">  @</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#E5C07B\">Override</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">  public</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> void</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> setString</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">String</span><span style=\"--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\"> str</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">    this</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">data</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> =</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> str;</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">  }</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">}</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div><div class=\"collapsed-lines\"></div></div><p><strong>代码逐行注释</strong>：</p>\n<ol>\n<li><code>public class Model implements IModel</code>：类 <code>Model</code> 实现了 <code>IModel</code> 接口。</li>\n<li><code>private String data;</code>：私有字段 <code>data</code> 用于实际存储字符串内容。</li>\n<li><code>public Model()</code>：构造函数，将 <code>data</code> 初始化为空字符串（当然也可改为接受一个初始值）。</li>\n<li><code>public String getString()</code>：实现接口方法，返回当前存储的字符串。</li>\n<li><code>public void setString(String str)</code>：实现接口方法，修改存储的字符串。</li>\n</ol>\n<h2>Stage 2: 实现文本方式的 View</h2>\n<h3>1. IView 接口</h3>\n<ul>\n<li>\n<p><strong>代码名称</strong>：<code>IView.java</code></p>\n</li>\n<li>\n<p><strong>功能</strong>：定义了一个最简单的视图接口，能够显示信息，以及（可选）展示错误消息等。这里只做最基本的打印操作。</p>\n</li>\n</ul>\n<div class=\"language-java line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"java\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-java\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">public</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> interface</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> IView</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">  /**</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">   * 显示给用户看的输出</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">   * </span><span style=\"--shiki-light:#A626A4;--shiki-light-font-style:italic;--shiki-dark:#C678DD;--shiki-dark-font-style:italic\">@param</span><span style=\"--shiki-light:#383A42;--shiki-light-font-style:italic;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\"> message</span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"> 要显示的内容</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">   */</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">  void</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> showMessage</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">String</span><span style=\"--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\"> message</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">);</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">  /**</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">   * 显示错误信息</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">   * </span><span style=\"--shiki-light:#A626A4;--shiki-light-font-style:italic;--shiki-dark:#C678DD;--shiki-dark-font-style:italic\">@param</span><span style=\"--shiki-light:#383A42;--shiki-light-font-style:italic;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\"> error</span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"> 要显示的错误信息</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">   */</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">  void</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> showError</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">String</span><span style=\"--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\"> error</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">);</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">}</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p><strong>代码逐行注释</strong>：</p>\n<ol>\n<li><code>public interface IView { ... }</code>：定义视图接口 <code>IView</code>。</li>\n<li><code>void showMessage(String message);</code>：向用户显示普通文本消息。</li>\n<li><code>void showError(String error);</code>：向用户显示错误信息或提示。</li>\n</ol>\n<h3>2. TextView 类</h3>\n<ul>\n<li><strong>代码名称</strong>：<code>TextView.java</code></li>\n<li><strong>功能</strong>：<code>IView</code> 的具体实现，把消息打印到给定的输出流（如控制台）。</li>\n</ul>\n<div class=\"language-java line-numbers-mode has-collapsed-lines collapsed\" data-highlighter=\"shiki\" data-ext=\"java\" style=\"--vp-collapsed-lines:15;--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-java\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">import</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> java.io.PrintStream</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">;</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">public</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> class</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> TextView</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> implements</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> IView</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">  private</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> final</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> PrintStream</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\"> out</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">;</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">  /**</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">   * 构造函数</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">   * </span><span style=\"--shiki-light:#A626A4;--shiki-light-font-style:italic;--shiki-dark:#C678DD;--shiki-dark-font-style:italic\">@param</span><span style=\"--shiki-light:#383A42;--shiki-light-font-style:italic;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\"> out</span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"> 指定要输出的流，比如 System.out</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">   */</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">  public</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> TextView</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">PrintStream</span><span style=\"--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\"> out</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">    this</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">out</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> =</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> out;</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">  }</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">  @</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#E5C07B\">Override</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">  public</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> void</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> showMessage</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">String</span><span style=\"--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\"> message</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">    out</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">println</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(message);</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">  }</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">  @</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#E5C07B\">Override</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">  public</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> void</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> showError</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">String</span><span style=\"--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\"> error</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">    out</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">println</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"ERROR: \"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> +</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> error);</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">  }</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">}</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div><div class=\"collapsed-lines\"></div></div><p><strong>代码逐行注释</strong>：</p>\n<ol>\n<li><code>private final PrintStream out;</code>：用来存放输出流（比如 <code>System.out</code>，也可以是测试时的假输出）。</li>\n<li>构造函数：接受一个 <code>PrintStream out</code> 并保存，方便后续统一打印。</li>\n<li><code>showMessage</code>：实现接口方法，直接打印普通信息。</li>\n<li><code>showError</code>：实现接口方法，在打印时加上 <code>\"ERROR: \"</code> 前缀以示区别。</li>\n</ol>\n<h2>Stage 3: 实现文本方式的 Controller</h2>\n<h3>1. IController 接口</h3>\n<ul>\n<li><strong>代码名称</strong>：<code>IController.java</code></li>\n<li><strong>功能</strong>：定义了控制器的最小接口，即一个 <code>start()</code> 方法，开始接管程序流程。</li>\n</ul>\n<div class=\"language-java line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"java\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-java\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">public</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> interface</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> IController</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">  /**</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">   * 开始执行程序逻辑</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">   */</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">  void</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> start</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">();</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">}</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><h3>2. TextController 类</h3>\n<ul>\n<li><strong>代码名称</strong>：<code>TextController.java</code></li>\n<li><strong>功能</strong>：文本控制器的实现，结合 <code>IModel</code>、<code>IView</code> 以及用户输入（通过 Scanner 读取）。循环读取用户命令，进行相应处理。</li>\n</ul>\n<div class=\"language-java line-numbers-mode has-collapsed-lines collapsed\" data-highlighter=\"shiki\" data-ext=\"java\" style=\"--vp-collapsed-lines:15;--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-java\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">import</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> java.util.Scanner</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">;</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">public</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> class</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> TextController</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> implements</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> IController</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">  private</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> final</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> IModel</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\"> model</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">;</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">  private</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> final</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> IView</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\"> view</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">;</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">  private</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> final</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> Scanner</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\"> sc</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">;</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">  /**</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">   * 构造函数</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">   * </span><span style=\"--shiki-light:#A626A4;--shiki-light-font-style:italic;--shiki-dark:#C678DD;--shiki-dark-font-style:italic\">@param</span><span style=\"--shiki-light:#383A42;--shiki-light-font-style:italic;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\"> model</span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"> 模型</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">   * </span><span style=\"--shiki-light:#A626A4;--shiki-light-font-style:italic;--shiki-dark:#C678DD;--shiki-dark-font-style:italic\">@param</span><span style=\"--shiki-light:#383A42;--shiki-light-font-style:italic;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\"> view</span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">  视图</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">   * </span><span style=\"--shiki-light:#A626A4;--shiki-light-font-style:italic;--shiki-dark:#C678DD;--shiki-dark-font-style:italic\">@param</span><span style=\"--shiki-light:#383A42;--shiki-light-font-style:italic;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\"> sc</span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">    用于读取用户输入的扫描器</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">   */</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">  public</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> TextController</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">IModel</span><span style=\"--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\"> model</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">IView</span><span style=\"--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\"> view</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">Scanner</span><span style=\"--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\"> sc</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">    this</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">model</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> =</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> model;</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">    this</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">view</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> =</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> view;</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">    this</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">sc</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> =</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> sc;</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">  }</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">  @</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#E5C07B\">Override</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">  public</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> void</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> start</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">    view</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">showMessage</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"欢迎使用文本版程序！\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">);</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    boolean</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\"> running</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> =</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> true</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">;</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    while</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> (running) {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">      view</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">showMessage</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"请输入操作：</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">\\n</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> +</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">                       \"1: 查看当前字符串</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">\\n</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> +</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">                       \"2: 设置新的字符串</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">\\n</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> +</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">                       \"q: 退出程序\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">);</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">      String</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\"> input</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> =</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\"> sc</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">nextLine</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">().</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">trim</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">();</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">      switch</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> (input) {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        case</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> \"1\"</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">:</span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"> // 查看当前字符串</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">          String</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\"> current</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> =</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\"> model</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">getString</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">();</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">          view</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">showMessage</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"当前字符串为: \"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> +</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> current);</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">          break</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">;</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        case</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> \"2\"</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">:</span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"> // 设置新的字符串</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">          view</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">showMessage</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"请输入新字符串：\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">);</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">          String</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\"> newVal</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> =</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\"> sc</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">nextLine</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">();</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">          model</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">setString</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(newVal);</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">          view</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">showMessage</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"已更新字符串！\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">);</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">          break</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">;</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        case</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> \"q\"</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">:</span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"> // 退出</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">          running </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> false</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">;</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">          view</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">showMessage</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"程序已退出。\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">);</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">          break</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">;</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        default:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">          view</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">showError</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"未知命令，请重新输入。\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">);</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">      }</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    }</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">  }</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">}</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div><div class=\"collapsed-lines\"></div></div><p><strong>代码逐行注释</strong>：</p>\n<ol>\n<li>定义了 <code>model</code>, <code>view</code>, <code>sc</code> 三个私有字段，分别负责模型、视图和输入。</li>\n<li><code>public TextController(IModel model, IView view, Scanner sc)</code>：构造函数中注入这三者。</li>\n<li><code>start()</code>：核心方法，用 <code>while</code> 循环反复让用户输入命令。</li>\n<li>根据用户输入的内容（<code>switch (input)</code>）来做不同的操作：\n<ul>\n<li><code>\"1\"</code>：读取并打印当前字符串</li>\n<li><code>\"2\"</code>：让用户输入新的字符串并更新到模型中</li>\n<li><code>\"q\"</code>：退出循环并结束程序</li>\n<li>其他：打印错误提示</li>\n</ul>\n</li>\n</ol>\n<h2>Stage 4: 测试并运行文本版 MVC</h2>\n<ul>\n<li><strong>代码名称</strong>：<code>MainText.java</code>（示例主类）</li>\n<li><strong>功能</strong>：演示如何搭建并运行我们的文本版 MVC。</li>\n</ul>\n<div class=\"language-java line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"java\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-java\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">import</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> java.util.Scanner</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">;</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">public</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> class</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> MainText</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">  public</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> static</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> void</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> main</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">String</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">[] </span><span style=\"--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">args</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">    IModel</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\"> model</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> =</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> new</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> Model</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">();                 </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">// 创建模型</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">    IView</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\"> view</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> =</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> new</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> TextView</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">System</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">out</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">);      </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">// 创建文本视图，输出到控制台</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">    Scanner</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\"> sc</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> =</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> new</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> Scanner</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">System</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">in</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">);        </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">// 创建扫描器读取用户输入</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">    IController</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\"> controller</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> =</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> new</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> TextController</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(model, view, sc);</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">    controller</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">start</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">();                         </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">// 启动文本版程序</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">  }</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">}</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p><strong>代码逐行注释</strong>：</p>\n<ol>\n<li><code>IModel model = new Model();</code>：实例化我们刚才写的 <code>Model</code>。</li>\n<li><code>IView view = new TextView(System.out);</code>：文本视图使用 <code>System.out</code> 输出到控制台。</li>\n<li><code>Scanner sc = new Scanner(System.in);</code>：从控制台读取用户输入。</li>\n<li><code>IController controller = new TextController(model, view, sc);</code>：组装 MVC 三要素。</li>\n<li><code>controller.start();</code>：启动控制器，程序进入循环运行。</li>\n</ol>\n<p>运行该 <code>main</code> 方法后，您可以在控制台依照提示输入指令来操作模型的字符串。</p>\n<h2>Stage 5: 初识 GUI（不太好的写法示例）</h2>\n<p>下面我们开始引入图形界面（GUI）。先做一个“坏设计但能运行”的简单版本，让大家看到最基本的 Swing 用法。这个版本会让“视图”直接持有并修改 <code>Model</code>，从而破坏了 MVC 的解耦原则，但能让我们先快速见识到 Swing 编程的主要元素：<code>JFrame</code>, <code>JLabel</code>, <code>JButton</code>, <code>JTextField</code> 等。</p>\n<h3>1. 简易的 GUI View（不推荐写法）</h3>\n<ul>\n<li><strong>代码名称</strong>：<code>JFrameView.java</code></li>\n<li><strong>功能</strong>：创建一个窗口 (<code>JFrame</code>)，里面含有一个输入框、两个按钮和一个标签；当点击按钮时，直接操作 <code>Model</code>。</li>\n</ul>\n<div class=\"language-java line-numbers-mode has-collapsed-lines collapsed\" data-highlighter=\"shiki\" data-ext=\"java\" style=\"--vp-collapsed-lines:15;--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-java\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">import</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> javax.swing.</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">*</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">;</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">import</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> java.awt.</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">*</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">;</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">import</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> java.awt.event.ActionEvent</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">;</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">import</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> java.awt.event.ActionListener</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">;</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">public</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> class</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> JFrameView</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> extends</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> JFrame</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> implements</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> ActionListener</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">  private</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> final</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> IModel</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\"> model</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">;</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">  private</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> final</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> JLabel</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\"> display</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">;</span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">      // 用于显示文本</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">  private</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> final</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> JTextField</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\"> input</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">;</span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">    // 用户输入的文本框</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">  private</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> final</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> JButton</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\"> echoButton</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">;</span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">  // Echo 按钮</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">  private</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> final</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> JButton</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\"> exitButton</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">;</span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">  // Exit 按钮</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">  public</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> JFrameView</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">String</span><span style=\"--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\"> caption</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">IModel</span><span style=\"--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\"> model</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">    super</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(caption);</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">    this</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">model</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> =</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> model;</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">    this</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">setLayout</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">new</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> FlowLayout</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">());</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">    // Label</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    display </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> new</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> JLabel</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"初始状态\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">);</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">    this</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">add</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(display);</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">    // TextField</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    input </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> new</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> JTextField</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">10</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">); </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">// 宽度10列</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">    this</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">add</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(input);</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">    // Echo 按钮</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    echoButton </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> new</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> JButton</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"Echo\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">);</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">    echoButton</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">setActionCommand</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"Echo Button\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">);</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">    echoButton</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">addActionListener</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">this</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">);   </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">// 直接由自己处理监听</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">    this</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">add</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(echoButton);</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">    // Exit 按钮</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    exitButton </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> new</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> JButton</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"Exit\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">);</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">    exitButton</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">setActionCommand</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"Exit Button\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">);</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">    exitButton</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">addActionListener</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">this</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">);</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">    this</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">add</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(exitButton);</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">    this</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">pack</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">();           </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">// 让布局生效</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">    this</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">setVisible</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">true</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">); </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">// 显示窗口</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">    this</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">setDefaultCloseOperation</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">JFrame</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">EXIT_ON_CLOSE</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">);</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">  }</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">  @</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#E5C07B\">Override</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">  public</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> void</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> actionPerformed</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">ActionEvent</span><span style=\"--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\"> e</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    switch</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> (</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">e</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">getActionCommand</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()) {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">      case</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> \"Echo Button\"</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">        // 直接修改 model</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">        model</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">setString</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">input</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">getText</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">());</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">        display</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">setText</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">model</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">getString</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">());</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        break</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">;</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">      case</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> \"Exit Button\"</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">        System</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">exit</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">0</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">);</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        break</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">;</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">      default:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">        // do nothing</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    }</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">  }</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">}</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div><div class=\"collapsed-lines\"></div></div><p><strong>代码逐行注释</strong>：</p>\n<ol>\n<li><code>extends JFrame implements ActionListener</code>：让类本身既是一个窗口，又直接处理按钮点击事件。</li>\n<li><code>this.setLayout(new FlowLayout());</code>：使用流式布局，让控件依次放置。</li>\n<li>创建 <code>JLabel</code>, <code>JTextField</code>, 两个 <code>JButton</code>，并将它们添加到框架中。</li>\n<li><code>echoButton.setActionCommand(\"Echo Button\");</code>：设置按钮的“命令字符串”，后面在 <code>actionPerformed</code> 里区分。</li>\n<li><code>echoButton.addActionListener(this);</code>：将当前对象本身作为监听器。</li>\n<li>在 <code>actionPerformed</code> 中，通过 <code>switch</code> 判断是哪个按钮被点击：\n<ul>\n<li><code>\"Echo Button\"</code>：把输入框的内容写入模型，再将模型里的新值更新到标签显示。</li>\n<li><code>\"Exit Button\"</code>：退出程序。</li>\n</ul>\n</li>\n</ol>\n<h3>2. 启动这个不推荐的 GUI</h3>\n<ul>\n<li><strong>代码名称</strong>：<code>MainBadGUI.java</code></li>\n</ul>\n<div class=\"language-java line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"java\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-java\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">public</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> class</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> MainBadGUI</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">  public</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> static</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> void</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> main</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">String</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">[] </span><span style=\"--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">args</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">    IModel</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\"> model</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> =</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> new</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> Model</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">();</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">    // 直接把 Model 传给 View，违反了解耦原则，但可用</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">    JFrameView</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\"> view</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> =</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> new</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> JFrameView</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"Bad GUI Demo\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, model);</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">  }</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">}</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>这样就能弹出一个窗口，点击 Echo 会直接改模型，点击 Exit 会关闭程序。</p>\n<h2>Stage 6: 解耦 View 与 Model</h2>\n<p>为了让我们的 MVC 架构更清晰，我们希望视图<strong>不要</strong>直接调用 <code>model.setString</code>。而是把对模型的修改统一交给 Controller 来处理。</p>\n<p>思路：</p>\n<ol>\n<li><strong>View</strong> 不再持有 <code>model</code>；只提供获取文本、显示文本等方法。</li>\n<li><strong>Controller</strong> 拥有 <code>model</code> 和 <code>view</code>，并把自己注册给 <code>view</code>，让 <code>view</code> 把事件再转给 <code>controller</code>。</li>\n</ol>\n\n<p><strong>Controller 说明</strong>：</p>\n<ul>\n<li>\n<p>现在 <code>JFrameView</code> 不再直接操作 <code>model</code>，而是把按钮的点击事件通过 <code>ActionListener</code> 转给 <code>Controller</code>。</p>\n</li>\n<li>\n<p><code>Controller</code> 持有 <code>model</code>，因此可以安全地进行 <code>model.setString(...)</code>，然后再告诉 <code>view</code> 更新界面。</p>\n</li>\n</ul>\n<h3>1. 报错解决方案</h3>\n<p>回顾我们在<strong>文本版</strong>和<strong>图形版</strong>的示例时，会发现两套 <code>IView</code>/<code>View</code> 的接口和实现不同：</p>\n<ul>\n<li><strong>文本版 IView</strong> 通常会有 <code>showMessage(...)</code>、<code>showError(...)</code> 方法。</li>\n<li><strong>图形版 IView</strong> 在最简化的设计中，只有比如 <code>getInputString()</code>、<code>clearInputString()</code>、<code>setEchoOutput()</code>、<code>display()</code> 等方法，可能<strong>并未</strong>包含 <code>showMessage(...)</code>。</li>\n</ul>\n<p>如果你的<strong>控制器</strong>里还保留了对 <code>view.showMessage(...)</code> 的调用（大概率是从文本版代码沿用过来的），那就会和新的图形版 <code>IView</code> 接口冲突，编译时报错。</p>\n<h3>2. 解决思路</h3>\n<h4>2.1 方案 1：在图形版 <code>IView</code> 中补充 <code>showMessage(...)</code> 方法</h4>\n\n<p><strong>IView 要点</strong>：</p>\n<ul>\n<li>新增了 <code>showMessage(String msg)</code> 和 <code>showError(String err)</code> 这两个方法。</li>\n<li>其他方法（如 <code>getInputString()</code>, <code>setEchoOutput()</code> 等）保持原状。</li>\n</ul>\n",
      "image": "https://bornforthis.cn/gzh.jpg",
      "date_published": "2025-03-05T23:22:59.000Z",
      "date_modified": "2025-04-10T23:49:50.000Z",
      "authors": [
        {
          "name": "AI悦创"
        }
      ],
      "tags": []
    },
    {
      "title": "开篇词｜借 DeepSeek 东风，开启 AI 应用开发之旅",
      "url": "https://bornforthis.cn/column/DeepSeek-Application-Development-Practical-Guide/00.html",
      "id": "https://bornforthis.cn/column/DeepSeek-Application-Development-Practical-Guide/00.html",
      "summary": "你好，我是悦创。 不知道大家 2025 年过得怎么样？反正我是没怎么过好，春节开始就忙得很。起因就是 DeepSeek 这货在春节前突然就成了网红了。红到什么程度呢？过年走亲戚，听到最多的就是俩词——哪吒和 DeepSeek。连我 58 岁的大爷都在问我，悦创啊，你说抖音剪视频是不是也能用 “第普谁课” 啊？听得我人都麻了。 这热度，你说领导能坐得住？...",
      "content_html": "<figure><figcaption></figcaption></figure>\n<p>你好，我是悦创。</p>\n<p>不知道大家 2025 年过得怎么样？反正我是没怎么过好，春节开始就忙得很。起因就是 DeepSeek 这货在春节前突然就成了网红了。红到什么程度呢？过年走亲戚，听到最多的就是俩词——哪吒和 DeepSeek。连我 58 岁的大爷都在问我，悦创啊，你说抖音剪视频是不是也能用 “第普谁课” 啊？听得我人都麻了。</p>\n<p>这热度，你说领导能坐得住？于是整个春节，都在忙着做规划，布局 DeepSeek。然后春节之后，各云厂商就纷纷宣布自己的平台支持 DeepSeek 了，而且我的老东家“浪潮”和现任东家“联通云”都先后推出了 DeepSeek 一体机，很受政企客户欢迎。这让我想起了《飞驰人生 2》里贾冰的一句台词，“过年的时候啊，像什么法拉顺利啊，保时敏捷啊，黄博基尼啊，哎呀，疯抢啊”。</p>\n<figure><figcaption></figcaption></figure>\n<p>这热度，你还坐得住吗？是不是也想跑步入场，学习一下 AI ，拥抱一下 DeepSeek 呢？然而我们自己去摸索相关资料时，可能很快就会被一堆专业名词、机器学习算法的深奥知识劝退。看着 AIGC 一浪高过一浪的新技术涌现，就是不知道自己如何投身其中。</p>\n<p>对于这个问题，这里我想给你分享一下我的一些经历。</p>\n<h2>一点感悟</h2>\n<p>事实上，我们知道，DeepSeek 爆火是今年春节前后的事情，DeepSeek 模型能力强，还开源，直接让国人的 AI 热情空前高涨，极大推动了国内应用 AI 化的发展进程。2025 年，绝对将会是 AI 应用发展的革命年，用不了多久，AI 旋风就会席卷到各个行业。</p>\n<p>我在差不多两年前，GPT 模型刚刚发布时，就开始投身到 AI 应用开发的实践中，那个时候，没有 LangChain，没有 Agent，也没有 RAG，大家就是琢磨着如何在提示词上做文章，去完成传统应用做不到的事情。</p>\n<p>比如，在当时，我就考虑如何用 AI 重塑 K8s 管理系统，让用户可以用自然语言去操作 K8s 资源，而不是在传统 UI 上点点点。我的思路是在模板中预置了一些规则以及挖了空的 API，比如 <code>GET /v1/{resourceName}/{Namespace}</code>，之后让大模型根据用户输入的 prompt 去填空，比如用户说：帮我查询 default 命名空间下的 pod，大模型就会把上面的 API 组装成 <code>GET /v1/pods/default</code>，此时后端便可以调用这条 API，拿到资源了。</p>\n<p>这种方法在当时很新鲜，但在出了 Function Calling 以及 Agent 技术后，便迅速被淘汰了。像这样的案例还有很多，很多 AI 开发者都是在技术不断地发展中，摸爬滚打前行。</p>\n<p>直到去年中旬之后，基本上 AI 应用开发的路线开始进入了一个相对稳定的阶段，核心的两大技术就是 Agent 与 RAG，具体实现方式则有很多框架做支撑，但其实都是殊途同归。此时制约应用实现效果的瓶颈便是大模型的能力了，作为国内开发者，除了部分出海项目可以使用 GPT 模型外，大多数项目受制于国内大模型的能力问题，只能做的差强人意。</p>\n<p>但随着 DeepSeek 系列模型的发布，国内终于有了一款能够比肩 GPT 的模型，这使得很多优秀的开发框架和技术也能够站在巨人的肩膀上，发挥出更好的作用。</p>\n<p>因此，我希望出一套课程，<strong>深刻挖掘一下 DeepSeek 在应用开发中的能力，同时在课程中使用目前最主流的 AI 应用开发思想、套路、工具以及框架</strong>。对于 AI 开发老鸟，可以与时俱进，查漏补缺，掌握业界前沿的开发思想和工具；而对于 AI 开发新手，则可以绕过过去几年我摸爬滚打的弯路，借力 DeepSeek，快速入门 AI 应用开发领域。</p>\n<h2>课程设计</h2>\n<p>为此，我将课程划分成了一个前置章节和五个正式章节。</p>\n<figure><figcaption></figcaption></figure>\n<p>前置课程里，我想和绝大多数像我一样的“民用级”程序员聊聊天，一起探讨一下在 DeepSeek 如此火爆的背景下，应该如何入场，以及入场上有哪些可探索的方向。之后还会学习做 AI 应用开发不可或缺的 Agent 技术。</p>\n<p>第一章，我会为揭秘云厂商针对不同的客户群体，<strong>私有化部署 DeepSeek 的几种不同方案</strong>。包括单卡的量化版部署、多卡的高可用负载均衡方案、多卡的分布式部署方案以及在消费级硬件，比如纯 CPU 上部署 DeepSeek 的方案等等。最后我们还会体验一下如何微调和蒸馏 R1 大模型。</p>\n<p>第二章我们将会一起<strong>打造一个求职助手</strong>。求职找工作写简历，是我们每个职场人都经历过的事情。那我们是否可以告别传统肉眼搜索职位，手工写简历的方式呢？</p>\n<p>DeepSeek 的深度思考能力以及超强的写作能力，给了我们启发。这个项目不使用 Agent，而是会采用去年 9 月份，Anthropic 公司（Claude 模型的母公司）推出的**模型上下文协议（MCP）**来实现。通过 MCP，可以让大模型连接本地文件系统、数据库、调用工具等等。</p>\n<p>第三章我们来<strong>实现一个 AI 版的“作业帮”</strong>，这个项目是聚焦 DeepSeek 的又一大出色能力——数学理解力。我们从“作业帮”项目切入，一起学习<strong>多模态、RAG</strong> 等热点技术。除此之外，这个项目采用了 AI 开发的另一种思想——平台化开发，可以零代码构建出 Agent 与工作流。搭配平台的 API，实现自然语言前端、Agent 和工具的分离。</p>\n<p><strong>第四章我们来实现一个智能编程助手</strong>。代码能力是 DeepSeek 的亮点之一，目前已经有多个智能编程软件宣布接入了 DeepSeek。所以这个项目我们不打算重复造轮子，而是要以构建 Golang 的 Web 后端项目为例，带你掌握如何让 AI 稳定生成固定项目代码风格的代码。这个项目会使用目前非常热门的 LangGraph 框架完成。</p>\n<p><strong>第五章我们来探索一下 AI 与金融领域的结合</strong>。DeepSeek 的母公司幻方量化是一家著名金融量化公司。因此 DeepSeek 在训练数据集上必然也会有很多的金融领域相关数据做支撑，所以用 DeepSeek 做金融项目，会有先天优势。</p>\n<p>此外，最近一年内，好几个知名大模型厂商和平台都举办了以金融为主题的 AI 大赛，旨在探索行业解决方案以及挖掘既懂业务又懂技术的人才。所以这一章我们就以 A 股市场为主题，做一下探索性的开发，包括股票名称代码查询、数据分析统计、简单量化策略等。</p>\n<p>你会发现，整个课程几乎都是以内容紧凑的实践课程组成的，且每个项目都聚焦了 DeepSeek 模型的某个特点。整门课程的交付目标就是，为你提炼 DeepSeek 应用开发的核心经验，帮助你提升 AI 应用开发的工程化能力。</p>\n<p>欢迎你和我一起学习讨论，让我们开始行动起来吧！</p>\n<figure><figcaption></figcaption></figure>\n<details class=\"hint-container details\"><summary>详情</summary>\n<p>我是一家大型银行的科技条线基层工作者，今年来了之后，我也是真的能感受到从上之下的公司内部开始非常重视AI、大模型的应用。 我自己也觉得这对于个人也是一个机会，一定要努力过才不会后悔。 希望大家都参与进来，一起努力构建一个好课</p>\n<blockquote>\n<p>作者回复: 感谢同学支持，用习主席的话来说，这就是百年未有之大变局啊</p>\n</blockquote>\n</details>\n<details class=\"hint-container details\"><summary>公众号：AI悦创【二维码】</summary>\n<figure><img src=\"/gzh.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n</details>\n<div class=\"hint-container info\">\n<p class=\"hint-container-title\">AI悦创·编程一对一</p>\n<p>AI悦创·推出辅导班啦，包括「Python 语言辅导班、C++ 辅导班、java 辅导班、算法/数据结构辅导班、少儿编程、pygame 游戏开发、Linux、Web、Sql」，全部都是一对一教学：一对一辅导 + 一对一答疑 + 布置作业 + 项目实践等。当然，还有线下线上摄影课程、Photoshop、Premiere 一对一教学、QQ、微信在线，随时响应！微信：Jiabcdefh</p>\n<p>C++ 信息奥赛题解，长期更新！长期招收一对一中小学信息奥赛集训，莆田、厦门地区有机会线下上门，其他地区线上。微信：Jiabcdefh</p>\n<p>方法一：<a href=\"http://wpa.qq.com/msgrd?v=3&amp;uin=1432803776&amp;site=qq&amp;menu=yes\" target=\"_blank\" rel=\"noopener noreferrer\">QQ</a></p>\n<p>方法二：微信：Jiabcdefh</p>\n</div>\n<figure><img src=\"/zsxq.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n",
      "date_published": "2025-03-04T21:58:22.000Z",
      "date_modified": "2025-04-10T23:49:50.000Z",
      "authors": [
        {
          "name": "AI悦创"
        }
      ],
      "tags": []
    },
    {
      "title": "DeepSeek 应用开发实战",
      "url": "https://bornforthis.cn/column/DeepSeek-Application-Development-Practical-Guide/",
      "id": "https://bornforthis.cn/column/DeepSeek-Application-Development-Practical-Guide/",
      "summary": "你将获得 掌握 DeepSeek 模型使用、部署与应用方案 实战演练，基于 DeepSeek 开发四大 AI 项目 DeepSeek、RAG、LangGraph 等前沿技术速递 举一反三，提升 AI 应用开发工程化能力 课程介绍 随着 DeepSeek 系列模型的发布，国内终于有了一款能够比肩 GPT 的模型，这将极大推动国内应用 AI 化的发展进程。...",
      "content_html": "<h2>你将获得</h2>\n<ul>\n<li>掌握 DeepSeek 模型使用、部署与应用方案</li>\n<li>实战演练，基于 DeepSeek 开发四大 AI 项目</li>\n<li>DeepSeek、RAG、LangGraph 等前沿技术速递</li>\n<li>举一反三，提升 AI 应用开发工程化能力</li>\n</ul>\n<h2>课程介绍</h2>\n<p>随着 DeepSeek 系列模型的发布，国内终于有了一款能够比肩 GPT 的模型，这将极大推动国内应用 AI 化的发展进程。2025 年 AI 应用发展的步伐会变得更快。</p>\n<p>无论是否是计算机或 AI 专业出身，每个人都有机会在 AIGC 浪潮中找到自己的位置。为了帮助你与时俱进，快速拥抱 DeepSeek 等前沿技术，我们邀请了 AI悦创开设这门课程，带你学习<strong>如何基于 DeepSeek，综合提升自己的 AI 应用开发工程化能力。</strong></p>\n<p>本课程将会涉及当前业界**最主流的 AI 应用开发思想、套路、工具以及框架，设计的实战项目也会聚焦 DeepSeek 模型的某个特点。**对于 AI 开发老鸟，可以与时俱进，查漏补缺，掌握业界前沿的开发思想和工具；而对于 AI 开发新手，则可以绕过过去几年我摸爬滚打的弯路，借力 DeepSeek，快速入门 AI 应用开发领域。</p>\n<p>课程分为六个章节，具体设计思路如下：</p>\n<figure><figcaption></figcaption></figure>\n<p>**前置课程：**探讨普通程序员如何使用和学习 DeepSeek，有哪些探索方向，并学习 AI 应用开发不可或缺的 Agent 技术。</p>\n<p>**第一章：**揭秘云厂商针对不同的客户群体，私有化部署 DeepSeek 的几种不同方案。包括单卡的量化版部署、多卡的高可用负载均衡方案、多卡的分布式部署方案以及在消费级硬件，比如纯 CPU 上部署 DeepSeek 的方案等等。最后还将体验如何微调和蒸馏 R1 大模型。</p>\n<p>**第二章：**利用 DeepSeek 的深度思考能力以及超强的写作能力，开发一个求助助手。本项目还会引入模型上下文协议（MCP）来让模型连接本地文件系统、数据库、调用工具等等。</p>\n<p>**第三章：**利用 DeepSeek 出色的数学理解力，用平台化开发的方式，构建一个 AI 版“作业帮”，该项目还将涉及多模态、RAG、工作流等热点技术。</p>\n<p>**第四章：**代码能力是 DeepSeek 的亮点之一，目前已经有多个智能编程软件宣布接入了 DeepSeek。所以这个项目我们不打算重复造轮子，而是以构建 Golang 的 Web 后端项目为例，利用目前非常热门的 LangGraph 框架，让 AI 稳定生成固定项目代码风格的代码。</p>\n<p>**第五章：**探索 AI 与金融领域的结合，我们将以 A 股市场为主题，做一下探索性的开发，包括股票名称代码查询、数据分析统计、简单量化策略等。</p>\n<p>课程代码库（随上线进度动态更新）：<a href=\"https://github.com/AndersonHJB/BornforthisData\" target=\"_blank\" rel=\"noopener noreferrer\">https://github.com/AndersonHJB/BornforthisData</a></p>\n<figure><figcaption></figcaption></figure>\n<details class=\"hint-container details\"><summary>公众号：AI悦创【二维码】</summary>\n<figure><img src=\"/gzh.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n</details>\n<div class=\"hint-container info\">\n<p class=\"hint-container-title\">AI悦创·编程一对一</p>\n<p>AI悦创·推出辅导班啦，包括「Python 语言辅导班、C++ 辅导班、java 辅导班、算法/数据结构辅导班、少儿编程、pygame 游戏开发、Linux、Web、Sql」，全部都是一对一教学：一对一辅导 + 一对一答疑 + 布置作业 + 项目实践等。当然，还有线下线上摄影课程、Photoshop、Premiere 一对一教学、QQ、微信在线，随时响应！微信：Jiabcdefh</p>\n<p>C++ 信息奥赛题解，长期更新！长期招收一对一中小学信息奥赛集训，莆田、厦门地区有机会线下上门，其他地区线上。微信：Jiabcdefh</p>\n<p>方法一：<a href=\"http://wpa.qq.com/msgrd?v=3&amp;uin=1432803776&amp;site=qq&amp;menu=yes\" target=\"_blank\" rel=\"noopener noreferrer\">QQ</a></p>\n<p>方法二：微信：Jiabcdefh</p>\n</div>\n<figure><img src=\"/zsxq.jpg\" alt=\"\" tabindex=\"0\" loading=\"lazy\"><figcaption></figcaption></figure>\n",
      "date_published": "2025-03-04T21:28:26.000Z",
      "date_modified": "2025-04-10T23:49:50.000Z",
      "authors": [
        {
          "name": "AI悦创"
        }
      ],
      "tags": []
    },
    {
      "title": "GenAI with Python：Build Agents from Scratch (Complete Tutorial)",
      "url": "https://bornforthis.cn/blog/2025/Other/20-genai-with-python-build-agents-from-scratch-complete-tutorial.html",
      "id": "https://bornforthis.cn/blog/2025/Other/20-genai-with-python-build-agents-from-scratch-complete-tutorial.html",
      "summary": "with Ollama, LangChain, LangGraph (No GPU, No APIKEY) Intro Prompt Engineering is the practice of designing and refining prompts (text inputs) to enhance the behavior of Large L...",
      "content_html": "<blockquote>\n<p>with Ollama, LangChain, LangGraph (No GPU, No APIKEY)</p>\n</blockquote>\n<figure><figcaption></figcaption></figure>\n<h2>Intro</h2>\n<p><strong>Prompt Engineering</strong> is the practice of designing and refining prompts (text inputs) to enhance the behavior of Large Language Models (LLMs). The goal is to get the desired responses from the model by carefully crafting the instructions. The most used prompting techniques are:</p>\n<ul>\n<li><strong>Chain-of-Thought:</strong> involves generating a step-by-step reasoning process to reach a conclusion. The model is pushed to “think out loud” by explicitly laying out the logical steps that lead to the final answer.</li>\n<li><strong>ReAct</strong> <strong>(Reason+Act):</strong> combines reasoning with action. The model not only thinks through a problem but also takes actions based on its reasoning. So it’s more interactive as the model alternates between reasoning steps and actions, refining its approach iteratively. Basically, it’s a loop of “thought”, “action”, “observation”.</li>\n</ul>\n<blockquote>\n<p>Let’s make an example: imagine asking an AI to “find the best laptop under $1000”.</p>\n<ul>\n<li>\n<p><strong>Normal Answer</strong>: “Lenovo Thinkpad”.</p>\n</li>\n<li>\n<p><strong>Chain-of-Thought Answer</strong>: “I need to consider factors like performance, battery life, and build quality. Then, I would check which laptops are priced under $1000. According to my knoweldge base, the Lenovo Thinkpad is the best”.</p>\n</li>\n<li>\n<p><strong>ReAct Answer</strong>: Same as the Chain-of-Thought Answer + the Action of performing a web-search for “best laptops under $1000 in 2024” and analyze the results (which might not be “Lenovo Thinkpad”).</p>\n</li>\n</ul>\n</blockquote>\n<p>Agents are created using the ReAct technique, so the main difference with LLMs is the <strong>ability to take action</strong>. Agents are AI systems designed to process sequential reasoning, with the option of executing external tools (i.e. database query, web search) in case the LLM’s general-purpose knowledge isn’t enough. To put it simply, a normal AI Chatbot generates random text when it doesn’t know how to answer a question, but an Agent activates its tools to fill the gap and give a specific response.</p>\n<p>In this tutorial, I’m going to build from scratch a multi-agent system with human-in-the-loop. I will present some useful Python code that can be easily applied in other similar cases (just copy, paste, run) and walk through every line of code with comments so that you can replicate this example (link to the full code below).</p>\n<p><a href=\"https://github.com/AndersonHJB/BornforthisData\" target=\"_blank\" rel=\"noopener noreferrer\">https://github.com/AndersonHJB/BornforthisData</a></p>\n<p>In particular, I will go through:</p>\n<ul>\n<li><strong>Setup</strong> of the env and the LLM</li>\n<li><strong>Tools</strong> with <em>LangChain</em></li>\n<li><strong>Decision Making</strong> with <em>Ollama</em></li>\n<li><strong>Agent Structure</strong> with <em>Pydantic</em></li>\n<li><strong>Graph Workflow</strong> with <em>LangGraph</em></li>\n<li><strong>Multi-Agent &amp; Human-in-the-Loop</strong></li>\n</ul>\n<h2>Setup</h2>\n<p>At the moment, there are 2 libraries for LLMs and Agents that are trying to become the main framework in the market:</p>\n<ul>\n<li><a href=\"https://www.langchain.com/\" target=\"_blank\" rel=\"noopener noreferrer\"><em>LangChain</em> </a>— <strong>ideal for building large-scale LLM-powered apps that require complex interactions and workflows</strong>. It provides a comprehensive set of tools, focusing on creating complex workflows. It’s based on a “chain of components”, allowing different processing steps, where each step can involve different LLMs. <em>LangChain</em> has a specific module for complex multi-Agent systems: <a href=\"https://www.langchain.com/langgraph\" target=\"_blank\" rel=\"noopener noreferrer\"><em>LangGraph</em></a></li>\n<li><a href=\"https://docs.llamaindex.ai/en/stable/\" target=\"_blank\" rel=\"noopener noreferrer\"><em>LLamaIndex</em> </a>— <strong>suited for applications that prioritize search and retrieval capabilities, particularly for large datasets</strong>. It focuses on ingesting, structuring, and accessing domain-specific data in a way that is optimized for consumption by LLMs. It is designed for speed and accuracy in data retrieval, making it suitable for applications that require quick access to large volumes of data. Also <em>LlamaIndex</em> has its Agents module: <a href=\"https://github.com/run-llama/llama_deploy\" target=\"_blank\" rel=\"noopener noreferrer\"><em>Llama-Agents</em></a></li>\n</ul>\n<p>I shall use the former as it’s more flexible. By installing <em>LangChain</em> (<code>pip install langchain</code>) you will gain access to all the <a href=\"https://python.langchain.com/v0.2/docs/concepts/\" target=\"_blank\" rel=\"noopener noreferrer\">modules</a>.</p>\n<ol>\n<li><em>langchain:</em> the main package containing chains, Agents, and retrieval strategies</li>\n<li><em>langchain-core:</em> has the base abstractions (like LLMs, vector stores, retrievers) used in <em>langchain</em> package</li>\n<li><em>langchain-community:</em> third-party integrations that are maintained by the community</li>\n<li><em>langchain-experimental</em>: containing dangerous stuff (i.e. tools allowing Agents to execute code)</li>\n<li>Partner packages like <em>langchain-openai</em>, <em>langchain-anthropic</em></li>\n<li>Tools for deployment like <a href=\"https://python.langchain.com/v0.2/docs/langserve/\" target=\"_blank\" rel=\"noopener noreferrer\"><em>LangServe</em></a> and <a href=\"https://www.langchain.com/langsmith\" target=\"_blank\" rel=\"noopener noreferrer\"><em>LangSmith</em></a></li>\n</ol>\n<p>Additionally, I’m going to install <em>LangGraph</em> (<code>pip install langgraph</code>) for building Agents using a node-edges style of workflow.</p>\n<figure><figcaption></figcaption></figure>\n<p>I will run my LLM locally using <a href=\"https://ollama.com/\" target=\"_blank\" rel=\"noopener noreferrer\"><strong>Ollama</strong></a> (<code>pip install ollama</code>) and I shall pick Meta’s <a href=\"https://ollama.com/library/llama3.1\" target=\"_blank\" rel=\"noopener noreferrer\"><em>Llama 3.1</em></a> because it’s the smartest LLM that you can run without GPUs.</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">import</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> ollama</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">llm </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> \"llama3.1\"</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">q </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> '''who died on September 9, 2024?'''</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">res </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> ollama.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">chat</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">model</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">llm, </span></span>\n<span class=\"line\"><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">                  messages</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">[{</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"role\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"system\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"content\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">},</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">                            {</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"role\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"user\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"content\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:q}])</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">res</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><figure><figcaption></figcaption></figure>\n<p>As expected, the LLM knowledge is limited to the date of its last training. Please note that there are <strong>3 roles</strong> in the interaction with a LLM chatbot:</p>\n<ul>\n<li><em>“role”:“system”</em> — used to pass core instructions to the model on how the conversation should proceed</li>\n<li><em>“role”:“user”</em>— used for user’s questions</li>\n<li><em>“role”:“assistant”</em> — it’s the reply from the model</li>\n</ul>\n<h2>Tools</h2>\n<p>One of the most common tools is the ability to <strong>search the Internet</strong>. In Python, the easiest way to do it is with the famous private browser <a href=\"https://pypi.org/project/duckduckgo-search/\" target=\"_blank\" rel=\"noopener noreferrer\"><em>DuckDuckGo</em></a> (<code>pip install duckduckgo-search</code>).</p>\n<p>Since I’m using <em>Ollama</em>, there are two options for creating a tool. First, with the standard decorator from <em>LangChain</em> (this is the most frequently used).</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">from</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> langchain_core.tools </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">import</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> tool</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">from</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> langchain_community.tools </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">import</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> DuckDuckGoSearchRun</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">@tool</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"tool_browser\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> tool_browser</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">q</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> str</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">) -&gt; </span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">str</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    \"\"\"Search on DuckDuckGo browser by passing the input `q`\"\"\"</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> DuckDuckGoSearchRun</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">().</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">run</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(q)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># test</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">( </span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">tool_browser</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(q) )</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><figure><figcaption></figcaption></figure>\n<p>Second, by creating a normal function and turning it into an <em>Ollama</em> schema with <a href=\"https://github.com/aurelio-labs/semantic-router\" target=\"_blank\" rel=\"noopener noreferrer\"><em>Semantic Router</em></a> (<code>pip install semantic-router</code>), a library to simplify tool-making.</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">from</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> semantic_router.utils.function_call </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">import</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> FunctionSchema</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> browser</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">q</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">str</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">) -&gt; </span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">str</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    \"\"\"Search on DuckDuckGo browser by passing the input `q`\"\"\"</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> DuckDuckGoSearchRun</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">().</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">run</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(q)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">tool_browser </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> FunctionSchema</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(browser).</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">to_ollama</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">tool_browser</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><figure><figcaption></figcaption></figure>\n<p>Among the tools, we shall also include the <strong>final answer</strong>: after every question from the user, the Agent must decide whether to use a tool or give the final answer. Please note that the more specific you describe the answer structure, the better it works.</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">@tool</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"final_answer\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> final_answer</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">text</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">str</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">) -&gt; </span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">str</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    \"\"\"Returns a natural language response to the user by passing the input `text`. </span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    You should provide as much context as possible and specify the source of the information.</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">    \"\"\"</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> text</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><h2>Decision Making</h2>\n<p>We need to do some <strong>Prompt Engineering</strong> to define what the Agent must do and how.</p>\n<div class=\"language-python line-numbers-mode has-collapsed-lines collapsed\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--vp-collapsed-lines:15;--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">prompt </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> \"\"\"</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">You know everything, you must answer every question from the user, you can use the list of tools provided to you.</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">Your goal is to provide the user with the best possible answer, including key information about the sources and tools used.</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">Note, when using a tool, you provide the tool name and the arguments to use in JSON format. </span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">For each call, you MUST ONLY use one tool AND the response format must ALWAYS be in the pattern:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">```json</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">{\"name\":\"&lt;tool_name&gt;\", \"parameters\": {\"&lt;tool_input_key&gt;\":&lt;tool_input_value&gt;}}</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">```</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">Remember, do NOT use any tool with the same query more than once.</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">Remember, if the user doesn't ask a specific question, you MUST use the `final_answer` tool directly.</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">Every time the user asks a question, you take note of some keywords in the memory.</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">Every time you find some information related to the user's question, you take note of some keywords in the memory.</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">You should aim to collect information from a diverse range of sources before providing the answer to the user. </span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">Once you have collected plenty of information to answer the user's question use the `final_answer` tool.</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"\"\"</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div><div class=\"collapsed-lines\"></div></div><p>Using <em>Ollama</em>, we can test the decision-making process of the Agent right away. We need to tell the Agent what tools are available to use.</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">dic_tools </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"tool_browser\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:tool_browser, </span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">             \"final_answer\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:final_answer}</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">str_tools </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> \"</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">\\n</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">join</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">([</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">str</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(n</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\". `\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">str</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(v.name)</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"`: \"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">str</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(v.description) </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> n,v </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> enumerate</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(dic_tools.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">values</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">())])</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">prompt_tools </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> f</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"You can use the following tools:</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">\\n</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">{</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">str_tools</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">}</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(prompt_tools)</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><figure><figcaption></figcaption></figure>\n<p>The prompt and the tools, combined with the LLM, define the core of the Agent. At this point, our AI should be able to decide what to do. For instance, if I don’t ask any question, it should go directly for the final answer.</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># LLM deciding what tool to use</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">from</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> pprint </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">import</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> pprint</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">llm_res </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> ollama.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">chat</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">    model</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">llm,</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">    messages</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">[{</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"role\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"system\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"content\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:prompt</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">\\n</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">prompt_tools},</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">              {</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"role\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"user\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"content\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"hello\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">}</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">             ], </span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">format</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"json\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">pprint</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(llm_res)</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><figure><figcaption></figcaption></figure>\n<p>Inversely, when I ask something specific, the Agent should use the web-search tool and generate the input query for it, based on my request.</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># LLM deciding what tool to use (output format = json)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">llm_res </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> ollama.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">chat</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">    model</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">llm,</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">    messages</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">[{</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"role\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"system\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"content\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:prompt</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">\\n</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">prompt_tools},</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">              {</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"role\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"user\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"content\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:q}</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">             ], </span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">format</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"json\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">llm_res[</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"message\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">][</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"content\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><figure><figcaption></figcaption></figure>\n<p>We can check how the Agent processes the result of the query, by passing it as the context for the LLM.</p>\n<div class=\"language-python line-numbers-mode has-collapsed-lines collapsed\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--vp-collapsed-lines:15;--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># LLM with context</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">import</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> json</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">tool_input </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> json.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">loads</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(llm_res[</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"message\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">][</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"content\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">])[</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"parameters\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">][</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"q\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">context </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> tool_browser</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(tool_input)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"tool output:</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">\\n</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, context)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">llm_output </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> ollama.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">chat</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">    model</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">llm,</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">    messages</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">[{</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"role\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"system\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"content\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"Give the most accurate answer using the folling information:</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">\\n</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">context},</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">              {</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"role\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"user\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"content\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:q}</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">             ])</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">\\n</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">llm output:</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">\\n</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, llm_output[</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"message\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">][</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"content\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">])</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div><div class=\"collapsed-lines\"></div></div><figure><figcaption></figcaption></figure>\n<p>It’s confirmed that the core model works. But, sometimes LLMs can generate incorrect and inconsistent content (so called “hallucinations”), therefore it’s common practice to specify the data structure that the model must follow.</p>\n<h2>Agent Structure</h2>\n<p>Generally, LLMs work with API calls, so both input and output must follow a specific <strong>Data Structure</strong>. In Python, the most widely used library for data validation is <a href=\"https://docs.pydantic.dev/latest/\" target=\"_blank\" rel=\"noopener noreferrer\"><em>Pydantic</em></a>: it makes sure the information your program uses is in the right format and has the right values.</p>\n<p>Basically, the goal is to transform the LLM response, which is not “stable”, into an Agent response, a structured and validated object.</p>\n<figure><figcaption></figcaption></figure>\n<p>To start, you create a class that describes the data you want, including its type and any rules it must follow. <em>Pydantic</em> checks if the data is correct, and if not, it gives you a clear error message. That is particularly useful because responses from the LLM can vary after each run.</p>\n<div class=\"language-python line-numbers-mode has-collapsed-lines collapsed\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--vp-collapsed-lines:15;--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">from</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> pydantic </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">import</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> BaseModel </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">#this is the standard class</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># Taking for example the last LLM response, I want this structure:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># {tool_name: 'tool_browser', </span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">#  tool_input: {'q':'September 9 2024 deaths'}, </span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">#  tool_output: str( tool_browser({'q':'September 9 2024 deaths'})) }</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">class</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> AgentRes</span><span style=\"--shiki-light:#C18401;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">BaseModel</span><span style=\"--shiki-light:#C18401;--shiki-dark:#ABB2BF\">)</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    tool_name: </span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">str</span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">  #&lt;--must be a string = 'tool_browser'</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    tool_input: </span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">dict</span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"> #&lt;--must be a dictionary = {'q':'September 9 2024 deaths'}</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    tool_output: </span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">str</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> |</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> None</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> =</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> None</span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"> #can be a string or None, default = None</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    </span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">    @</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">classmethod</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> from_llm</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E5C07B;--shiki-dark-font-style:italic\">cls</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> res</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">dict</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">): </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">#&lt;--return the class itself</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        try</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">            out </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> json.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">loads</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(res[</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"message\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">][</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"content\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">])</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">            return</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\"> cls</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">tool_name</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">out[</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"name\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">], </span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">tool_input</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">out[</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"parameters\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">])</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        except</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#ABB2BF\"> Exception</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> as</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> e:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">            print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">f</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"Error from Ollama:</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">\\n</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">{</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">res</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">}</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">\\n</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">            raise</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> e</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># test</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">agent_res </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> AgentRes.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">from_llm</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(llm_res)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"from</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">\\n</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, llm_res[</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"message\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">][</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"content\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">], </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">\\n</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">to\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">agent_res</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div><div class=\"collapsed-lines\"></div></div><figure><figcaption></figcaption></figure>\n<p>The tool output can be added as such:</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># test the tool output</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">AgentRes</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">tool_name</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> =</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> \"tool_browser\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span></span>\n<span class=\"line\"><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">         tool_input</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> =</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'q'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'September 9 2024 deaths'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">}, </span></span>\n<span class=\"line\"><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">         tool_output</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\"> =</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> str</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">( </span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">tool_browser</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">({</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'q'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'September 9 2024 deaths'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">})) )</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><figure><figcaption></figcaption></figure>\n<p>The model can already understand if and when to use the tool, but we can make it even smarter by adding a <strong>Memory System</strong>. That shall include relevant information from the chat history and a reminder of the original request from the user.</p>\n<div class=\"language-python line-numbers-mode has-collapsed-lines collapsed\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--vp-collapsed-lines:15;--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'''</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">Messages in Memory will have this structure:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">[{'role':'assistant', 'content':'{\"name\":\"final_answer\", \"parameters\":{\"text\":\"How can I assist you today?\"}}'},</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> {'role':'user', 'content':None}]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'''</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> save_memory</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">lst_res</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span><span style=\"--shiki-light:#986801;--shiki-dark:#ABB2BF\">list[AgentRes]</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> user_q</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">str</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">) -&gt; </span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">list</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">    ## create</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    memory </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> []</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> res </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> [res </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> res </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> lst_res </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> res.tool_output </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">is</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> not</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> None</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">        memory.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">extend</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">([</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">            ### assistant message</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">            {</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"role\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"assistant\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"content\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: json.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">dumps</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">({</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"name\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:res.tool_name, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"parameters\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:res.tool_input})},</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">            ### user message</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">            {</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"role\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"user\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"content\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:res.tool_output}</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">        ])</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    </span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">    ## add a reminder of the original goal</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> memory:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">        memory </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> [{</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"role\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"user\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"content\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:(</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">f</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'''</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">                This is just a reminder that my original query was `</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">{</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">user_q</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">}</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">`.</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">                Only answer to the original query, and nothing else, but use the information I gave you. </span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">                Provide as much information as possible when you use the `final_answer` tool.</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">                '''</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)}]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> memory</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div><div class=\"collapsed-lines\"></div></div><p>As for the chat history, I’m going to add also a piece of a simulated conversation, just to make sure the Agent understands what I want.</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">history</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">[{</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"role\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"user\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"content\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"hi there, how are you?\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">},</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">         {</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"role\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"assistant\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"content\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"I'm good, thanks!\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">},</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">         {</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"role\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"user\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"content\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"I have a question\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">},</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">         {</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"role\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"assistant\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"content\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"tell me\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">}]</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>Now, we can put it all together to <strong>create the Agent</strong>.</p>\n<div class=\"language-python line-numbers-mode has-collapsed-lines collapsed\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--vp-collapsed-lines:15;--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> run_agent</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">user_q</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">str</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> chat_history</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span><span style=\"--shiki-light:#986801;--shiki-dark:#ABB2BF\">list[</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">dict</span><span style=\"--shiki-light:#986801;--shiki-dark:#ABB2BF\">]</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> lst_res</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span><span style=\"--shiki-light:#986801;--shiki-dark:#ABB2BF\">list[AgentRes]</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\"> lst_tools</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">list</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">) -&gt; AgentRes:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">    ## start memory</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    memory </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> save_memory</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">lst_res</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">lst_res, </span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">user_q</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">user_q)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    </span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">    ## track used tools</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> memory:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">        tools_used </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> [res.tool_name </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">for</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> res </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">in</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> lst_res]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">        if</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(tools_used) </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">&gt;=</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> len</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(lst_tools):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">            memory[</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">-</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">1</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">][</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"content\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">] </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> \"You must now use the `final_answer` tool.\"</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">        </span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">    ## messages</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    messages </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> [{</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"role\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"system\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"content\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:prompt</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">\\n</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">+</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">prompt_tools},</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">                *</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">chat_history,</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">                {</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"role\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"user\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"content\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:user_q},</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">                *</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">memory]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">    pprint</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(messages) </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">#&lt;--print to see prompt + tools + chat_history</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    </span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">    ## output</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    llm_res </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> ollama.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">chat</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">model</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">llm, </span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">messages</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">messages, </span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">format</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"json\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> AgentRes.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">from_llm</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(llm_res)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># test</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">agent_res </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> run_agent</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">user_q</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">q, </span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">chat_history</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">chat_history, </span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">lst_res</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">[], </span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">lst_tools</span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">dic_tools.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\">keys</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">())</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">\\n</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">agent_res:\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, agent_res)</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div><div class=\"collapsed-lines\"></div></div><figure><figcaption></figcaption></figure>\n<p>As you can see, our Agent is started up with the prompt + the available tools + the chat history.</p>\n<h2>Graph Workflow</h2>\n<p><em>LangGraph</em> is an orchestration framework that enables more control over the Agent workflows. One of the key concepts is the <strong>State</strong>: each execution creates a dictionary that is passed between nodes in the graph and gets updated every time with the output of the node.</p>\n<p>We define the initial state using <a href=\"https://docs.python.org/3/library/typing.html#\" target=\"_blank\" rel=\"noopener noreferrer\"><em>Typing</em></a>, the Python library to play with data types.</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">import</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> typing</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">class</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> State</span><span style=\"--shiki-light:#C18401;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">typing</span><span style=\"--shiki-light:#C18401;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">TypedDict</span><span style=\"--shiki-light:#C18401;--shiki-dark:#ABB2BF\">)</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    user_q: </span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">str</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    chat_history: </span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">list</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> </span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    lst_res: list[AgentRes]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    output: </span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">dict</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># test</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">state </span><span style=\"--shiki-light:#383A42;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#383A42;--shiki-dark:#61AFEF\"> State</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">({</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"user_q\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:q, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"chat_history\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:chat_history, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"lst_res\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:[agent_res], </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"output\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:{}})</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">state</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><figure><figcaption></figcaption></figure>\n<p>For each node (Agent and Tools) and each edge (action), we need to write a function to define the model behavior. Let’s start with the <strong>Agent node</strong> (for now just one):</p>\n<div class=\"language-python line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"python\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-python\"><span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># Agent</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">def</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> node_agent</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic\">state</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">):</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">    print</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div>",
      "date_published": "2025-03-04T18:18:02.000Z",
      "date_modified": "2025-04-10T23:49:50.000Z",
      "authors": [
        {
          "name": "AI悦创"
        }
      ],
      "tags": []
    },
    {
      "title": "Data",
      "url": "https://bornforthis.cn/column/video_loging/data.html",
      "id": "https://bornforthis.cn/column/video_loging/data.html",
      "summary": "1. 发布信息",
      "content_html": "<h2>1. 发布信息</h2>\n\n",
      "date_published": "2025-03-03T18:47:55.000Z",
      "date_modified": "2025-04-10T23:49:50.000Z",
      "authors": [
        {
          "name": "AI悦创"
        }
      ],
      "tags": []
    }
  ]
}